From 95942234874b0720955f91c502e7a121f5a21349 Mon Sep 17 00:00:00 2001 From: John Kingsnorth Date: Fri, 17 Sep 2021 12:26:52 +0100 Subject: [PATCH] dev/core#2846 Towards validation of start and end dates. Forms. --- CRM/Campaign/Form/Campaign.php | 8 +++ .../Form/ContributionPage/Settings.php | 9 ++-- CRM/Event/Form/ManageEvent/EventInfo.php | 6 ++- CRM/Event/Form/ManageEvent/Registration.php | 8 +-- CRM/Price/Form/Field.php | 6 +++ CRM/Utils/Date.php | 53 +++++++++++++++++++ 6 files changed, 79 insertions(+), 11 deletions(-) diff --git a/CRM/Campaign/Form/Campaign.php b/CRM/Campaign/Form/Campaign.php index e558d4502b..d3923324a6 100644 --- a/CRM/Campaign/Form/Campaign.php +++ b/CRM/Campaign/Form/Campaign.php @@ -249,6 +249,8 @@ class CRM_Campaign_Form_Campaign extends CRM_Core_Form { ]; $this->addButtons($buttons); + + $this->addFormRule(['CRM_Campaign_Form_Campaign', 'formRule']); } /** @@ -265,6 +267,12 @@ class CRM_Campaign_Form_Campaign extends CRM_Core_Form { public static function formRule($fields, $files, $errors) { $errors = []; + // Validate start/end date inputs + $validateDates = \CRM_Utils_Date::validateStartEndDatepickerInputs('start_date', $fields['start_date'], 'end_date', $fields['end_date']); + if ($validateDates !== TRUE) { + $errors[$validateDates['key']] = $validateDates['message']; + } + return empty($errors) ? TRUE : $errors; } diff --git a/CRM/Contribute/Form/ContributionPage/Settings.php b/CRM/Contribute/Form/ContributionPage/Settings.php index f9adcb47c9..008b99fb10 100644 --- a/CRM/Contribute/Form/ContributionPage/Settings.php +++ b/CRM/Contribute/Form/ContributionPage/Settings.php @@ -252,11 +252,10 @@ class CRM_Contribute_Form_ContributionPage_Settings extends CRM_Contribute_Form_ } } - //CRM-11494 - $start = CRM_Utils_Date::processDate($values['start_date']); - $end = CRM_Utils_Date::processDate($values['end_date']); - if (($end < $start) && ($end != 0)) { - $errors['end_date'] = ts('End date should be after Start date.'); + // Validate start/end date inputs + $validateDates = \CRM_Utils_Date::validateStartEndDatepickerInputs('start_date', $values['start_date'], 'end_date', $values['end_date']); + if ($validateDates !== TRUE) { + $errors[$validateDates['key']] = $validateDates['message']; } if (!empty($self->_values['payment_processor']) && $financialType = CRM_Contribute_BAO_Contribution::validateFinancialType($values['financial_type_id'])) { diff --git a/CRM/Event/Form/ManageEvent/EventInfo.php b/CRM/Event/Form/ManageEvent/EventInfo.php index 9e1c5dfbf3..3bb85e3c47 100644 --- a/CRM/Event/Form/ManageEvent/EventInfo.php +++ b/CRM/Event/Form/ManageEvent/EventInfo.php @@ -196,8 +196,10 @@ class CRM_Event_Form_ManageEvent_EventInfo extends CRM_Event_Form_ManageEvent { public static function formRule($values) { $errors = []; - if (!empty($values['end_date']) && ($values['end_date'] < $values['start_date'])) { - $errors['end_date'] = ts('End date should be after Start date.'); + // Validate start/end date inputs + $validateDates = \CRM_Utils_Date::validateStartEndDatepickerInputs('start_date', $values['start_date'], 'end_date', $values['end_date']); + if ($validateDates !== TRUE) { + $errors[$validateDates['key']] = $validateDates['message']; } //CRM-4286 diff --git a/CRM/Event/Form/ManageEvent/Registration.php b/CRM/Event/Form/ManageEvent/Registration.php index 16fcd9c3f5..40ef0d402f 100644 --- a/CRM/Event/Form/ManageEvent/Registration.php +++ b/CRM/Event/Form/ManageEvent/Registration.php @@ -460,10 +460,10 @@ class CRM_Event_Form_ManageEvent_Registration extends CRM_Event_Form_ManageEvent } } - if (isset($values['registration_start_date']) && isset($values['registration_end_date'])) { - if ($values['registration_end_date'] < $values['registration_start_date']) { - $errorMsg['registration_end_date'] = ts('Registration end date should be after Registration start date'); - } + // Validate start/end date inputs + $validateDates = \CRM_Utils_Date::validateStartEndDatepickerInputs('registration_start_date', $values['registration_start_date'], 'registration_end_date', $values['registration_end_date']); + if ($validateDates !== TRUE) { + $errorMsg[$validateDates['key']] = $validateDates['message']; } //check that the selected profiles have either firstname+lastname or email required diff --git a/CRM/Price/Form/Field.php b/CRM/Price/Form/Field.php index 3b1170e833..1e295f8698 100644 --- a/CRM/Price/Form/Field.php +++ b/CRM/Price/Form/Field.php @@ -449,6 +449,12 @@ class CRM_Price_Form_Field extends CRM_Core_Form { $errors['count'] = ts('Participant Count must be greater than zero.'); } + // Validate start/end date inputs + $validateDates = \CRM_Utils_Date::validateStartEndDatepickerInputs('active_on', $fields['active_on'], 'expire_on', $fields['expire_on']); + if ($validateDates !== TRUE) { + $errors[$validateDates['key']] = $validateDates['message']; + } + if ($form->_action & CRM_Core_Action::ADD) { if ($fields['html_type'] != 'Text') { $countemptyrows = 0; diff --git a/CRM/Utils/Date.php b/CRM/Utils/Date.php index 632eb4910b..beeb8e630d 100644 --- a/CRM/Utils/Date.php +++ b/CRM/Utils/Date.php @@ -2223,4 +2223,57 @@ class CRM_Utils_Date { return $dateObject->format($format); } + /** + * Check if the value returned by a date picker has a date section (ie: includes + * a '-' character) if it includes a time section (ie: includes a ':'). + * + * @param string $value + * A date/time string input from a datepicker value. + * + * @return bool + * TRUE if valid, FALSE if there is a time without a date. + */ + public static function datePickerValueWithTimeHasDate($value) { + // If there's no : (time) or a : and a - (date) then return true + return ( + strpos($value, ':') === FALSE + || strpos($value, ':') !== FALSE && strpos($value, '-') !== FALSE + ); + } + + /** + * Validate start and end dates entered on a form to make sure they are + * logical. Expects the form keys to be start_date and end_date. + * + * @param string $startFormKey + * The form element key of the 'start date' + * @param string $startValue + * The value of the 'start date' + * @param string $endFormKey + * The form element key of the 'end date' + * @param string $endValue + * The value of the 'end date' + * + * @return array|bool + * TRUE if valid, an array of the erroneous form key, and error message to + * use otherwise. + */ + public static function validateStartEndDatepickerInputs($startFormKey, $startValue, $endFormKey, $endValue) { + + // Check date as well as time is set + if (!empty($startValue) && !self::datePickerValueWithTimeHasDate($startValue)) { + return ['key' => $startFormKey, 'message' => ts('Please enter a date as well as a time.')]; + } + if (!empty($endValue) && !self::datePickerValueWithTimeHasDate($endValue)) { + return ['key' => $endFormKey, 'message' => ts('Please enter a date as well as a time.')]; + } + + // Check end date is after start date + if (!empty($startValue) && !empty($endValue) && $endValue < $startValue) { + return ['key' => $endFormKey, 'message' => ts('The end date should be after the start date.')]; + } + + return TRUE; + } + } -- 2.25.1