From 57f8e7f062ec53dd1fa2d6467723e3b9c619780b Mon Sep 17 00:00:00 2001 From: "deb.monish" Date: Wed, 20 Apr 2016 02:15:10 +0530 Subject: [PATCH] CRM-18147 - Advanced filtering on email or email_id does not work for the Contact API --- CRM/Contact/BAO/Query.php | 34 ++++++++++++++++++++++------ CRM/Core/BAO/Block.php | 1 + CRM/Utils/System.php | 2 +- tests/phpunit/api/v3/ContactTest.php | 34 +++++++++++++++++++++------- 4 files changed, 55 insertions(+), 16 deletions(-) diff --git a/CRM/Contact/BAO/Query.php b/CRM/Contact/BAO/Query.php index 561ae08e24..155592732b 100644 --- a/CRM/Contact/BAO/Query.php +++ b/CRM/Contact/BAO/Query.php @@ -417,7 +417,6 @@ class CRM_Contact_BAO_Query { $operator = 'AND', $apiEntity = NULL ) { - $this->_params = &$params; if ($this->_params == NULL) { $this->_params = array(); @@ -499,7 +498,7 @@ class CRM_Contact_BAO_Query { $this->_whereTables = $this->_tables; $this->selectClause($apiEntity); - $this->_whereClause = $this->whereClause(); + $this->_whereClause = $this->whereClause($apiEntity); if (array_key_exists('civicrm_contribution', $this->_whereTables)) { $component = 'contribution'; } @@ -1662,9 +1661,11 @@ class CRM_Contact_BAO_Query { static $skipWhere = NULL; static $likeNames = NULL; $result = NULL; + // Change camelCase EntityName to lowercase with underscores $apiEntity = _civicrm_api_get_entity_name_from_camel($apiEntity); + // check if $value is in OK (Operator as Key) format as used by Get API if (CRM_Utils_System::isNull($values)) { return $result; } @@ -1728,8 +1729,9 @@ class CRM_Contact_BAO_Query { * Get the where clause for a single field. * * @param array $values + * @param string $apiEntity */ - public function whereClauseSingle(&$values) { + public function whereClauseSingle(&$values, $apiEntity) { // do not process custom fields or prefixed contact ids or component params if (CRM_Core_BAO_CustomField::getKeyID($values[0]) || (substr($values[0], 0, CRM_Core_Form::CB_PREFIX_LEN) == CRM_Core_Form::CB_PREFIX) || @@ -1810,7 +1812,8 @@ class CRM_Contact_BAO_Query { return; case 'email': - $this->email($values); + case 'email_id': + $this->email($values, $apiEntity); return; case 'phone_numeric': @@ -1970,9 +1973,11 @@ class CRM_Contact_BAO_Query { /** * Given a list of conditions in params generate the required where clause. * + * @param string $apiEntity + * * @return string */ - public function whereClause() { + public function whereClause($apiEntity) { $this->_where[0] = array(); $this->_qill[0] = array(); @@ -1987,7 +1992,7 @@ class CRM_Contact_BAO_Query { $this->_where[0][] = self::buildClause("contact_a.id", $this->_params[$id][1], $this->_params[$id][2]); } else { - $this->whereClauseSingle($this->_params[$id]); + $this->whereClauseSingle($this->_params[$id], $apiEntity); } } @@ -3373,10 +3378,25 @@ WHERE $smartGroupClause * Where / qill clause for email * * @param array $values + * @param string $apiEntity */ - protected function email(&$values) { + protected function email(&$values, $apiEntity) { list($name, $op, $value, $grouping, $wildcard) = $values; + // CRM-18147: for Contact's GET API, email fieldname got appended with its entity as in {$apiEntiy}_{$name} + // so following code is use build whereClause for contact's primart email id + if (!empty($apiEntity)) { + $dataType = 'String'; + if ($name == 'email_id') { + $dataType = 'Integer'; + $name = 'id'; + } + + $this->_where[$grouping][] = self::buildClause('civicrm_email.is_primary', '=', 1, 'Integer'); + $this->_where[$grouping][] = self::buildClause("civicrm_email.$name", $op, $value, $dataType); + return; + } + $n = strtolower(trim($value)); if ($n) { if (substr($n, 0, 1) == '"' && diff --git a/CRM/Core/BAO/Block.php b/CRM/Core/BAO/Block.php index 4f09025f15..ca29380af2 100644 --- a/CRM/Core/BAO/Block.php +++ b/CRM/Core/BAO/Block.php @@ -419,6 +419,7 @@ class CRM_Core_BAO_Block { } // if params is_primary then set all others to not be primary & exit out + // if is_primary = 1 if (!empty($params['is_primary'])) { $sql = "UPDATE $table SET is_primary = 0 WHERE contact_id = %1"; $sqlParams = array(1 => array($contactId, 'Integer')); diff --git a/CRM/Utils/System.php b/CRM/Utils/System.php index 886fb2f5a5..3a7dc1c535 100644 --- a/CRM/Utils/System.php +++ b/CRM/Utils/System.php @@ -685,7 +685,7 @@ class CRM_Utils_System { if (is_array($value)) { // @todo Reuse of the $value variable = asking for trouble. foreach ($value as $key => $value) { - if (!self::isNull($value)) { + if (in_array($key, CRM_Core_DAO::acceptedSQLOperators(), TRUE) || !self::isNull($value)) { return FALSE; } } diff --git a/tests/phpunit/api/v3/ContactTest.php b/tests/phpunit/api/v3/ContactTest.php index 910be009c9..ea70d9f74e 100644 --- a/tests/phpunit/api/v3/ContactTest.php +++ b/tests/phpunit/api/v3/ContactTest.php @@ -257,21 +257,39 @@ class api_v3_ContactTest extends CiviUnitTestCase { * Verify that attempt to create individual contact with only an email succeeds. */ public function testCreateEmailIndividual() { - + $primaryEmail = 'man3@yahoo.com'; + $notPrimaryEmail = 'man4@yahoo.com'; $params = array( - 'email' => 'man3@yahoo.com', + 'email' => $primaryEmail, 'contact_type' => 'Individual', 'location_type_id' => 1, ); - $contact = $this->callAPISuccess('contact', 'create', $params); + $contact1 = $this->callAPISuccess('contact', 'create', $params); - $this->assertEquals(3, $contact['id']); - $email = $this->callAPISuccess('email', 'get', array('contact_id' => $contact['id'])); - $this->assertEquals(1, $email['count']); - $this->assertEquals('man3@yahoo.com', $email['values'][$email['id']]['email']); + $this->assertEquals(3, $contact1['id']); + $email1 = $this->callAPISuccess('email', 'get', array('contact_id' => $contact1['id'])); + $this->assertEquals(1, $email1['count']); + $this->assertEquals($primaryEmail, $email1['values'][$email1['id']]['email']); - $this->callAPISuccess('contact', 'delete', $contact); + $email2 = $this->callAPISuccess('email', 'create', array('contact_id' => $contact1['id'], 'is_primary' => 0, 'email' => $notPrimaryEmail)); + + // Case 1: Check with criteria primary 'email' => array('IS NOT NULL' => 1) + $result = $this->callAPISuccess('contact', 'get', array('email' => array('IS NOT NULL' => 1))); + $primaryEmailContactIds = array_keys($result['values']); + $this->assertEquals($primaryEmail, $email1['values'][$email1['id']]['email']); + + // Case 2: Check with criteria primary 'email' => array('<>' => '') + $result = $this->callAPISuccess('contact', 'get', array('email' => array('<>' => ''))); + $primaryEmailContactIds = array_keys($result['values']); + $this->assertEquals($primaryEmail, $email1['values'][$email1['id']]['email']); + + // Case 3: Check with email_id='primary email id' + $result = $this->callAPISuccess('contact', 'get', array('email_id' => $email1['id'])); + $this->assertEquals(1, $result['count']); + $this->assertEquals($contact1['id'], $result['id']); + + $this->callAPISuccess('contact', 'delete', $contact1); } /** -- 2.25.1