CRM-4287: Contact search for email address shows only primary email matches as results
[civicrm-core.git] / tests / phpunit / CRM / Contact / BAO / QueryTest.php
index 12640081f501fe8f381864ffe2fb3b25c07def2b..965a3a8f8bef082bf1da1b14647a959c78b59b8b 100644 (file)
@@ -1,7 +1,5 @@
 <?php
 
-require_once 'CiviTest/Contact.php';
-
 /**
  *  Include dataProvider for tests
  * @group headless
@@ -33,8 +31,10 @@ class CRM_Contact_BAO_QueryTest extends CiviUnitTestCase {
   }
 
   /**
-   *  Test CRM_Contact_BAO_Query::searchQuery()
+   *  Test CRM_Contact_BAO_Query::searchQuery().
+   *
    * @dataProvider dataProvider
+   *
    * @param $fv
    * @param $count
    * @param $ids
@@ -151,6 +151,62 @@ class CRM_Contact_BAO_QueryTest extends CiviUnitTestCase {
     }
   }
 
+  /**
+   * Test searchByPrimaryEmailOnly setting.
+   */
+  public function testSearchByPrimaryEmailOnly() {
+    $contactID = $this->individualCreate();
+    $params = array(
+      'contact_id' => $contactID,
+      'email' => 'primary@example.com',
+      'is_primary' => 1,
+    );
+    $this->callAPISuccess('email', 'create', $params);
+
+    unset($params['is_primary']);
+    $params['email'] = 'secondary@team.com';
+    $this->callAPISuccess('email', 'create', $params);
+
+    foreach (array(0, 1) as $searchPrimary) {
+      Civi::settings()->set('searchPrimaryEmailOnly', $searchPrimary);
+
+      $params = array(
+        0 => array(
+          0 => 'email',
+          1 => 'LIKE',
+          2 => 'secondary@example.com',
+          3 => 0,
+          4 => 1,
+        ),
+      );
+      $returnProperties = array(
+        'contact_type' => 1,
+        'contact_sub_type' => 1,
+        'sort_name' => 1,
+      );
+
+      $queryObj = new CRM_Contact_BAO_Query($params, $returnProperties);
+      $resultDAO = $queryObj->searchQuery(0, 0, NULL,
+        FALSE, FALSE,
+        FALSE, FALSE,
+        FALSE);
+
+      if ($searchPrimary) {
+        $this->assertEquals($resultDAO->N, 0);
+      }
+      else {
+        //Assert secondary email gets included in search results.
+        while ($resultDAO->fetch()) {
+          $this->assertEquals('secondary@example.com', $resultDAO->email);
+        }
+      }
+
+      // API should always return primary email.
+      $result = $this->callAPISuccess('Contact', 'get', array('contact_id' => $contactID));
+      $this->assertEquals('primary@example.com', $result['values'][$contactID]['email']);
+    }
+  }
+
   /**
    * CRM-14263 search builder failure with search profile & address in criteria
    * We are retrieving primary here - checking the actual sql seems super prescriptive - but since the massive query object has
@@ -249,6 +305,21 @@ class CRM_Contact_BAO_QueryTest extends CiviUnitTestCase {
     CRM_Contact_BAO_GroupContactCache::load($group, TRUE);
   }
 
+  /**
+   * Test searches are case insensitive.
+   */
+  public function testCaseInsensitive() {
+    $orgID = $this->organizationCreate(array('organization_name' => 'BOb'));
+    $this->callAPISuccess('Contact', 'create', array('display_name' => 'Minnie Mouse', 'employer_id' => $orgID, 'contact_type' => 'Individual'));
+    $searchParams = array(array('current_employer', '=', 'bob', 0, 1));
+    $query = new CRM_Contact_BAO_Query($searchParams);
+    $result = $query->apiQuery($searchParams);
+    $this->assertEquals(1, count($result[0]));
+    $contact = reset($result[0]);
+    $this->assertEquals('Minnie Mouse', $contact['display_name']);
+    $this->assertEquals('BOb', $contact['current_employer']);
+  }
+
   /**
    * Test smart groups with non-numeric don't fail on equal queries.
    *
@@ -277,4 +348,74 @@ class CRM_Contact_BAO_QueryTest extends CiviUnitTestCase {
 
   }
 
+  /**
+   * Test the group contact clause does not contain an OR.
+   *
+   * The search should return 3 contacts - 2 households in the smart group of
+   * Contact Type = Household and one Individual hard-added to it. The
+   * Household that meets both criteria should be returned once.
+   */
+  public function testGroupClause() {
+    $this->householdCreate();
+    $householdID = $this->householdCreate();
+    $individualID = $this->individualCreate();
+    $groupID = $this->smartGroupCreate();
+    $this->callAPISuccess('GroupContact', 'create', array('group_id' => $groupID, 'contact_id' => $individualID, 'status' => 'Added'));
+    $this->callAPISuccess('GroupContact', 'create', array('group_id' => $groupID, 'contact_id' => $householdID, 'status' => 'Added'));
+
+    // Refresh the cache for test purposes. It would be better to alter to alter the GroupContact add function to add contacts to the cache.
+    CRM_Contact_BAO_GroupContactCache::remove($groupID, FALSE);
+
+    $sql = CRM_Contact_BAO_Query::getQuery(
+      array(array('group', 'IN', array($groupID), 0, 0)),
+      array('contact_id')
+    );
+
+    $dao = CRM_Core_DAO::executeQuery($sql);
+    $this->assertEquals(3, $dao->N);
+    $this->assertFalse(strstr($sql, ' OR '));
+
+    $sql = CRM_Contact_BAO_Query::getQuery(
+      array(array('group', 'IN', array($groupID), 0, 0)),
+      array('contact_id' => 1, 'group' => 1)
+    );
+
+    $dao = CRM_Core_DAO::executeQuery($sql);
+    $this->assertEquals(3, $dao->N);
+    $this->assertFalse(strstr($sql, ' OR '), 'Query does not include or');
+    while ($dao->fetch()) {
+      $this->assertTrue(($dao->groups == $groupID || $dao->groups == ',' . $groupID), $dao->groups . ' includes ' . $groupID);
+    }
+  }
+
+  /**
+   * CRM-19562 ensure that only ids are used for contact_id searching.
+   */
+  public function testContactIDClause() {
+    $params = array(
+      array("mark_x_2", "=", 1, 0, 0),
+      array("mark_x_foo@example.com", "=", 1, 0, 0),
+    );
+    $returnProperties = array(
+      "sort_name" => 1,
+      "email" => 1,
+      "do_not_email" => 1,
+      "is_deceased" => 1,
+      "on_hold" => 1,
+      "display_name" => 1,
+      "preferred_mail_format" => 1,
+    );
+    $numberofContacts = 2;
+    $query = new CRM_Contact_BAO_Query($params, $returnProperties);
+    try {
+      $query->apiQuery($params, $returnProperties, NULL, NULL, 0, $numberofContacts);
+    }
+    catch (Exception $e) {
+      $this->assertEquals("A fatal error was triggered: One of parameters  (value: foo@example.com) is not of the type Positive",
+        $e->getMessage());
+      return $this->assertTrue(TRUE);
+    }
+    return $this->fail('Test failed for some reason which is not good');
+  }
+
 }