Jcalendar replacement for event date
authoreileen <emcnaughton@wikimedia.org>
Wed, 30 Oct 2019 06:45:36 +0000 (19:45 +1300)
committereileen <emcnaughton@wikimedia.org>
Thu, 31 Oct 2019 07:17:06 +0000 (20:17 +1300)
CRM/Contact/BAO/Query.php
CRM/Contact/BAO/SavedSearch.php
CRM/Event/BAO/Query.php
templates/CRM/Event/Form/Search/Common.tpl
tests/phpunit/api/v3/ContactTest.php

index d67f250dc038f58c391975b22803d74edab61185..ed641932bc9132bd85142f959b18d308e22c11ca 100644 (file)
@@ -1613,18 +1613,11 @@ class CRM_Contact_BAO_Query {
     foreach (array_keys($formValues) as $id) {
       if (
         !in_array($id, $nonLegacyDateFields) && (
-        preg_match('/_date_relative$/', $id) ||
-        $id == 'event_relative')
+        preg_match('/_date_relative$/', $id))
       ) {
-        if ($id == 'event_relative') {
-          $fromRange = 'event_start_date_low';
-          $toRange = 'event_end_date_high';
-        }
-        else {
-          $dateComponent = explode('_date_relative', $id);
-          $fromRange = "{$dateComponent[0]}_date_low";
-          $toRange = "{$dateComponent[0]}_date_high";
-        }
+        $dateComponent = explode('_date_relative', $id);
+        $fromRange = "{$dateComponent[0]}_date_low";
+        $toRange = "{$dateComponent[0]}_date_high";
 
         if (array_key_exists($fromRange, $formValues) && array_key_exists($toRange, $formValues)) {
           CRM_Contact_BAO_Query::fixDateValues($formValues[$id], $formValues[$fromRange], $formValues[$toRange]);
@@ -1690,8 +1683,7 @@ class CRM_Contact_BAO_Query {
       }
       elseif (
         !in_array($id, $nonLegacyDateFields) && (
-          preg_match('/_date_relative$/', $id) ||
-          $id == 'event_relative')
+          preg_match('/_date_relative$/', $id))
       ) {
         // Already handled in previous loop
         continue;
@@ -5277,12 +5269,20 @@ civicrm_relationship.start_date > {$today}
    * @param string $fieldTitle
    * @param bool $appendTimeStamp
    * @param string $dateFormat
+   * @param string|null $highDBFieldName
+   *   Optional field name for when the 'high' part of the calculation uses a different field than the 'low' part.
+   *   This is an obscure situation & one we don't want to do more of but supporting them here is the only way for now.
+   *   Examples are event date & relationship active date -in both cases we are looking for things greater than the start
+   *   date & less than the end date.
+   *
+   * @throws \CRM_Core_Exception
    */
   public function dateQueryBuilder(
     $values, $tableName, $fieldName,
     $dbFieldName, $fieldTitle,
     $appendTimeStamp = TRUE,
-    $dateFormat = 'YmdHis'
+    $dateFormat = 'YmdHis',
+    $highDBFieldName = NULL
   ) {
     // @todo - remove dateFormat - pretty sure it's never passed in...
     list($name, $op, $value, $grouping, $wildcard) = $values;
@@ -5346,9 +5346,10 @@ civicrm_relationship.start_date > {$today}
 
       $this->_tables[$tableName] = $this->_whereTables[$tableName] = 1;
       if ($secondDate) {
+        $highDBFieldName = $highDBFieldName ?? $dbFieldName;
         $this->_where[$grouping][] = "
 ( {$tableName}.{$dbFieldName} $firstOP '$firstDate' ) AND
-( {$tableName}.{$dbFieldName} $secondOP '$secondDate' )
+( {$tableName}.{$highDBFieldName} $secondOP '$secondDate' )
 ";
         $this->_qill[$grouping][] = "$fieldTitle - $firstPhrase \"$firstDateFormat\" " . ts('AND') . " $secondPhrase \"$secondDateFormat\"";
       }
@@ -7044,15 +7045,18 @@ AND   displayRelType.is_active = 1
     $this->_whereTables[$tableName] = $this->_whereTables[$tableName] ?? 1;
 
     $dates = CRM_Utils_Date::getFromTo($value, NULL, NULL);
+    // Where end would be populated only if we are handling one of the weird ones with different from & to fields.
+    $secondWhere = $fieldSpec['where_end'] ?? $fieldSpec['where'];
     if (empty($dates[0])) {
       // ie. no start date we only have end date
-      $this->_where[$grouping][] = $fieldSpec['where'] . " <= '{$dates[1]}'";
+      $this->_where[$grouping][] = $secondWhere . " <= '{$dates[1]}'";
 
       $this->_qill[$grouping][] = ts('%1 is ', [$fieldSpec['title']]) . $filters[$value] . ' (' . ts("to %1", [
         CRM_Utils_Date::customFormat($dates[1]),
       ]) . ')';
     }
     elseif (empty($dates[1])) {
+
       // ie. no end date we only have start date
       $this->_where[$grouping][] = $fieldSpec['where'] . " >= '{$dates[1]}'";
 
@@ -7067,7 +7071,12 @@ AND   displayRelType.is_active = 1
         // Special handling for contact table as it has a known alias in advanced search.
         $where = str_replace('civicrm_contact.', 'contact_a.', $where);
       }
-      $this->_where[$grouping][] = $where . " BETWEEN '{$dates[0]}' AND '{$dates[1]}'";
+      if ($secondWhere !== $fieldSpec['where']) {
+        $this->_where[$grouping][] = $fieldSpec['where'] . ">=  '{$dates[0]}' AND $secondWhere <='{$dates[1]}'";
+      }
+      else {
+        $this->_where[$grouping][] = $where . " BETWEEN '{$dates[0]}' AND '{$dates[1]}'";
+      }
 
       $this->_qill[$grouping][] = ts('%1 is ', [$fieldSpec['title']]) . $filters[$value] . ' (' . ts("between %1 and %2", [
         CRM_Utils_Date::customFormat($dates[0]),
@@ -7082,6 +7091,7 @@ AND   displayRelType.is_active = 1
    * @param $values
    *
    * @return bool
+   * @throws \CRM_Core_Exception
    */
   public function buildDateRangeQuery($values) {
     if ($this->isADateRangeField($values[0])) {
index 67a61350bac3712dbfc9abe056201472cee2a54f..414de20abc57a49a793797df7393645487815c21 100644 (file)
@@ -398,7 +398,6 @@ LEFT JOIN civicrm_email ON (contact_a.id = civicrm_email.contact_id AND civicrm_
     // form format and simply saves (e.g) custom_3_relative => "this.year"
     $relativeDates = ['relative_dates' => []];
     $specialDateFields = [
-      'event_relative',
       'log_date_relative',
       'relation_action_date_relative',
     ];
index 03d83044cb10a789dc7d595ae84291588fb7d344..d3caf5328007ac95321f7f87afcf9486b21a2470 100644 (file)
@@ -47,16 +47,15 @@ class CRM_Event_BAO_Query extends CRM_Core_BAO_Query {
     $fields = array_merge($fields, CRM_Event_DAO_Event::import());
     $fields = array_merge($fields, self::getParticipantFields());
     $fields = array_merge($fields, CRM_Core_DAO_Discount::export());
-
+    $fields['event'] = self::getPseudoEventDateFieldMetadata();
     return $fields;
   }
 
   /**
    * @return array
    */
-  public static function &getParticipantFields() {
-    $fields = CRM_Event_BAO_Participant::importableFields('Individual', TRUE, TRUE);
-    return $fields;
+  public static function getParticipantFields() {
+    return CRM_Event_BAO_Participant::importableFields('Individual', TRUE, TRUE);
   }
 
   /**
@@ -249,7 +248,7 @@ class CRM_Event_BAO_Query extends CRM_Core_BAO_Query {
 
   /**
    * @param $values
-   * @param $query
+   * @param \CRM_Contact_BAO_Query $query
    */
   public static function whereClauseSingle(&$values, &$query) {
     $checkPermission = empty($query->_skipPermission);
@@ -257,6 +256,13 @@ class CRM_Event_BAO_Query extends CRM_Core_BAO_Query {
     $fields = array_merge(CRM_Event_BAO_Event::fields(), CRM_Event_BAO_Participant::exportableFields());
 
     switch ($name) {
+      case 'event_low':
+      case 'event_high':
+        $query->dateQueryBuilder($values,
+          'civicrm_event', 'event', 'start_date', ts('Event Active On'), TRUE, 'YmdHis', 'end_date'
+        );
+        return;
+
       case 'event_start_date_low':
       case 'event_start_date_high':
         $query->dateQueryBuilder($values,
@@ -584,8 +590,11 @@ class CRM_Event_BAO_Query extends CRM_Core_BAO_Query {
     $fields = [
       'participant_status_id',
       'participant_register_date',
+      // Super-weird but we have to make it work.....
+      'event',
     ];
     $metadata = civicrm_api3('Participant', 'getfields', [])['values'];
+    $metadata['event'] = self::getPseudoEventDateFieldMetadata();
     return array_intersect_key($metadata, array_flip($fields));
   }
 
@@ -628,11 +637,6 @@ class CRM_Event_BAO_Query extends CRM_Core_BAO_Query {
        FALSE, ['class' => 'crm-select2', 'multiple' => 'multiple', 'placeholder' => ts('- any -')]
     );
 
-    CRM_Core_Form_Date::buildDateRange($form, 'event', 1, '_start_date_low', '_end_date_high', ts('From'), FALSE);
-
-    $form->addElement('hidden', 'event_date_range_error');
-    $form->addFormRule(['CRM_Event_BAO_Query', 'formRule'], $form);
-
     $form->addElement('checkbox', "event_include_repeating_events", NULL, ts('Include participants from all events in the %1 series', [1 => '<em>%1</em>']));
 
     $form->addSelect('participant_role_id',
@@ -672,30 +676,20 @@ class CRM_Event_BAO_Query extends CRM_Core_BAO_Query {
   }
 
   /**
-   * Check if the values in the date range are in correct chronological order.
+   * Get metadata from pseudo search field 'event'.
    *
-   * @todo Get this to work with CRM_Utils_Rule::validDateRange
-   *
-   * @param array $fields
-   * @param array $files
-   * @param CRM_Core_Form $form
-   *
-   * @return bool|array
+   * @return array
    */
-  public static function formRule($fields, $files, $form) {
-    $errors = [];
-
-    if ((empty($fields['event_start_date_low']) || empty($fields['event_end_date_high']))) {
-      return TRUE;
-    }
-    $lowDate = strtotime($fields['event_start_date_low']);
-    $highDate = strtotime($fields['event_end_date_high']);
-
-    if ($lowDate > $highDate) {
-      $errors['event_date_range_error'] = ts('Please check that your Event Date Range is in correct chronological order.');
-    }
-
-    return empty($errors) ? TRUE : $errors;
+  protected static function getPseudoEventDateFieldMetadata(): array {
+    return [
+      'name' => 'event',
+      'type' => CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME,
+      'title' => ts('Event Active On'),
+      'table_name' => 'civicrm_event',
+      'where' => 'civicrm_event.start_date',
+      'where_end' => 'civicrm_event.end_date',
+      'html' => ['type' => 'SelectDate', 'formatType' => 'activityDateTime'],
+    ];
   }
 
 }
index c4a66740ebafcb12f31e1ae3a45ebdfdcf9c5bf8..1afbace0bc34aec8430bb2613618943b07cd62c2 100644 (file)
@@ -33,8 +33,7 @@
   <td class="crm-event-form-block-event_type_id"> {$form.event_type_id.label}<br />{$form.event_type_id.html} </td>
 </tr>
 <tr>
-  {include file="CRM/Core/DateRange.tpl" fieldName="event" from='_start_date_low' to='_end_date_high' label="<label>Event Dates</label>"}
-</tr>
+    {include file="CRM/Core/DatePickerRangeWrapper.tpl" fieldName="event" colspan="2"}</tr>
 <tr>
   {include file="CRM/Core/DatePickerRangeWrapper.tpl" fieldName="participant_register_date" colspan="2"}
 </tr>
index 03dd75effaf015c2ee917469ee6368d362fa17ff..b807fbc6df32b4e91099fbf65561a1e6aa461b48 100644 (file)
@@ -2120,6 +2120,8 @@ class api_v3_ContactTest extends CiviUnitTestCase {
 
   /**
    * Ensure consistent return format for option group fields.
+   *
+   * @throws \CRM_Core_Exception
    */
   public function testPseudoFields() {
     $params = [
@@ -2156,6 +2158,8 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * These include value, array & birth_date_high, birth_date_low
    * && deceased.
+   *
+   * @throws \CRM_Core_Exception
    */
   public function testContactGetBirthDate() {
     $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, ['birth_date' => 'first day of next month - 2 years']));