From 2bedfb3f454c661adeeaa06f5f6620160e44fda5 Mon Sep 17 00:00:00 2001 From: Hossein Amin Date: Sat, 2 Jun 2018 14:03:11 +0300 Subject: [PATCH] fix for issue dev/core#127, incorrect cache records for smart groups, with testunit --- CRM/Contact/BAO/Query.php | 51 +++++++++++++++++----------- contributor-key.yml | 4 +++ tests/phpunit/api/v3/ContactTest.php | 51 ++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 19 deletions(-) diff --git a/CRM/Contact/BAO/Query.php b/CRM/Contact/BAO/Query.php index a4618da916..0781901113 100644 --- a/CRM/Contact/BAO/Query.php +++ b/CRM/Contact/BAO/Query.php @@ -5779,13 +5779,26 @@ SELECT COUNT( conts.total_amount ) as cancel_count, * @param $having */ public function filterRelatedContacts(&$from, &$where, &$having) { - static $_rTypeProcessed = NULL; - static $_rTypeFrom = NULL; - static $_rTypeWhere = NULL; - - if (!$_rTypeProcessed) { - $_rTypeProcessed = TRUE; - + if (!isset(Civi::$statics[__CLASS__]['related_contacts_filter'])) { + Civi::$statics[__CLASS__]['related_contacts_filter'] = array(); + } + $_rTempCache =& Civi::$statics[__CLASS__]['related_contacts_filter']; + // skip if filter has already applied + foreach ($_rTempCache as $acache) { + if (strpos($from, $acache['from']) !== FALSE) { + $having = NULL; + return; + } + } + $arg_sig = sha1("$from $where $having"); + if (isset($_rTempCache[$arg_sig])) { + $cache = $_rTempCache[$arg_sig]; + } + else { + $cache = array( + "from" => "", + "where" => "", + ); // create temp table with contact ids $tableName = CRM_Core_DAO::createTempTableName('civicrm_transform', TRUE); $sql = "CREATE TEMPORARY TABLE $tableName ( contact_id int primary key) ENGINE=HEAP"; @@ -5805,11 +5818,11 @@ SELECT contact_a.id if (is_numeric($this->_displayRelationshipType)) { $relationshipTypeLabel = $rTypes[$this->_displayRelationshipType]['label_a_b']; - $_rTypeFrom = " + $cache['from'] = " INNER JOIN civicrm_relationship displayRelType ON ( displayRelType.contact_id_a = contact_a.id OR displayRelType.contact_id_b = contact_a.id ) INNER JOIN $tableName transform_temp ON ( transform_temp.contact_id = displayRelType.contact_id_a OR transform_temp.contact_id = displayRelType.contact_id_b ) "; - $_rTypeWhere = " + $cache['where'] = " WHERE displayRelType.relationship_type_id = {$this->_displayRelationshipType} AND displayRelType.is_active = 1 "; @@ -5818,36 +5831,36 @@ AND displayRelType.is_active = 1 list($relType, $dirOne, $dirTwo) = explode('_', $this->_displayRelationshipType); if ($dirOne == 'a') { $relationshipTypeLabel = $rTypes[$relType]['label_a_b']; - $_rTypeFrom .= " + $cache['from'] .= " INNER JOIN civicrm_relationship displayRelType ON ( displayRelType.contact_id_a = contact_a.id ) INNER JOIN $tableName transform_temp ON ( transform_temp.contact_id = displayRelType.contact_id_b ) "; } else { $relationshipTypeLabel = $rTypes[$relType]['label_b_a']; - $_rTypeFrom .= " + $cache['from'] .= " INNER JOIN civicrm_relationship displayRelType ON ( displayRelType.contact_id_b = contact_a.id ) INNER JOIN $tableName transform_temp ON ( transform_temp.contact_id = displayRelType.contact_id_a ) "; } - $_rTypeWhere = " + $cache['where'] = " WHERE displayRelType.relationship_type_id = $relType AND displayRelType.is_active = 1 "; } $this->_qill[0][] = $qillMessage . "'" . $relationshipTypeLabel . "'"; + $_rTempCache[$arg_sig] = $cache; } - if (!empty($this->_permissionWhereClause)) { - $_rTypeWhere .= "AND $this->_permissionWhereClause"; - } - - if (strpos($from, $_rTypeFrom) === FALSE) { + if (strpos($from, $cache['from']) === FALSE) { // lets replace all the INNER JOIN's in the $from so we dont exclude other data // this happens when we have an event_type in the quert (CRM-7969) $from = str_replace("INNER JOIN", "LEFT JOIN", $from); - $from .= $_rTypeFrom; - $where = $_rTypeWhere; + $from .= $cache['from']; + $where = $cache['where']; + if (!empty($this->_permissionWhereClause)) { + $where .= "AND $this->_permissionWhereClause"; + } } $having = NULL; diff --git a/contributor-key.yml b/contributor-key.yml index e27a864a55..5e266d61f4 100644 --- a/contributor-key.yml +++ b/contributor-key.yml @@ -1354,3 +1354,7 @@ name : Yashodha Chaku organization: CiviDesk jira : yashodha + +- github : hosseinamin + name : Hossein Amin + jira : hosseinamin diff --git a/tests/phpunit/api/v3/ContactTest.php b/tests/phpunit/api/v3/ContactTest.php index e76ee55d9a..ae77ad4141 100644 --- a/tests/phpunit/api/v3/ContactTest.php +++ b/tests/phpunit/api/v3/ContactTest.php @@ -3785,4 +3785,55 @@ class api_v3_ContactTest extends CiviUnitTestCase { $this->assertEquals(array('external_identifier'), $result['values']['UI_external_identifier']); } + public function testSmartGroupsForRelatedContacts() { + $rtype1 = $this->callAPISuccess('relationship_type', 'create', array( + "name_a_b" => uniqid() . " Child of", + "name_b_a" => uniqid() . " Parent of", + )); + $rtype2 = $this->callAPISuccess('relationship_type', 'create', array( + "name_a_b" => uniqid() . " Household Member of", + "name_b_a" => uniqid() . " Household Member is", + )); + $h1 = $this->householdCreate(); + $c1 = $this->individualCreate(array('last_name' => 'Adams')); + $c2 = $this->individualCreate(array('last_name' => 'Adams')); + $this->callAPISuccess('relationship', 'create', array( + 'contact_id_a' => $c1, + 'contact_id_b' => $c2, + 'is_active' => 1, + 'relationship_type_id' => $rtype1['id'], // Child of + )); + $this->callAPISuccess('relationship', 'create', array( + 'contact_id_a' => $c1, + 'contact_id_b' => $h1, + 'is_active' => 1, + 'relationship_type_id' => $rtype2['id'], // Household Member of + )); + $this->callAPISuccess('relationship', 'create', array( + 'contact_id_a' => $c2, + 'contact_id_b' => $h1, + 'is_active' => 1, + 'relationship_type_id' => $rtype2['id'], // Household Member of + )); + + $ssParams = array( + 'formValues' => array( + 'display_relationship_type' => $rtype1['id'] . '_a_b', // Child of + 'sort_name' => 'Adams', + ), + ); + $g1ID = $this->smartGroupCreate($ssParams, array('name' => uniqid(), 'title' => uniqid())); + $ssParams = array( + 'formValues' => array( + 'display_relationship_type' => $rtype2['id'] . '_a_b', // Household Member of + ), + ); + $g2ID = $this->smartGroupCreate($ssParams, array('name' => uniqid(), 'title' => uniqid())); + CRM_Contact_BAO_GroupContactCache::loadAll(); + $g1Contacts = $this->callAPISuccess('contact', 'get', array('group' => $g1ID)); + $g2Contacts = $this->callAPISuccess('contact', 'get', array('group' => $g2ID)); + $this->assertTrue($g1Contacts['count'] == 1); + $this->assertTrue($g2Contacts['count'] == 2); + } + } -- 2.25.1