From: aydun Date: Tue, 24 Mar 2015 10:16:12 +0000 (+0000) Subject: CRM-16160: Changes to add search by age to Advanced Search X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=c4a7c96745401d557a8ac29ad665a9fa93a5e59e;p=civicrm-core.git CRM-16160: Changes to add search by age to Advanced Search --- diff --git a/CRM/Contact/BAO/Query.php b/CRM/Contact/BAO/Query.php index 1cd5f00faf..ff7f82dddd 100644 --- a/CRM/Contact/BAO/Query.php +++ b/CRM/Contact/BAO/Query.php @@ -1767,6 +1767,8 @@ class CRM_Contact_BAO_Query { CRM_Activity_BAO_Query::whereClauseSingle($values, $this); return; + case 'age_low': + case 'age_high': case 'birth_date_low': case 'birth_date_high': case 'deceased_date_low': @@ -1774,6 +1776,10 @@ class CRM_Contact_BAO_Query { $this->demographics($values); return; + case 'age_asof_date': + // handled by demographics + return; + case 'log_date_low': case 'log_date_high': $this->modifiedDates($values); @@ -3869,7 +3875,12 @@ WHERE id IN ( $groupIDs ) public function demographics(&$values) { list($name, $op, $value, $grouping, $wildcard) = $values; - if (($name == 'birth_date_low') || ($name == 'birth_date_high')) { + if (($name == 'age_low') || ($name == 'age_high')) { + $this->ageRangeQueryBuilder($values, + 'contact_a', 'age', 'birth_date', ts('Age') + ); + } + elseif (($name == 'birth_date_low') || ($name == 'birth_date_high')) { $this->dateQueryBuilder($values, 'contact_a', 'birth_date', 'birth_date', ts('Birth Date') @@ -5137,6 +5148,104 @@ SELECT COUNT( conts.total_amount ) as cancel_count, } } + + /** + * @param $values + * @param string $tableName + * @param string $fieldName + * @param string $dbFieldName + * @param $fieldTitle + * @param null $options + */ + public function ageRangeQueryBuilder( + &$values, + $tableName, $fieldName, + $dbFieldName, $fieldTitle, + $options = NULL + ) { + list($name, $op, $value, $grouping, $wildcard) = $values; + + $asofDateValues = $this->getWhereValues("{$fieldName}_asof_date", $grouping); + $asofDate = NULL; // will be treated as current day + if ($asofDateValues) { + $asofDate = CRM_Utils_Date::processDate($asofDateValues[2]); + $asofDateFormat = CRM_Utils_Date::customFormat(substr($asofDate, 0, 8)); + $fieldTitle .= ' ' . ts('as of') . ' ' . $asofDateFormat; + } + + if ($name == "{$fieldName}_low" || + $name == "{$fieldName}_high" + ) { + if (isset($this->_rangeCache[$fieldName])) { + return; + } + $this->_rangeCache[$fieldName] = 1; + + $secondOP = $secondPhrase = $secondValue = NULL; + + if ($name == "{$fieldName}_low") { + $firstPhrase = ts('greater than or equal to'); + // NB: age > X means date of birth < Y + $firstOP = '<='; + $firstDate = self::calcDateFromAge($asofDate, $value, 'min'); + + $secondValues = $this->getWhereValues("{$fieldName}_high", $grouping); + if (!empty($secondValues)) { + $secondOP = '>='; + $secondPhrase = ts('less than or equal to'); + $secondValue = $secondValues[2]; + $secondDate = self::calcDateFromAge($asofDate, $secondValue, 'max'); + } + } + else { + $firstOP = '>='; + $firstPhrase = ts('less than or equal to'); + $firstDate = self::calcDateFromAge($asofDate, $value, 'max'); + + $secondValues = $this->getWhereValues("{$fieldName}_low", $grouping); + if (!empty($secondValues)) { + $secondOP = '<='; + $secondPhrase = ts('greater than or equal to'); + $secondValue = $secondValues[2]; + $secondDate = self::calcDateFromAge($asofDate, $secondValue, 'min'); + } + } + + + if ($secondOP) { + $this->_where[$grouping][] = " +( {$tableName}.{$dbFieldName} $firstOP '$firstDate' ) AND +( {$tableName}.{$dbFieldName} $secondOP '$secondDate' ) +"; + $displayValue = $options ? $options[$value] : $value; + $secondDisplayValue = $options ? $options[$secondValue] : $secondValue; + + $this->_qill[$grouping][] + = "$fieldTitle - $firstPhrase \"$displayValue\" " . ts('AND') . " $secondPhrase \"$secondDisplayValue\""; + } + else { + $this->_where[$grouping][] = "{$tableName}.{$dbFieldName} $firstOP '$firstDate'"; + $displayValue = $options ? $options[$value] : $value; + $this->_qill[$grouping][] = "$fieldTitle - $firstPhrase \"$displayValue\""; + } + $this->_tables[$tableName] = $this->_whereTables[$tableName] = 1; + return; + } + } + + public static function calcDateFromAge($asofDate, $age, $type) { + $date = new DateTime($asofDate); + if ($type == "min") { + // minimum age is $age: dob <= date - age "235959" + $date->sub(new DateInterval("P" . $age . "Y")); + return $date->format('Ymd') . "235959"; + } else { + // max age is $age: dob >= date - (age + 1y) + 1d "000000" + $date->sub(new DateInterval("P" . ($age + 1) . "Y"))->add(new DateInterval("P1D")); + return $date->format('Ymd') . "000000"; + } + } + /** * Given the field name, operator, value & its data type * builds the where Clause for the query diff --git a/CRM/Contact/Form/Search/Criteria.php b/CRM/Contact/Form/Search/Criteria.php index 995b415892..86b2dc286a 100644 --- a/CRM/Contact/Form/Search/Criteria.php +++ b/CRM/Contact/Form/Search/Criteria.php @@ -489,6 +489,12 @@ class CRM_Contact_Form_Search_Criteria { } $form->addGroup($genderOptions, 'gender_id', ts('Gender'))->setAttribute('allowClear', TRUE); + $form->add('text', 'age_low', ts('Min Age')); + $form->addRule('age_low', ts('Please enter a positive integer'), 'positiveInteger'); + $form->add('text', 'age_high', ts('Max Age')); + $form->addRule('age_high', ts('Please enter a positive integer'), 'positiveInteger'); + $form->addDate('age_asof_date', ts('Age as of Date'), FALSE, array('formatType' => 'searchDate')); + CRM_Core_Form_Date::buildDateRange($form, 'birth_date', 1, '_low', '_high', ts('From'), FALSE, FALSE, 'birth'); CRM_Core_Form_Date::buildDateRange($form, 'deceased_date', 1, '_low', '_high', ts('From'), FALSE, FALSE, 'birth'); diff --git a/templates/CRM/Contact/Form/Search/Criteria/Demographics.tpl b/templates/CRM/Contact/Form/Search/Criteria/Demographics.tpl index b4fe33a430..9548d5acf2 100644 --- a/templates/CRM/Contact/Form/Search/Criteria/Demographics.tpl +++ b/templates/CRM/Contact/Form/Search/Criteria/Demographics.tpl @@ -30,8 +30,12 @@ {include file="CRM/Core/DateRange.tpl" fieldName="birth_date" from='_low' to='_high'} - - {$form.is_deceased.label}
+ + {include file="CRM/Core/AgeRange.tpl" fieldName="age" from='_low' to='_high' date='_asof_date'} + + + + {$form.is_deceased.label}
{$form.is_deceased.html} diff --git a/templates/CRM/Core/AgeRange.tpl b/templates/CRM/Core/AgeRange.tpl new file mode 100644 index 0000000000..a56f2971ea --- /dev/null +++ b/templates/CRM/Core/AgeRange.tpl @@ -0,0 +1,58 @@ +{* + +--------------------------------------------------------------------+ + | CiviCRM version 4.6 | + +--------------------------------------------------------------------+ + | Copyright CiviCRM LLC (c) 2004-2014 | + +--------------------------------------------------------------------+ + | This file is a part of CiviCRM. | + | | + | CiviCRM is free software; you can copy, modify, and distribute it | + | under the terms of the GNU Affero General Public License | + | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | + | | + | CiviCRM is distributed in the hope that it will be useful, but | + | WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | + | See the GNU Affero General Public License for more details. | + | | + | You should have received a copy of the GNU Affero General Public | + | License and the CiviCRM Licensing Exception along | + | with this program; if not, contact CiviCRM LLC | + | at info[AT]civicrm[DOT]org. If you have questions about the | + | GNU Affero General Public License or the licensing of CiviCRM, | + | see the CiviCRM license FAQ at http://civicrm.org/licensing | + +--------------------------------------------------------------------+ +*} +{*this is included inside a table row*} + + + + {assign var=minName value=$fieldName|cat:$from} + {$form.$minName.label} + {$form.$minName.html} + + + {assign var=maxName value=$fieldName|cat:$to} + {$form.$maxName.label} + {$form.$maxName.html} + + + + + + {assign var=dateName value=$fieldName|cat:$date} + {$form.$dateName.label} + {include file="CRM/common/jcalendar.tpl" elementName=$dateName} + + {literal} + + {/literal} +