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]);
}
elseif (
!in_array($id, $nonLegacyDateFields) && (
- preg_match('/_date_relative$/', $id) ||
- $id == 'event_relative')
+ preg_match('/_date_relative$/', $id))
) {
// Already handled in previous loop
continue;
* @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;
$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\"";
}
$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]}'";
// 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]),
* @param $values
*
* @return bool
+ * @throws \CRM_Core_Exception
*/
public function buildDateRangeQuery($values) {
if ($this->isADateRangeField($values[0])) {
$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);
}
/**
/**
* @param $values
- * @param $query
+ * @param \CRM_Contact_BAO_Query $query
*/
public static function whereClauseSingle(&$values, &$query) {
$checkPermission = empty($query->_skipPermission);
$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,
$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));
}
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',
}
/**
- * 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'],
+ ];
}
}