/**
  * Tests the removeInSync method.
  *
  */
 public function testRemoveInSync()
 {
     // Create empty tables.
     CRM_Mailchimp_Sync::createTemporaryTableForMailchimp();
     CRM_Mailchimp_Sync::createTemporaryTableForCiviCRM();
     // Prepare the mock for the subscription the post hook will do.
     $api_prophecy = $this->prophesize('CRM_Mailchimp_Api3');
     CRM_Mailchimp_Utils::setMailchimpApi($api_prophecy->reveal());
     $api_prophecy->get('/lists/dummylistid/interest-categories', Argument::any())->willReturn(json_decode('{"http_code":200,"data":{"categories":[{"id":"categoryid","title":"' . static::MC_INTEREST_CATEGORY_TITLE . '"}]}}'));
     $api_prophecy->get("/lists/dummylistid/interest-categories/categoryid/interests", Argument::any())->willReturn(json_decode('{"http_code":200,"data":{"interests":[{"id":"interestId1","name":"' . static::MC_INTEREST_NAME_1 . '"},{"id":"interestId2","name":"' . static::MC_INTEREST_NAME_2 . '"}]}}'));
     $api_prophecy->get('/lists', ['fields' => 'lists.id,lists.name', 'count' => 10000])->willReturn(json_decode(json_encode(['http_code' => 200, 'data' => ['lists' => []]])));
     $sync = new CRM_Mailchimp_Sync(static::$test_list_id);
     // Test 1.
     //
     // Delete records from both tables when there's a cid_guess--contact link
     // and the hash is the same.
     CRM_Core_DAO::executeQuery("INSERT INTO tmp_mailchimp_push_c (email, hash, contact_id) VALUES\n      ('*****@*****.**', 'aaaaaaaaaaaaaaaa', 1),\n      ('*****@*****.**', 'aaaaaaaaaaaaaaaa', 2);");
     CRM_Core_DAO::executeQuery("INSERT INTO tmp_mailchimp_push_m (email, hash, cid_guess) VALUES\n      ('*****@*****.**', 'aaaaaaaaaaaaaaaa', 1),\n      ('*****@*****.**', 'aaaaaaaaaaaaaaaa', 2);");
     $result = $sync->removeInSync('pull');
     $this->assertEquals(2, $result);
     $this->assertEquals(0, $sync->countMailchimpMembers());
     $this->assertEquals(0, $sync->countCiviCrmMembers());
     // Test 2.
     //
     // Check different hashes stops removals.
     CRM_Core_DAO::executeQuery("INSERT INTO tmp_mailchimp_push_c (email, hash, contact_id) VALUES\n      ('*****@*****.**', 'different', 1),\n      ('*****@*****.**', 'different', 2);");
     CRM_Core_DAO::executeQuery("INSERT INTO tmp_mailchimp_push_m (email, hash, cid_guess) VALUES\n      ('*****@*****.**', 'aaaaaaaaaaaaaaaa', 1),\n      ('*****@*****.**', 'aaaaaaaaaaaaaaaa', 2);");
     $result = $sync->removeInSync('pull');
     $this->assertEquals(0, $result);
     $this->assertEquals(2, $sync->countMailchimpMembers());
     $this->assertEquals(2, $sync->countCiviCrmMembers());
     // Test 3.
     //
     // Check nothing removed if no cid-contact match.
     CRM_Mailchimp_Sync::createTemporaryTableForMailchimp();
     CRM_Mailchimp_Sync::createTemporaryTableForCiviCRM();
     CRM_Core_DAO::executeQuery("INSERT INTO tmp_mailchimp_push_c (email, hash, contact_id) VALUES\n      ('*****@*****.**', 'aaaaaaaaaaaaaaaa', 1),\n      ('*****@*****.**', 'aaaaaaaaaaaaaaaa', 2);");
     CRM_Core_DAO::executeQuery("INSERT INTO tmp_mailchimp_push_m (email, hash, cid_guess) VALUES\n      ('*****@*****.**', 'aaaaaaaaaaaaaaaa', 0),\n      ('*****@*****.**', 'aaaaaaaaaaaaaaaa', NULL);");
     $result = $sync->removeInSync('pull');
     $this->assertEquals(0, $result);
     $this->assertEquals(2, $sync->countMailchimpMembers());
     $this->assertEquals(2, $sync->countCiviCrmMembers());
     // Test 4.
     //
     // Check duplicate civi contact deleted.
     CRM_Mailchimp_Sync::createTemporaryTableForMailchimp();
     CRM_Mailchimp_Sync::createTemporaryTableForCiviCRM();
     CRM_Core_DAO::executeQuery("INSERT INTO tmp_mailchimp_push_c (email, hash, contact_id) VALUES\n      ('*****@*****.**', 'Xaaaaaaaaaaaaaaa', 1),\n      ('*****@*****.**', 'Yaaaaaaaaaaaaaaa', 2);");
     CRM_Core_DAO::executeQuery("INSERT INTO tmp_mailchimp_push_m (email, hash, cid_guess) VALUES\n      ('*****@*****.**', 'bbbbbbbbbbbbbbbb', 1);");
     $result = $sync->removeInSync('push');
     $this->assertEquals(1, $result);
     $this->assertEquals(1, $sync->countMailchimpMembers());
     $this->assertEquals(1, $sync->countCiviCrmMembers());
     // Test 5.
     //
     // Check duplicate civi contact NOT deleted when in pull mode.
     CRM_Mailchimp_Sync::createTemporaryTableForMailchimp();
     CRM_Mailchimp_Sync::createTemporaryTableForCiviCRM();
     CRM_Core_DAO::executeQuery("INSERT INTO tmp_mailchimp_push_c (email, hash, contact_id) VALUES\n      ('*****@*****.**', 'Xaaaaaaaaaaaaaaa', 1),\n      ('*****@*****.**', 'Yaaaaaaaaaaaaaaa', 2);");
     CRM_Core_DAO::executeQuery("INSERT INTO tmp_mailchimp_push_m (email, hash, cid_guess) VALUES\n      ('*****@*****.**', 'bbbbbbbbbbbbbbbb', 1);");
     $result = $sync->removeInSync('pull');
     $this->assertEquals(0, $result);
     $this->assertEquals(1, $sync->countMailchimpMembers());
     $this->assertEquals(2, $sync->countCiviCrmMembers());
     // Test 5: one contact should be removed because it's in sync, the other
     // because it's a duplicate.
     //
     // Check duplicate civi contact deleted.
     CRM_Mailchimp_Sync::createTemporaryTableForMailchimp();
     CRM_Mailchimp_Sync::createTemporaryTableForCiviCRM();
     CRM_Core_DAO::executeQuery("INSERT INTO tmp_mailchimp_push_c (email, hash, contact_id) VALUES\n      ('*****@*****.**', 'aaaaaaaaaaaaaaaa', 1),\n      ('*****@*****.**', 'Yaaaaaaaaaaaaaaa', 2);");
     CRM_Core_DAO::executeQuery("INSERT INTO tmp_mailchimp_push_m (email, hash, cid_guess) VALUES\n      ('*****@*****.**', 'aaaaaaaaaaaaaaaa', 1);");
     $result = $sync->removeInSync('push');
     $this->assertEquals(2, $result);
     $this->assertEquals(0, $sync->countMailchimpMembers());
     $this->assertEquals(0, $sync->countCiviCrmMembers());
     CRM_Mailchimp_Sync::dropTemporaryTables();
 }
 /**
  * Check interests are properly mapped as groups are changed and that
  * collectMailchimp and collectCiviCrm work as expected.
  *
  *
  * This uses the posthook, which in turn uses
  * updateMailchimpFromCiviSingleContact.
  *
  * If all is working then at that point both collections should match.
  *
  */
 public function testSyncInterestGroupings()
 {
     $api = CRM_Mailchimp_Utils::getMailchimpApi();
     try {
         // Add them to the interest group (this should not trigger a Mailchimp
         // update as they are not in thet membership list yet).
         $this->joinGroup(static::$civicrm_contact_1, static::$civicrm_group_id_interest_1);
         // The post hook should subscribe this person and set their interests.
         $this->joinMembershipGroup(static::$civicrm_contact_1);
         // Check their interest group was set.
         $result = $api->get("/lists/" . static::$test_list_id . "/members/" . static::$civicrm_contact_1['subscriber_hash'], ['fields' => 'status,interests'])->data;
         $this->assertEquals((object) [static::$test_interest_id_1 => TRUE, static::$test_interest_id_2 => FALSE], $result->interests);
         // Remove them to the interest group.
         $this->removeGroup(static::$civicrm_contact_1, static::$civicrm_group_id_interest_1);
         // Check their interest group was unset.
         $result = $api->get("/lists/" . static::$test_list_id . "/members/" . static::$civicrm_contact_1['subscriber_hash'], ['fields' => 'status,interests'])->data;
         $this->assertEquals((object) [static::$test_interest_id_1 => FALSE, static::$test_interest_id_2 => FALSE], $result->interests);
         // Add them to the 2nd interest group.
         // While this is a dull test, we assume it works if the other interest
         // group one did, it leaves the fixture with one on and one off which is a
         // good mix for the next test.
         $this->joinGroup(static::$civicrm_contact_1, static::$civicrm_group_id_interest_2);
         // Check their interest group was set.
         $result = $api->get("/lists/" . static::$test_list_id . "/members/" . static::$civicrm_contact_1['subscriber_hash'], ['fields' => 'status,interests'])->data;
         $this->assertEquals((object) [static::$test_interest_id_1 => FALSE, static::$test_interest_id_2 => TRUE], $result->interests);
         // Now check collections work.
         $sync = new CRM_Mailchimp_Sync(static::$test_list_id);
         $sync->collectCiviCrm('push');
         $this->assertEquals(1, $sync->countCiviCrmMembers());
         $sync->collectMailchimp('push');
         $this->assertEquals(1, $sync->countMailchimpMembers());
         $matches = $sync->matchMailchimpMembersToContacts();
         $this->assertEquals(['bySubscribers' => 1, 'byUniqueEmail' => 0, 'byNameEmail' => 0, 'bySingle' => 0, 'totalMatched' => 1, 'newContacts' => 0, 'failures' => 0], $matches);
         // This should return 1
         $dao = CRM_Core_DAO::executeQuery("SELECT * FROM tmp_mailchimp_push_m");
         $dao->fetch();
         $mc = ['email' => $dao->email, 'first_name' => $dao->first_name, 'last_name' => $dao->last_name, 'interests' => $dao->interests, 'hash' => $dao->hash, 'cid_guess' => $dao->cid_guess];
         $dao = CRM_Core_DAO::executeQuery("SELECT * FROM tmp_mailchimp_push_c");
         $dao->fetch();
         $civi = ['email' => $dao->email, 'email_id' => $dao->email_id, 'contact_id' => $dao->contact_id, 'first_name' => $dao->first_name, 'last_name' => $dao->last_name, 'interests' => $dao->interests, 'hash' => $dao->hash];
         $this->assertEquals($civi['first_name'], $mc['first_name']);
         $this->assertEquals($civi['last_name'], $mc['last_name']);
         $this->assertEquals($civi['email'], $mc['email']);
         $this->assertEquals($civi['interests'], $mc['interests']);
         $this->assertEquals($civi['hash'], $mc['hash']);
         // As the records are in sync, they should be and deleted.
         $in_sync = $sync->removeInSync('push');
         $this->assertEquals(1, $in_sync);
         // Now check the tables are both empty.
         $this->assertEquals(0, $sync->countMailchimpMembers());
         $this->assertEquals(0, $sync->countCiviCrmMembers());
     } catch (CRM_Mailchimp_Exception $e) {
         // Spit out request and response for debugging.
         print "Request:\n";
         print_r($e->request);
         print "Response:\n";
         print_r($e->response);
         // re-throw exception.
         throw $e;
     }
 }