CRM-18125 remove country_id from filter where state_province_id is present
authoreileen <emcnaughton@wikimedia.org>
Tue, 1 Mar 2016 01:23:44 +0000 (14:23 +1300)
committereileen <emcnaughton@wikimedia.org>
Tue, 1 Mar 2016 17:33:12 +0000 (06:33 +1300)
The country_id is implcit in the state_province_id, but in the absence of a combined filter including it hurts performance

Change-Id: Ic311c4c438002e7390e2c0f7b21059bd26f618f3

CRM/Contact/BAO/Query.php
CRM/Contact/Form/Search/Advanced.php

index 7db2bafb4763cd1adef80a9835b23d401e76f2eb..f7b9fd4fea49ad7cd6425e0f319ee81d91ac0d7d 100644 (file)
@@ -1507,6 +1507,8 @@ class CRM_Contact_BAO_Query {
       return $params;
     }
 
+    self::filterCountryFromValuesIfStateExists($formValues);
+
     foreach ($formValues as $id => $values) {
 
       if (self::isAlreadyProcessedForQueryFormat($values)) {
@@ -4456,6 +4458,31 @@ civicrm_relationship.is_permission_a_b = 0
     return in_array($operator, CRM_Core_DAO::acceptedSQLOperators());
   }
 
+  /**
+   * If the state and country are passed remove state.
+   *
+   * Country is implicit from the state, but including both results in
+   * a poor query as there is no combined index on state AND country.
+   *
+   * CRM-18125
+   *
+   * @param array $formValues
+   */
+  public static function filterCountryFromValuesIfStateExists(&$formValues) {
+    if (!empty($formValues['country'])) {
+      if (isset($formValues['state_province'])) {
+        // The use of array map sanitises the data by ensuring we are dealing with integers.
+        $states = implode(', ', array_map('intval', $formValues['state_province']));
+        $countryList = CRM_Core_DAO::singleValueQuery(
+          "SELECT GROUP_CONCAT(country_id) FROM civicrm_state_province WHERE id IN ($states)"
+        );
+        if ($countryList == $formValues['country']) {
+          unset($formValues['country']);
+        }
+      }
+    }
+  }
+
   /**
    * Create and query the db for an contact search.
    *
index aca7d35e79cb7fc626241b41b9c3ca5a474f87b7..7c059e41c8091cdab7ac3195f760b7c709ea876b 100644 (file)
@@ -381,11 +381,29 @@ class CRM_Contact_Form_Search_Advanced extends CRM_Contact_Form_Search {
     if (!is_array($defaults)) {
       $defaults = array();
     }
-
+    $this->loadDefaultCountryBasedOnState($defaults);
     if ($this->_ssID && empty($_POST)) {
       $defaults = array_merge($defaults, CRM_Contact_BAO_SavedSearch::getFormValues($this->_ssID));
     }
     return $defaults;
   }
 
+  /**
+   * Set the default country for the form.
+   *
+   * For performance reasons country might be removed from the form CRM-18125
+   * but we need to include it in our defaults or the state will not be visible.
+   *
+   * @param array $defaults
+   */
+  public function loadDefaultCountryBasedOnState(&$defaults) {
+    if (!empty($defaults['state_province'])) {
+      $defaults['country'] = CRM_Core_DAO::singleValueQuery(
+        "SELECT country_id FROM civicrm_state_province
+         WHERE id = %1",
+        array(1 => array($defaults['state_province'][0], 'Integer'))
+      );
+    }
+  }
+
 }