/**
  * Collect CiviCRM data into temporary working table.
  */
 public static function syncPushCollectCiviCRM(CRM_Queue_TaskContext $ctx, $listID)
 {
     CRM_Mailchimp_Utils::checkDebug('Start-CRM_Mailchimp_Form_Sync syncPushCollectCiviCRM $listID= ', $listID);
     $sync = new CRM_Mailchimp_Sync($listID);
     $stats[$listID]['c_count'] = $sync->collectCiviCrm('push');
     CRM_Mailchimp_Utils::checkDebug('Start-CRM_Mailchimp_Form_Sync syncPushCollectCiviCRM $stats[$listID][c_count]= ', $stats[$listID]['c_count']);
     static::updatePushStats($stats);
     return CRM_Queue_Task::TASK_SUCCESS;
 }
 /**
  * Tests the selection of email address.
  *
  * 1. Check initial email is picked up.
  * 2. Check that a bulk one is preferred, if exists.
  * 3. Check that a primary one is used bulk is on hold.
  * 4. Check that a primary one is used if no bulk one.
  * 5. Check that secondary, not bulk, not primary one is NOT used.
  * 6. Check that a not bulk, not primary one is used if all else fails.
  * 7. Check contact not selected if all emails on hold
  * 8. Check contact not selected if opted out
  * 9. Check contact not selected if 'do not email' is set
  * 10. Check contact not selected if deceased.
  *
  * @depends testGetMCInterestGroupings
  */
 public function testCollectCiviUsesRightEmail()
 {
     $subscriber_hash = static::$civicrm_contact_1['subscriber_hash'];
     // 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->put("/lists/dummylistid/members/{$subscriber_hash}", Argument::any());
     $this->joinMembershipGroup(static::$civicrm_contact_1);
     $sync = new CRM_Mailchimp_Sync(static::$test_list_id);
     //
     // Test 1:
     //
     $sync->collectCiviCrm('push');
     // Should have one person in it.
     $this->assertEquals(1, $sync->countCiviCrmMembers());
     $dao = CRM_Core_DAO::executeQuery("SELECT email FROM tmp_mailchimp_push_c");
     $dao->fetch();
     // Check email is what we'd expect.
     $this->assertEquals(static::$civicrm_contact_1['email'], $dao->email);
     //
     // Test 2:
     //
     // Now add another email, this one is bulk.
     // Nb. adding a bulk email removes the is_bulkmail flag from other email
     // records.
     $second_email = civicrm_api3('Email', 'create', ['contact_id' => static::$civicrm_contact_1['contact_id'], 'email' => static::$civicrm_contact_2['email'], 'is_bulkmail' => 1, 'sequential' => 1]);
     if (empty($second_email['id'])) {
         throw new Exception("Well this shouldn't happen. No Id for created email.");
     }
     $sync->collectCiviCrm('push');
     // Should have one person in it.
     $this->assertEquals(1, $sync->countCiviCrmMembers());
     $dao = CRM_Core_DAO::executeQuery("SELECT email FROM tmp_mailchimp_push_c");
     $dao->fetch();
     // Check email is what we'd expect.
     $this->assertEquals(static::$civicrm_contact_2['email'], $dao->email);
     //
     // Test 3:
     //
     // Set the bulk one to on hold.
     //
     civicrm_api3('Email', 'create', ['id' => $second_email['id'], 'email' => $second_email['values'][0]['email'], 'on_hold' => 1]);
     $sync->collectCiviCrm('push');
     $this->assertEquals(1, $sync->countCiviCrmMembers());
     $dao = CRM_Core_DAO::executeQuery("SELECT email FROM tmp_mailchimp_push_c");
     $dao->fetch();
     // Check email is what we'd expect.
     $this->assertEquals(static::$civicrm_contact_1['email'], $dao->email);
     //
     // Test 4:
     //
     // Delete the bulk one; should now fallback to primary.
     //
     civicrm_api3('Email', 'delete', ['id' => $second_email['id']]);
     $sync->collectCiviCrm('push');
     // Should have one person in it.
     $this->assertEquals(1, $sync->countCiviCrmMembers());
     $dao = CRM_Core_DAO::executeQuery("SELECT email FROM tmp_mailchimp_push_c");
     $dao->fetch();
     // Check email is what we'd expect.
     $this->assertEquals(static::$civicrm_contact_1['email'], $dao->email);
     //
     // Test 5:
     //
     // Add a not bulk, not primary one. This should NOT get used.
     //
     $second_email = civicrm_api3('Email', 'create', ['contact_id' => static::$civicrm_contact_1['contact_id'], 'email' => static::$civicrm_contact_2['email'], 'is_bulkmail' => 0, 'is_primary' => 0, 'sequential' => 1]);
     if (empty($second_email['id'])) {
         throw new Exception("Well this shouldn't happen. No Id for created email.");
     }
     $sync->collectCiviCrm('push');
     $this->assertEquals(1, $sync->countCiviCrmMembers());
     $dao = CRM_Core_DAO::executeQuery("SELECT email FROM tmp_mailchimp_push_c");
     $dao->fetch();
     // Check email is what we'd expect.
     $this->assertEquals(static::$civicrm_contact_1['email'], $dao->email);
     //
     // Test 6:
     //
     // Check that an email is selected, even if there's no primary and no bulk.
     //
     // Find the primary email and delete it.
     $result = civicrm_api3('Email', 'get', ['contact_id' => static::$civicrm_contact_1['contact_id'], 'email' => static::$civicrm_contact_1['email'], 'api.Email.delete' => ['id' => '$value.id']]);
     $sync->collectCiviCrm('push');
     // Should have one person in it.
     $this->assertEquals(1, $sync->countCiviCrmMembers());
     $dao = CRM_Core_DAO::executeQuery("SELECT email FROM tmp_mailchimp_push_c");
     $dao->fetch();
     // Check email is what we'd expect.
     $this->assertEquals(static::$civicrm_contact_2['email'], $dao->email);
     //
     // Test 7
     //
     // Check that if all emails are on hold, user is not selected.
     //
     civicrm_api3('Email', 'create', ['id' => $second_email['id'], 'email' => $second_email['values'][0]['email'], 'on_hold' => 1]);
     $sync->collectCiviCrm('push');
     $this->assertEquals(0, $sync->countCiviCrmMembers());
     //
     // Test 8
     //
     // Check that even with a bulk, primary email, contact is not selected if
     // they have opted out.
     civicrm_api3('Email', 'create', ['id' => $second_email['id'], 'email' => $second_email['values'][0]['email'], 'on_hold' => 0]);
     civicrm_api3('Contact', 'create', ['contact_id' => static::$civicrm_contact_1['contact_id'], 'is_opt_out' => 1]);
     $sync->collectCiviCrm('push');
     $this->assertEquals(0, $sync->countCiviCrmMembers());
     //
     // Test 9
     //
     // Check that even with a bulk, primary email, contact is not selected if
     // they have do_not_email
     civicrm_api3('Contact', 'create', ['contact_id' => static::$civicrm_contact_1['contact_id'], 'is_opt_out' => 0, 'do_not_email' => 1]);
     $sync->collectCiviCrm('push');
     $this->assertEquals(0, $sync->countCiviCrmMembers());
     //
     // Test 10
     //
     // Check that even with a bulk, primary email, contact is not selected if
     // they is_deceased
     civicrm_api3('Contact', 'create', ['contact_id' => static::$civicrm_contact_1['contact_id'], 'do_not_email' => 0, 'is_deceased' => 1]);
     $sync->collectCiviCrm('push');
     $this->assertEquals(0, $sync->countCiviCrmMembers());
 }
 /**
  * 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;
     }
 }