dev/core#2846 Towards validation of start and end dates. Forms.
authorJohn Kingsnorth <john@johnkingsnorth.co.uk>
Fri, 17 Sep 2021 11:26:52 +0000 (12:26 +0100)
committerJohn Kingsnorth <john@johnkingsnorth.co.uk>
Fri, 17 Sep 2021 11:26:52 +0000 (12:26 +0100)
CRM/Campaign/Form/Campaign.php
CRM/Contribute/Form/ContributionPage/Settings.php
CRM/Event/Form/ManageEvent/EventInfo.php
CRM/Event/Form/ManageEvent/Registration.php
CRM/Price/Form/Field.php
CRM/Utils/Date.php

index e558d4502bba90999031c2af9a20d176ecb02515..d3923324a6f05c3ec1cdbae89afc9d4e1d308271 100644 (file)
@@ -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;
   }
 
index f9adcb47c9bea3541cc7af6ccfad050d02d97e89..008b99fb1046e36a15ddac194f77ca10f075e650 100644 (file)
@@ -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'])) {
index 9e1c5dfbf3068ce19c7e0d179761cb1ec0ce8972..3bb85e3c478cf22898121be1ca18c6f33bd152fb 100644 (file)
@@ -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
index 16fcd9c3f5d5c50e49e98aac5f0e6da284fa803b..40ef0d402f1015abd1d645654772103388abfc0b 100644 (file)
@@ -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
index 3b1170e833e3693a6c924c193ea322696edc1e41..1e295f8698e4626352f974ebd82601345b5af41f 100644 (file)
@@ -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;
index 632eb4910bbafd25080a7d9159f8f849615df7e7..beeb8e630da5bd13f3a9611e6c40c8b903091bb3 100644 (file)
@@ -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;
+  }
+
 }