From be588106b8a4295d752f89949c6507b9dd524e30 Mon Sep 17 00:00:00 2001 From: Aidan Saunders Date: Wed, 28 Feb 2018 11:59:11 +0000 Subject: [PATCH] CRM-21816: Fix relative dates dropping other search conditions Using unset() within a foreach loop can cause elements to be skipped from the iteration. See https://wiki.php.net/rfc/php7_foreach#introduction for an example. --- CRM/Contact/BAO/Query.php | 71 +++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/CRM/Contact/BAO/Query.php b/CRM/Contact/BAO/Query.php index ac156fdf3a..bba79e2632 100644 --- a/CRM/Contact/BAO/Query.php +++ b/CRM/Contact/BAO/Query.php @@ -1559,6 +1559,42 @@ class CRM_Contact_BAO_Query { self::filterCountryFromValuesIfStateExists($formValues); + // Handle relative dates first + foreach (array_keys($formValues) as $id) { + if (preg_match('/_date_relative$/', $id) || + $id == 'event_relative' || + $id == 'case_from_relative' || + $id == 'case_to_relative' || + $id == 'participant_relative' + ) { + if ($id == 'event_relative') { + $fromRange = 'event_start_date_low'; + $toRange = 'event_end_date_high'; + } + elseif ($id == 'participant_relative') { + $fromRange = 'participant_register_date_low'; + $toRange = 'participant_register_date_high'; + } + elseif ($id == 'case_from_relative') { + $fromRange = 'case_from_start_date_low'; + $toRange = 'case_from_start_date_high'; + } + elseif ($id == 'case_to_relative') { + $fromRange = 'case_to_end_date_low'; + $toRange = 'case_to_end_date_high'; + } + else { + $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]); + } + } + } + foreach ($formValues as $id => &$val) { // CRM-19374 - we don't want to change $val in $formValues. // Assign it to a temp variable which operates while iteration. @@ -1618,39 +1654,8 @@ class CRM_Contact_BAO_Query { $id == 'case_to_relative' || $id == 'participant_relative' ) { - if ($id == 'event_relative') { - $fromRange = 'event_start_date_low'; - $toRange = 'event_end_date_high'; - } - elseif ($id == 'participant_relative') { - $fromRange = 'participant_register_date_low'; - $toRange = 'participant_register_date_high'; - } - elseif ($id == 'case_from_relative') { - $fromRange = 'case_from_start_date_low'; - $toRange = 'case_from_start_date_high'; - } - elseif ($id == 'case_to_relative') { - $fromRange = 'case_to_end_date_low'; - $toRange = 'case_to_end_date_high'; - } - else { - $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)) { - // relative dates are not processed correctly as lower date value were ignored, - // to ensure both high and low date value got added IF there is relative date, - // we need to reset $formValues by unset and then adding again via CRM_Contact_BAO_Query::fixDateValues(...) - if (!empty($formValues[$id])) { - unset($formValues[$fromRange]); - unset($formValues[$toRange]); - } - CRM_Contact_BAO_Query::fixDateValues($formValues[$id], $formValues[$fromRange], $formValues[$toRange]); - continue; - } + // Already handled in previous loop + continue; } elseif (in_array($id, $entityReferenceFields) && !empty($values) && is_string($values) && (strpos($values, ',') != FALSE)) { -- 2.25.1