/** * Process the form after the input has been submitted and validated. */ public function postProcess() { $groupId = $this->controller->exportValue('RemoveFromGroup', 'group_id'); $group = CRM_Core_PseudoConstant::group(); list($total, $removed, $notRemoved) = CRM_Contact_BAO_GroupContact::removeContactsFromGroup($this->_contactIds, $groupId); $status = array(ts("%count contact removed from '%2'", array('count' => $removed, 'plural' => "%count contacts removed from '%2'", 2 => $group[$groupId]))); if ($notRemoved) { $status[] = ts('1 contact was already not in this group', array('count' => $notRemoved, 'plural' => '%count contacts were already not in this group')); } $status = '<ul><li>' . implode('</li><li>', $status) . '</li></ul>'; CRM_Core_Session::setStatus($status, ts("Removed Contact From Group", array('plural' => "Removed Contacts From Group", 'count' => $removed)), 'success', array('expires' => 0)); }
/** * process the form after the input has been submitted and validated * * @access public * @return None */ function postProcess() { $groupId = $this->controller->exportValue('RemoveFromGroup', 'group_id'); $group =& CRM_Core_PseudoConstant::group(); list($total, $removed, $notRemoved) = CRM_Contact_BAO_GroupContact::removeContactsFromGroup($this->_contactIds, $groupId); $status = array(ts('Removed Contact(s) from %1', array(1 => $group[$groupId])), ts('Total Selected Contact(s): %1', array(1 => $total))); if ($removed) { $status[] = ts('Total Contact(s) removed from group: %1', array(1 => $removed)); } if ($notRemoved) { $status[] = ts('Total Contact(s) not in group: %1', array(1 => $notRemoved)); } CRM_Core_Session::setStatus($status); }
/** * Create contact. * * takes an associative array and creates a contact object and all the associated * derived objects (i.e. individual, location, email, phone etc) * * This function is invoked from within the web form layer and also from the api layer * * @param array $params * (reference ) an assoc array of name/value pairs. * @param bool $fixAddress * If we need to fix address. * @param bool $invokeHooks * If we need to invoke hooks. * * @param bool $skipDelete * Unclear parameter, passed to website create * * @todo explain this parameter * * @throws Exception * @return CRM_Contact_BAO_Contact|CRM_Core_Error * Created or updated contribution object. We are deprecating returning an error in * favour of exceptions */ public static function &create(&$params, $fixAddress = TRUE, $invokeHooks = TRUE, $skipDelete = FALSE) { $contact = NULL; if (empty($params['contact_type']) && empty($params['contact_id'])) { return $contact; } $isEdit = TRUE; if ($invokeHooks) { if (!empty($params['contact_id'])) { CRM_Utils_Hook::pre('edit', $params['contact_type'], $params['contact_id'], $params); } else { CRM_Utils_Hook::pre('create', $params['contact_type'], NULL, $params); $isEdit = FALSE; } } $config = CRM_Core_Config::singleton(); // CRM-6942: set preferred language to the current language if it’s unset (and we’re creating a contact). if (empty($params['contact_id']) && empty($params['preferred_language'])) { $params['preferred_language'] = $config->lcMessages; } // CRM-9739: set greeting & addressee if unset and we’re creating a contact. if (empty($params['contact_id'])) { foreach (self::$_greetingTypes as $greeting) { if (empty($params[$greeting . '_id'])) { if ($defaultGreetingTypeId = CRM_Contact_BAO_Contact_Utils::defaultGreeting($params['contact_type'], $greeting)) { $params[$greeting . '_id'] = $defaultGreetingTypeId; } } } } $transaction = new CRM_Core_Transaction(); $contact = self::add($params); if (!$contact) { // Not dying here is stupid, since we get into wierd situation and into a bug that // is impossible to figure out for the user or for us // CRM-7925 CRM_Core_Error::fatal(); } $params['contact_id'] = $contact->id; if (CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MULTISITE_PREFERENCES_NAME, 'is_enabled')) { // Enabling multisite causes the contact to be added to the domain group. $domainGroupID = CRM_Core_BAO_Domain::getGroupId(); if (!empty($domainGroupID)) { if (!empty($params['group']) && is_array($params['group'])) { $params['group'][$domainGroupID] = 1; } else { $params['group'] = array($domainGroupID => 1); } } } if (array_key_exists('group', $params)) { $contactIds = array($params['contact_id']); foreach ($params['group'] as $groupId => $flag) { if ($flag == 1) { CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIds, $groupId); } elseif ($flag == -1) { CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contactIds, $groupId); } } } // Add location Block data. $blocks = CRM_Core_BAO_Location::create($params, $fixAddress); foreach ($blocks as $name => $value) { $contact->{$name} = $value; } //add website CRM_Core_BAO_Website::create($params['website'], $contact->id, $skipDelete); //get userID from session $session = CRM_Core_Session::singleton(); $userID = $session->get('userID'); // add notes if (!empty($params['note'])) { if (is_array($params['note'])) { foreach ($params['note'] as $note) { $contactId = $contact->id; if (isset($note['contact_id'])) { $contactId = $note['contact_id']; } //if logged in user, overwrite contactId if ($userID) { $contactId = $userID; } $noteParams = array('entity_id' => $contact->id, 'entity_table' => 'civicrm_contact', 'note' => $note['note'], 'subject' => CRM_Utils_Array::value('subject', $note), 'contact_id' => $contactId); CRM_Core_BAO_Note::add($noteParams, CRM_Core_DAO::$_nullArray); } } else { $contactId = $contact->id; if (isset($note['contact_id'])) { $contactId = $note['contact_id']; } //if logged in user, overwrite contactId if ($userID) { $contactId = $userID; } $noteParams = array('entity_id' => $contact->id, 'entity_table' => 'civicrm_contact', 'note' => $params['note'], 'subject' => CRM_Utils_Array::value('subject', $params), 'contact_id' => $contactId); CRM_Core_BAO_Note::add($noteParams, CRM_Core_DAO::$_nullArray); } } // update the UF user_unique_id if that has changed CRM_Core_BAO_UFMatch::updateUFName($contact->id); if (!empty($params['custom']) && is_array($params['custom'])) { CRM_Core_BAO_CustomValueTable::store($params['custom'], 'civicrm_contact', $contact->id); } // make a civicrm_subscription_history entry only on contact create (CRM-777) if (empty($params['contact_id'])) { $subscriptionParams = array('contact_id' => $contact->id, 'status' => 'Added', 'method' => 'Admin'); CRM_Contact_BAO_SubscriptionHistory::create($subscriptionParams); } $transaction->commit(); // CRM-6367: fetch the right label for contact type’s display $contact->contact_type_display = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_ContactType', $contact->contact_type, 'label', 'name'); if (!$config->doNotResetCache) { // Note: doNotResetCache flag is currently set by import contact process and merging, // since resetting and // rebuilding cache could be expensive (for many contacts). We might come out with better // approach in future. CRM_Contact_BAO_Contact_Utils::clearContactCaches($contact->id); } if ($invokeHooks) { if ($isEdit) { CRM_Utils_Hook::post('edit', $params['contact_type'], $contact->id, $contact); } else { CRM_Utils_Hook::post('create', $params['contact_type'], $contact->id, $contact); } } // process greetings CRM-4575, cache greetings self::processGreetings($contact); return $contact; }
static function manageCiviCRMGroupSubcription($contactID = array(), $requestData, $action) { CRM_Mailchimp_Utils::checkDebug('Start- CRM_Mailchimp_Page_WebHook manageCiviCRMGroupSubcription $contactID= ', $contactID); CRM_Mailchimp_Utils::checkDebug('Start- CRM_Mailchimp_Page_WebHook manageCiviCRMGroupSubcription $requestData= ', $requestData); CRM_Mailchimp_Utils::checkDebug('Start- CRM_Mailchimp_Page_WebHook manageCiviCRMGroupSubcription $requestType= ', $action); if (empty($contactID) || empty($requestData['list_id']) || empty($action)) { return NULL; } $listID = $requestData['list_id']; $groupContactRemoves = $groupContactAdditions = array(); // Deal with subscribe/unsubscribe. // We need the CiviCRM membership group for this list. $groups = CRM_Mailchimp_Utils::getGroupsToSync(array(), $listID, $membership_only = TRUE); $allGroups = CRM_Mailchimp_Utils::getGroupsToSync(array(), $listID, $membership_only = FALSE); if (!$groups) { // This list is not mapped to a group in CiviCRM. return NULL; } $_ = array_keys($groups); $membershipGroupID = $_[0]; if ($action == 'subscribe') { $groupContactAdditions[$membershipGroupID][] = $contactID; } elseif ($action == 'unsubscribe') { $groupContactRemoves[$membershipGroupID][] = $contactID; $mcGroupings = array(); foreach (empty($requestData['merges']['GROUPINGS']) ? array() : $requestData['merges']['GROUPINGS'] as $grouping) { foreach (explode(', ', $grouping['groups']) as $group) { $mcGroupings[$grouping['id']][$group] = 1; } } foreach ($allGroups as $groupID => $details) { if ($groupID != $membershipGroupID && $details['is_mc_update_grouping']) { if (!empty($mcGroupings[$details['grouping_id']][$details['group_name']])) { $groupContactRemoves[$groupID][] = $contactID; } } } } // Now deal with all the groupings that are mapped to CiviCRM groups for this list // and that have the allow MC updates flag set. /* Sample groupings from MC: * * [GROUPINGS] => Array( * [0] => Array( * [id] => 11365 * [name] => CiviCRM * [groups] => special * )) * Re-map to mcGroupings[grouping_id][group_name] = 1; */ $mcGroupings = array(); foreach (empty($requestData['merges']['GROUPINGS']) ? array() : $requestData['merges']['GROUPINGS'] as $grouping) { foreach (explode(', ', $grouping['groups']) as $group) { $mcGroupings[$grouping['id']][$group] = 1; } } $groups = CRM_Mailchimp_Utils::getGroupsToSync(array(), $listID, $membership_only = FALSE); CRM_Mailchimp_Utils::checkDebug('Middle- CRM_Mailchimp_Page_WebHook manageCiviCRMGroupSubcription $groups ', $groups); CRM_Mailchimp_Utils::checkDebug('Middle- CRM_Mailchimp_Page_WebHook manageCiviCRMGroupSubcription $mcGroupings ', $mcGroupings); foreach ($groups as $groupID => $details) { if ($groupID != $membershipGroupID && $details['is_mc_update_grouping']) { // This is a group we allow updates for. if (empty($mcGroupings[$details['grouping_id']][$details['group_name']])) { $groupContactRemoves[$groupID][] = $contactID; } else { $groupContactAdditions[$groupID][] = $contactID; } } } // Add contacts to groups, if anything to do. foreach ($groupContactAdditions as $groupID => $contactIDs) { CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIDs, $groupID, 'Admin', 'Added'); } // Remove contacts from groups, if anything to do. foreach ($groupContactRemoves as $groupID => $contactIDs) { CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contactIDs, $groupID, 'Admin', 'Removed'); } CRM_Mailchimp_Utils::checkDebug('End - CRM_Mailchimp_Page_WebHook manageCiviCRMGroupSubcription $groupContactRemoves ', $groupContactRemoves); CRM_Mailchimp_Utils::checkDebug('End - CRM_Mailchimp_Page_WebHook manageCiviCRMGroupSubcription $groupContactAdditions ', $groupContactAdditions); CRM_Mailchimp_Utils::checkDebug('End - CRM_Mailchimp_Page_WebHook manageCiviCRMGroupSubcription $contactID= ', $contactID); CRM_Mailchimp_Utils::checkDebug('End - CRM_Mailchimp_Page_WebHook manageCiviCRMGroupSubcription $requestData= ', $requestData); CRM_Mailchimp_Utils::checkDebug('End - CRM_Mailchimp_Page_WebHook manageCiviCRMGroupSubcription $requestType= ', $action); }
/** * function to remove/ rejoin the group * * @param int $groupContactId id of crm_group_contact * @param string $status this is the status that should be updated. * * $access public */ function del($groupContactId, $status) { $groupContact =& new CRM_Contact_DAO_GroupContact(); $groupId = CRM_Contact_BAO_GroupContact::getGroupId($groupContactId); switch ($status) { case 'i': $groupStatus = 'Added'; break; case 'p': $groupStatus = 'Pending'; break; case 'o': $groupStatus = 'Removed'; break; } $contactID = array($this->_contactId); $method = 'Admin'; CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contactID, $groupId, $method, $groupStatus); }
function testContactAddedToGroup() { $params = CRM_CiviMailchimp_UtilsTest::sampleContactParams(); $contact = CRM_Contact_BAO_Contact::create($params); $mailchimp_sync_setting = CRM_CiviMailchimp_BAO_SyncSettingsTest::createTestGroupAndSyncSettings('Test group testContactAddedToGroup'); // Test that the contact is not in the group (contactAddedToGroup returns TRUE) $contact_added_to_group = CRM_CiviMailchimp_Utils::contactAddedToGroup($mailchimp_sync_setting->civicrm_group_id, $contact->id); $this->assertTrue($contact_added_to_group); // Test that the contact is in the group (contactAddedToGroup returns FALSE) $contact_ids = array($contact->id); CRM_Contact_BAO_GroupContact::addContactsToGroup($contact_ids, $mailchimp_sync_setting->civicrm_group_id); $contact_added_to_group = CRM_CiviMailchimp_Utils::contactAddedToGroup($mailchimp_sync_setting->civicrm_group_id, $contact->id); $this->assertFalse($contact_added_to_group); // Test that a status other than 'Added' returns TRUE CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contact_ids, $mailchimp_sync_setting->civicrm_group_id); $contact_added_to_group = CRM_CiviMailchimp_Utils::contactAddedToGroup($mailchimp_sync_setting->civicrm_group_id, $contact->id); $this->assertTrue($contact_added_to_group); }
/** * Process the form after the input has been submitted and validated. * * * @return void */ public function postProcess() { $params = $this->controller->exportValues(); $groupOption = CRM_Utils_Array::value('group_option', $params, NULL); if ($groupOption) { $groupParams = array(); $groupParams['title'] = $params['title']; $groupParams['description'] = $params['description']; $groupParams['visibility'] = "User and User Admin Only"; if (array_key_exists('group_type', $params) && is_array($params['group_type'])) { $groupParams['group_type'] = CRM_Core_DAO::VALUE_SEPARATOR . implode(CRM_Core_DAO::VALUE_SEPARATOR, array_keys($params['group_type'])) . CRM_Core_DAO::VALUE_SEPARATOR; } else { $groupParams['group_type'] = ''; } $groupParams['is_active'] = 1; $createdGroup = CRM_Contact_BAO_Group::create($groupParams); $groupID = $createdGroup->id; $groupName = $groupParams['title']; } else { $groupID = $params['group_id']; if (!isset($groupID)) { $groupID = $this->_id; } $group = CRM_Core_PseudoConstant::group(); $groupName = $group[$groupID]; } if (isset($groupID)) { $selectedIDs = $params['availablePlayers']; // First, remove any contacts before edit CRM_Contact_BAO_GroupContact::removeContactsFromGroup($this->_contactIds, $groupID); list($total, $added, $notAdded) = CRM_Contact_BAO_GroupContact::addContactsToGroup($selectedIDs, $groupID); $status = array(ts('%count player added to team', array('count' => $added, 'plural' => '%count players added to team'))); if ($notAdded) { $status[] = ts('%count player was already on team', array('count' => $notAdded, 'plural' => '%count players were already on team')); } $status = '<ul><li>' . implode('</li><li>', $status) . '</li></ul>'; CRM_Core_Session::setStatus($status, ts('Added Player to %1', array(1 => $groupName, 'count' => $added, 'plural' => 'Added Players to %1')), 'success', array('expires' => 0)); } if ($this->_context === 'amtg') { CRM_Core_Session::singleton()->pushUserContext(CRM_Utils_System::url('civicrm/tournament/team')); //search', "reset=1&force=1")); } }
/** * Takes an associative array and creates / removes * contacts from the groups * * * @param array $params * (reference ) an assoc array of name/value pairs. * @param array $contactId * Contact id. * * @param bool $visibility * @param string $method * * @return void */ public static function create(&$params, $contactId, $visibility = FALSE, $method = 'Admin') { $contactIds = array(); $contactIds[] = $contactId; //if $visibility is true we are coming in via profile mean $method = 'Web' $ignorePermission = FALSE; if ($visibility) { $ignorePermission = TRUE; } if ($contactId) { $contactGroupList =& CRM_Contact_BAO_GroupContact::getContactGroup($contactId, 'Added', NULL, FALSE, $ignorePermission); if (is_array($contactGroupList)) { foreach ($contactGroupList as $key) { $groupId = $key['group_id']; $contactGroup[$groupId] = $groupId; } } } // get the list of all the groups $allGroup = CRM_Contact_BAO_GroupContact::getGroupList(0, $visibility); // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input if (!is_array($params)) { $params = array(); } // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input if (!isset($contactGroup) || !is_array($contactGroup)) { $contactGroup = array(); } // check which values has to be add/remove contact from group foreach ($allGroup as $key => $varValue) { if (!empty($params[$key]) && !array_key_exists($key, $contactGroup)) { // add contact to group CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIds, $key, $method); } elseif (empty($params[$key]) && array_key_exists($key, $contactGroup)) { // remove contact from group CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contactIds, $key, $method); } } }
/** * takes an associative array and creates / removes * contacts from the groups * * * @param array $params (reference ) an assoc array of name/value pairs * @param array $contactId contact id * * @return none * @access public * @static */ static function create(&$params, $contactId, $visibility = false, $method = 'Admin') { $contactIds = array(); $contactIds[] = $contactId; if ($contactId) { $contactGroupList =& CRM_Contact_BAO_GroupContact::getContactGroup($contactId, 'Added'); if (is_array($contactGroupList)) { foreach ($contactGroupList as $key) { $groupId = $key['group_id']; $contactGroup[$groupId] = $groupId; } } } // get the list of all the groups $allGroup =& CRM_Contact_BAO_GroupContact::getGroupList(0, $visibility); // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input if (!is_array($params)) { $params = array(); } // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input if (!isset($contactGroup) || !is_array($contactGroup)) { $contactGroup = array(); } // check which values has to be add/remove contact from group foreach ($allGroup as $key => $varValue) { if (CRM_Utils_Array::value($key, $params) && !array_key_exists($key, $contactGroup)) { // add contact to group CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIds, $key, $method); } else { if (!CRM_Utils_Array::value($key, $params) && array_key_exists($key, $contactGroup)) { // remove contact from group CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contactIds, $key, $method); } } } }
/** * New contacts from Mailchimp need bringing into CiviCRM. */ static function syncPullUpdates(CRM_Queue_TaskContext $ctx, $listID) { // Prepare the groups that we need to update $stats[$listID]['added'] = $stats[$listID]['removed'] = 0; // We need the membership group and any groups mapped to interest groupings with the allow MC updates option set. $membership_group_id = FALSE; $updatable_grouping_groups = array(); foreach (CRM_Mailchimp_Utils::getGroupsToSync(array(), $listID) as $groupID => $details) { if (!$details['grouping_id']) { $membership_group_id = $groupID; } elseif ($details['is_mc_update_grouping']) { // This group is one that we allow Mailchimp to update CiviCRM with. $updatable_grouping_groups[$groupID] = $details; } } // all Mailchimp table $dao = CRM_Core_DAO::executeQuery("SELECT m.*, c.groupings c_groupings\n FROM tmp_mailchimp_push_m m\n LEFT JOIN tmp_mailchimp_push_c c ON m.email = c.email\n ;"); // Loop the $dao object creating/finding contacts in CiviCRM. $groupContactRemoves = $groupContact = array(); while ($dao->fetch()) { $params = array('FNAME' => $dao->first_name, 'LNAME' => $dao->last_name, 'EMAIL' => $dao->email); // Update/create contact. $contact_id = CRM_Mailchimp_Utils::updateContactDetails($params); if ($contact_id) { // Ensure the contact is in the membership group. if (!$dao->c_groupings) { // This contact was not found in the CiviCRM table. // Therefore they are not in the membership group. // (actually they could have an email problem as well, but that's OK). // Add them into the membership group. $groupContact[$membership_group_id][] = $contact_id; $civi_groupings = array(); $stats[$listID]['added']++; } else { // This contact is in C and MC, but has differences. // unpack the group membership from CiviCRM. $civi_groupings = unserialize($dao->c_groupings); } // unpack the group membership reported by MC $mc_groupings = unserialize($dao->groupings); // Now sort out the grouping_groups for those we are supposed to allow updates for foreach ($updatable_grouping_groups as $groupID => $details) { // Should this person be in this grouping:group according to MC? if (!empty($mc_groupings[$details['grouping_id']][$details['group_id']])) { // They should be in this group. if (empty($civi_groupings[$details['grouping_id']][$details['group_id']])) { // But they're not! Plan to add them in. $groupContact[$groupID][] = $contact_id; } } else { // They should NOT be in this group. if (!empty($civi_groupings[$details['grouping_id']][$details['group_id']])) { // But they ARE. Plan to remove them. $groupContactRemoves[$groupID][] = $contact_id; } } } } } // And now, what if a contact is not in the Mailchimp list? We must remove them from the membership group. $dao = CRM_Core_DAO::executeQuery("SELECT c.contact_id\n FROM tmp_mailchimp_push_c c\n WHERE NOT EXISTS (\n SELECT m.email FROM tmp_mailchimp_push_m m WHERE m.email=c.email\n );"); // Loop the $dao object creating/finding contacts in CiviCRM. while ($dao->fetch()) { $groupContactRemoves[$membership_group_id][] = $dao->contact_id; $stats[$listID]['removed']++; } // Log group contacts which are going to be added to CiviCRM CRM_Core_Error::debug_var('Mailchimp $groupContact= ', $groupContact); // FIXME: dirty hack setting a variable in session to skip post hook require_once 'CRM/Core/Session.php'; $session = CRM_Core_Session::singleton(); $session->set('skipPostHook', 'yes'); if ($groupContact) { // We have some contacts to add into groups... foreach ($groupContact as $groupID => $contactIDs) { CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIDs, $groupID, 'Admin', 'Added'); } } // Log group contacts which are going to be removed from CiviCRM CRM_Core_Error::debug_var('Mailchimp $groupContactRemoves= ', $groupContactRemoves); if ($groupContactRemoves) { // We have some contacts to add into groups... foreach ($groupContactRemoves as $groupID => $contactIDs) { CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contactIDs, $groupID, 'Admin', 'Removed'); } } // FIXME: unset variable in session $session->set('skipPostHook', ''); static::updatePullStats($stats); // Finally, finish up by removing the two temporary tables CRM_Core_DAO::executeQuery("DROP TABLE tmp_mailchimp_push_m;"); CRM_Core_DAO::executeQuery("DROP TABLE tmp_mailchimp_push_c;"); return CRM_Queue_Task::TASK_SUCCESS; }
/** * * @param <type> $params * @param <type> $op * * @return <type> */ function civicrm_group_contact_common(&$params, $op = 'add') { if (!is_array($params)) { return civicrm_create_error(ts('input parameter should be an array')); } $contactIDs = array(); $groupIDs = array(); foreach ($params as $n => $v) { if (substr($n, 0, 10) == 'contact_id') { $contactIDs[] = $v; } elseif (substr($n, 0, 8) == 'group_id') { $groupIDs[] = $v; } } if (empty($contactIDs)) { return civicrm_create_error(ts('contact_id is a required field')); } if (empty($groupIDs)) { return civicrm_create_error(ts('group_id is a required field')); } $method = CRM_Utils_Array::value('method', $params, 'API'); if ($op == 'add') { $status = CRM_Utils_Array::value('status', $params, 'Added'); } elseif ($op == 'pending') { $status = CRM_Utils_Array::value('status', $params, 'Pending'); } else { $status = CRM_Utils_Array::value('status', $params, 'Removed'); } $tracking = CRM_Utils_Array::value('tracking', $params); require_once 'CRM/Contact/BAO/GroupContact.php'; $values = array('is_error' => 0); if ($op == 'add' || $op == 'pending') { $values['total_count'] = $values['added'] = $values['not_added'] = 0; foreach ($groupIDs as $groupID) { list($tc, $a, $na) = CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIDs, $groupID, $method, $status, $tracking); $values['total_count'] += $tc; $values['added'] += $a; $values['not_added'] += $na; } } else { $values['total_count'] = $values['removed'] = $values['not_removed'] = 0; foreach ($groupIDs as $groupID) { list($tc, $r, $nr) = CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contactIDs, $groupID, $method, $status, $tracking); $values['total_count'] += $tc; $values['removed'] += $r; $values['not_removed'] += $nr; } } return $values; }
/** * function to remove/ rejoin the group * * @param int $groupContactId id of crm_group_contact * @param string $status this is the status that should be updated. * * $access public */ static function del($groupContactId, $status, $contactID) { $groupId = CRM_Contact_BAO_GroupContact::getGroupId($groupContactId); switch ($status) { case 'i': $groupStatus = 'Added'; break; case 'p': $groupStatus = 'Pending'; break; case 'o': $groupStatus = 'Removed'; break; case 'd': $groupStatus = 'Deleted'; break; } $groupNum = CRM_Contact_BAO_GroupContact::getContactGroup($contactID, 'Added', NULL, TRUE, TRUE); if ($groupNum == 1 && $groupStatus == 'Removed' && CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MULTISITE_PREFERENCES_NAME, 'is_enabled')) { CRM_Core_Session::setStatus(ts('Please ensure at least one contact group association is maintained.'), ts('Could Not Remove')); return FALSE; } $ids = array($contactID); $method = 'Admin'; $session = CRM_Core_Session::singleton(); $userID = $session->get('userID'); if ($userID == $contactID) { $method = 'Web'; } CRM_Contact_BAO_GroupContact::removeContactsFromGroup($ids, $groupId, $method, $groupStatus); }
/** * Function to create contact * takes an associative array and creates a contact object and all the associated * derived objects (i.e. individual, location, email, phone etc) * * This function is invoked from within the web form layer and also from the api layer * * @param array $params (reference ) an assoc array of name/value pairs * @param boolean $fixAddress if we need to fix address * @param boolean $invokeHooks if we need to invoke hooks * * @return object CRM_Contact_BAO_Contact object * @access public * @static */ static function &create(&$params, $fixAddress = true, $invokeHooks = true) { $contact = null; if (!CRM_Utils_Array::value('contact_type', $params) && !CRM_Utils_Array::value('contact_id', $params)) { return $contact; } $isEdit = true; if ($invokeHooks) { require_once 'CRM/Utils/Hook.php'; if (CRM_Utils_Array::value('contact_id', $params)) { CRM_Utils_Hook::pre('edit', $params['contact_type'], $params['contact_id'], $params); } else { CRM_Utils_Hook::pre('create', $params['contact_type'], null, $params); $isEdit = false; } } require_once 'CRM/Core/Transaction.php'; $transaction = new CRM_Core_Transaction(); $contact = self::add($params); $params['contact_id'] = $contact->id; if (defined('CIVICRM_MULTISITE') && CIVICRM_MULTISITE) { // in order to make sure that every contact must be added to a group (CRM-4613) - require_once 'CRM/Core/BAO/Domain.php'; $domainGroupID = CRM_Core_BAO_Domain::getGroupId(); if (CRM_Utils_Array::value('group', $params) && is_array($params['group'])) { $grpFlp = array_flip($params['group']); if (!array_key_exists(1, $grpFlp)) { $params['group'][$domainGroupID] = 1; } } else { $params['group'] = array($domainGroupID => 1); } } if (array_key_exists('group', $params)) { require_once 'CRM/Contact/BAO/GroupContact.php'; $contactIds = array($params['contact_id']); foreach ($params['group'] as $groupId => $flag) { if ($flag == 1) { CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIds, $groupId); } else { if ($flag == -1) { CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contactIds, $groupId); } } } } //add location Block data $blocks = CRM_Core_BAO_Location::create($params, $fixAddress); foreach ($blocks as $name => $value) { $contact->{$name} = $value; } //get userID from session $session =& CRM_Core_Session::singleton(); $userID = $session->get('userID'); // add notes if (CRM_Utils_Array::value('note', $params)) { if (is_array($params['note'])) { foreach ($params['note'] as $note) { $contactId = $contact->id; if (isset($note['contact_id'])) { $contactId = $note['contact_id']; } //if logged in user, overwrite contactId if ($userID) { $contactId = $userID; } $noteParams = array('entity_id' => $contact->id, 'entity_table' => 'civicrm_contact', 'note' => $note['note'], 'subject' => $note['subject'], 'contact_id' => $contactId); CRM_Core_BAO_Note::add($noteParams, CRM_Core_DAO::$_nullArray); } } else { $contactId = $contact->id; if (isset($note['contact_id'])) { $contactId = $note['contact_id']; } //if logged in user, overwrite contactId if ($userID) { $contactId = $userID; } $noteParams = array('entity_id' => $contact->id, 'entity_table' => 'civicrm_contact', 'note' => $params['note'], 'subject' => CRM_Utils_Array::value('subject', $params), 'contact_id' => $contactId); CRM_Core_BAO_Note::add($noteParams, CRM_Core_DAO::$_nullArray); } } // update the UF user_unique_id if that has changed require_once 'CRM/Core/BAO/UFMatch.php'; CRM_Core_BAO_UFMatch::updateUFName($contact->id); if (CRM_Utils_Array::value('custom', $params) && is_array($params['custom'])) { require_once 'CRM/Core/BAO/CustomValueTable.php'; CRM_Core_BAO_CustomValueTable::store($params['custom'], 'civicrm_contact', $contact->id); } // make a civicrm_subscription_history entry only on contact create (CRM-777) if (!CRM_Utils_Array::value('contact_id', $params)) { $subscriptionParams = array('contact_id' => $contact->id, 'status' => 'Added', 'method' => 'Admin'); CRM_Contact_BAO_SubscriptionHistory::create($subscriptionParams); } $transaction->commit(); $contact->contact_type_display = CRM_Contact_DAO_Contact::tsEnum('contact_type', $contact->contact_type); // reset the group contact cache for this group require_once 'CRM/Contact/BAO/GroupContactCache.php'; CRM_Contact_BAO_GroupContactCache::remove(); if ($invokeHooks) { if ($isEdit) { CRM_Utils_Hook::post('edit', $params['contact_type'], $contact->id, $contact); } else { CRM_Utils_Hook::post('create', $params['contact_type'], $contact->id, $contact); } } return $contact; }
/** * Function to create contact * takes an associative array and creates a contact object and all the associated * derived objects (i.e. individual, location, email, phone etc) * * This function is invoked from within the web form layer and also from the api layer * * @param array $params (reference ) an assoc array of name/value pairs * @param boolean $fixAddress if we need to fix address * @param boolean $invokeHooks if we need to invoke hooks * * @return object CRM_Contact_BAO_Contact object * @access public * @static */ static function &create(&$params, $fixAddress = true, $invokeHooks = true) { $contact = null; if (!CRM_Utils_Array::value('contact_type', $params) && !CRM_Utils_Array::value('contact_id', $params)) { return $contact; } $isEdit = true; if ($invokeHooks) { require_once 'CRM/Utils/Hook.php'; if (CRM_Utils_Array::value('contact_id', $params)) { CRM_Utils_Hook::pre('edit', $params['contact_type'], $params['contact_id'], $params); } else { CRM_Utils_Hook::pre('create', $params['contact_type'], null, $params); $isEdit = false; } } require_once 'CRM/Core/Transaction.php'; $transaction = new CRM_Core_Transaction(); $contact = self::add($params); if (!$contact) { // CRM_Core_Error::fatal( ts( 'THe contact was not created, not set up to handle error' ) ); } $params['contact_id'] = $contact->id; if (defined('CIVICRM_MULTISITE') && CIVICRM_MULTISITE) { // in order to make sure that every contact must be added to a group (CRM-4613) - require_once 'CRM/Core/BAO/Domain.php'; $domainGroupID = CRM_Core_BAO_Domain::getGroupId(); if (CRM_Utils_Array::value('group', $params) && is_array($params['group'])) { $grpFlp = array_flip($params['group']); if (!array_key_exists(1, $grpFlp)) { $params['group'][$domainGroupID] = 1; } } else { $params['group'] = array($domainGroupID => 1); } } if (array_key_exists('group', $params)) { require_once 'CRM/Contact/BAO/GroupContact.php'; $contactIds = array($params['contact_id']); foreach ($params['group'] as $groupId => $flag) { if ($flag == 1) { CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIds, $groupId); } else { if ($flag == -1) { CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contactIds, $groupId); } } } } $config = CRM_Core_Config::singleton(); if (!$config->doNotResetCache) { // Note: doNotResetCache flag is currently set by import contact process, since resetting and // rebuilding cache could be expensive (for many contacts). We might come out with better // approach in future. // clear acl cache if any. require_once 'CRM/ACL/BAO/Cache.php'; CRM_ACL_BAO_Cache::resetCache(); } //add location Block data $blocks = CRM_Core_BAO_Location::create($params, $fixAddress); foreach ($blocks as $name => $value) { $contact->{$name} = $value; } //get userID from session $session =& CRM_Core_Session::singleton(); $userID = $session->get('userID'); // add notes if (CRM_Utils_Array::value('note', $params)) { if (is_array($params['note'])) { foreach ($params['note'] as $note) { $contactId = $contact->id; if (isset($note['contact_id'])) { $contactId = $note['contact_id']; } //if logged in user, overwrite contactId if ($userID) { $contactId = $userID; } $noteParams = array('entity_id' => $contact->id, 'entity_table' => 'civicrm_contact', 'note' => $note['note'], 'subject' => $note['subject'], 'contact_id' => $contactId); CRM_Core_BAO_Note::add($noteParams, CRM_Core_DAO::$_nullArray); } } else { $contactId = $contact->id; if (isset($note['contact_id'])) { $contactId = $note['contact_id']; } //if logged in user, overwrite contactId if ($userID) { $contactId = $userID; } $noteParams = array('entity_id' => $contact->id, 'entity_table' => 'civicrm_contact', 'note' => $params['note'], 'subject' => CRM_Utils_Array::value('subject', $params), 'contact_id' => $contactId); CRM_Core_BAO_Note::add($noteParams, CRM_Core_DAO::$_nullArray); } } // update the UF user_unique_id if that has changed require_once 'CRM/Core/BAO/UFMatch.php'; CRM_Core_BAO_UFMatch::updateUFName($contact->id); if (CRM_Utils_Array::value('custom', $params) && is_array($params['custom'])) { require_once 'CRM/Core/BAO/CustomValueTable.php'; CRM_Core_BAO_CustomValueTable::store($params['custom'], 'civicrm_contact', $contact->id); } // make a civicrm_subscription_history entry only on contact create (CRM-777) if (!CRM_Utils_Array::value('contact_id', $params)) { $subscriptionParams = array('contact_id' => $contact->id, 'status' => 'Added', 'method' => 'Admin'); CRM_Contact_BAO_SubscriptionHistory::create($subscriptionParams); } $transaction->commit(); $contact->contact_type_display = $contact->contact_type; // reset the group contact cache for this group require_once 'CRM/Contact/BAO/GroupContactCache.php'; CRM_Contact_BAO_GroupContactCache::remove(); if ($invokeHooks) { if ($isEdit) { CRM_Utils_Hook::post('edit', $params['contact_type'], $contact->id, $contact); } else { CRM_Utils_Hook::post('create', $params['contact_type'], $contact->id, $contact); } } // process greetings CRM-4575, cache greetings self::processGreetings($contact); return $contact; }
/** * Remove a given contact from the group set to sync with the given * Mailchimp list. */ static function removeContactFromGroup($contact, $mailchimp_list_id) { $contact_ids = array($contact->id); $mailchimp_sync_settings = CRM_CiviMailchimp_BAO_SyncSettings::findByListId($mailchimp_list_id); CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contact_ids, $mailchimp_sync_settings->civicrm_group_id); self::markContactAsNoBulkEmailsIfSettingEnabled($contact); }
/** * Unsubscribe a contact from all groups that received this mailing * * @param int $job_id The job ID * @param int $queue_id The Queue Event ID of the recipient * @param string $hash The hash * @param boolean $return If true return the list of groups. * @return array|null $groups Array of all groups from which the contact was removed, or null if the queue event could not be found. * @access public * @static */ public static function &unsub_from_mailing($job_id, $queue_id, $hash, $return = false) { /* First make sure there's a matching queue event */ $q =& CRM_Mailing_Event_BAO_Queue::verify($job_id, $queue_id, $hash); if (!$q) { return null; } $contact_id = $q->contact_id; require_once 'CRM/Core/Transaction.php'; $transaction = new CRM_Core_Transaction(); $do =& new CRM_Core_DAO(); $mg = CRM_Mailing_DAO_Group::getTableName(); $job = CRM_Mailing_BAO_Job::getTableName(); $mailing = CRM_Mailing_BAO_Mailing::getTableName(); $group = CRM_Contact_BAO_Group::getTableName(); $gc = CRM_Contact_BAO_GroupContact::getTableName(); $do->query("\n SELECT {$mg}.entity_table as entity_table,\n {$mg}.entity_id as entity_id\n FROM {$mg}\n INNER JOIN {$job}\n ON {$job}.mailing_id = {$mg}.mailing_id\n WHERE {$job}.id = " . CRM_Utils_Type::escape($job_id, 'Integer') . "\n AND {$mg}.group_type = 'Include'"); /* Make a list of groups and a list of prior mailings that received * this mailing */ $groups = array(); $mailings = array(); while ($do->fetch()) { if ($do->entity_table == $group) { //$groups[$do->entity_id] = true; $groups[$do->entity_id] = null; } else { if ($do->entity_table == $mailing) { $mailings[] = $do->entity_id; } } } /* As long as we have prior mailings, find their groups and add to the * list */ while (!empty($mailings)) { $do->query("\n SELECT {$mg}.entity_table as entity_table,\n {$mg}.entity_id as entity_id\n FROM {$mg}\n WHERE {$mg}.mailing_id IN (" . implode(', ', $mailings) . ")\n AND {$mg}.group_type = 'Include'"); $mailings = array(); while ($do->fetch()) { if ($do->entity_table == $group) { $groups[$do->entity_id] = true; } else { if ($do->entity_table == $mailing) { $mailings[] = $do->entity_id; } } } } /* Now we have a complete list of recipient groups. Filter out all * those except smart groups and those that the contact belongs to */ $do->query("\n SELECT {$group}.id as group_id,\n {$group}.title as title,\n {$group}.description as description\n FROM {$group}\n LEFT JOIN {$gc}\n ON {$gc}.group_id = {$group}.id\n WHERE {$group}.id IN (" . implode(', ', array_keys($groups)) . ")\n AND ({$group}.saved_search_id is not null\n OR ({$gc}.contact_id = {$contact_id}\n AND {$gc}.status = 'Added')\n )"); if ($return) { while ($do->fetch()) { $groups[$do->group_id] = array('title' => $do->title, 'description' => $do->description); } return $groups; } else { while ($do->fetch()) { $groups[$do->group_id] = $do->title; } } $contacts = array($contact_id); foreach ($groups as $group_id => $group_name) { $notremoved = false; if ($group_name) { list($total, $removed, $notremoved) = CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contacts, $group_id, 'Email'); } if ($notremoved) { unset($groups[$group_id]); } } $ue =& new CRM_Mailing_Event_BAO_Unsubscribe(); $ue->event_queue_id = $queue_id; $ue->org_unsubscribe = 0; $ue->time_stamp = date('YmdHis'); $ue->save(); $transaction->commit(); return $groups; }
/** * Group contact helper function. * * @todo behaviour is highly non-standard - need to figure out how to make this 'behave' * & at the very least return IDs & details of the groups created / changed * * @param array $params * @param string $op * * @return array */ function _civicrm_api3_group_contact_common($params, $op = 'Added') { $contactIDs = array(); $groupIDs = array(); foreach ($params as $n => $v) { if (substr($n, 0, 10) == 'contact_id') { $contactIDs[] = $v; } elseif (substr($n, 0, 8) == 'group_id') { $groupIDs[] = $v; } } if (empty($contactIDs)) { return civicrm_api3_create_error('contact_id is a required field'); } if (empty($groupIDs)) { return civicrm_api3_create_error('group_id is a required field'); } $method = CRM_Utils_Array::value('method', $params, 'API'); $status = CRM_Utils_Array::value('status', $params, $op); $tracking = CRM_Utils_Array::value('tracking', $params); if ($op == 'Added' || $op == 'Pending') { $extraReturnValues = array('total_count' => 0, 'added' => 0, 'not_added' => 0); foreach ($groupIDs as $groupID) { list($tc, $a, $na) = CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIDs, $groupID, $method, $status, $tracking); $extraReturnValues['total_count'] += $tc; $extraReturnValues['added'] += $a; $extraReturnValues['not_added'] += $na; } } else { $extraReturnValues = array('total_count' => 0, 'removed' => 0, 'not_removed' => 0); foreach ($groupIDs as $groupID) { list($tc, $r, $nr) = CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contactIDs, $groupID, $method, $status, $tracking); $extraReturnValues['total_count'] += $tc; $extraReturnValues['removed'] += $r; $extraReturnValues['not_removed'] += $nr; } } // can't pass this by reference $dao = NULL; return civicrm_api3_create_success(1, $params, 'GroupContact', 'create', $dao, $extraReturnValues); }
/** * Remove one or more contacts from an existing group * * @param CRM_Contact $group A valid group object (passed by reference). * @param array $contacts An array of one or more valid Contact objects (passed by reference). * * * @return null if success or CRM_Error (db error or contact was not valid) * * @access public */ function crm_delete_group_contacts(&$group, $contacts, $method = 'Admin') { _crm_initialize(); if (!is_a($group, 'CRM_Contact_BAO_Group') && !is_a($group, 'CRM_Contact_DAO_Group')) { return _crm_error('Invalid group object passed in'); } $contactID = array(); foreach ($contacts as $contact) { if (!isset($contact->id)) { return _crm_error('Invalid contact object passed in'); } $contactID[] = $contact->id; } if (!empty($contactID)) { CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contactID, $group->id, $method); } return null; }
/** * Group contact helper function. * * @todo behaviour is highly non-standard - need to figure out how to make this 'behave' * & at the very least return IDs & details of the groups created / changed * * @param array $params * @param string $op * * @return array */ function _civicrm_api3_group_contact_common($params, $op = 'Added') { $contactIDs = array(); $groupIDs = array(); // CRM-16959: Handle multiple Contact IDs and Group IDs in legacy format // (contact_id.1, contact_id.2) or as an array foreach ($params as $n => $v) { if (substr($n, 0, 10) == 'contact_id') { if (is_array($v)) { foreach ($v as $arr_v) { $contactIDs[] = $arr_v; } } else { $contactIDs[] = $v; } } elseif (substr($n, 0, 8) == 'group_id') { if (is_array($v)) { foreach ($v as $arr_v) { $groupIDs[] = $arr_v; } } else { $groupIDs[] = $v; } } } $method = CRM_Utils_Array::value('method', $params, 'API'); $status = CRM_Utils_Array::value('status', $params, $op); $tracking = CRM_Utils_Array::value('tracking', $params); if ($op == 'Added' || $op == 'Pending') { $extraReturnValues = array('total_count' => 0, 'added' => 0, 'not_added' => 0); foreach ($groupIDs as $groupID) { list($tc, $a, $na) = CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIDs, $groupID, $method, $status, $tracking); $extraReturnValues['total_count'] += $tc; $extraReturnValues['added'] += $a; $extraReturnValues['not_added'] += $na; } } else { $extraReturnValues = array('total_count' => 0, 'removed' => 0, 'not_removed' => 0); foreach ($groupIDs as $groupID) { list($tc, $r, $nr) = CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contactIDs, $groupID, $method, $status, $tracking); $extraReturnValues['total_count'] += $tc; $extraReturnValues['removed'] += $r; $extraReturnValues['not_removed'] += $nr; } } // can't pass this by reference $dao = NULL; return civicrm_api3_create_success(1, $params, 'GroupContact', 'create', $dao, $extraReturnValues); }
/** * function to remove/ rejoin the group * * @param int $groupContactId id of crm_group_contact * @param string $status this is the status that should be updated. * * $access public */ function del($groupContactId, $status, $contactID) { $groupId = CRM_Contact_BAO_GroupContact::getGroupId($groupContactId); switch ($status) { case 'i': $groupStatus = 'Added'; break; case 'p': $groupStatus = 'Pending'; break; case 'o': $groupStatus = 'Removed'; break; } $groupNum = CRM_Contact_BAO_GroupContact::getContactGroup($this->_contactId, 'Added', null, true, true); if (defined('CIVICRM_MULTISITE') && CIVICRM_MULTISITE && $groupNum == 1 && $groupStatus == 'Removed') { CRM_Core_Session::setStatus('make sure at least one contact group association is maintained.'); return false; } $ids = array($contactID); $method = 'Admin'; $session =& CRM_Core_Session::singleton(); $userID = $session->get('userID'); if ($userID == $contactID) { $method = 'Web'; } CRM_Contact_BAO_GroupContact::removeContactsFromGroup($ids, $groupId, $method, $groupStatus); }
/** * Unsubscribe a contact from all groups that received this mailing. * * @param int $job_id * The job ID. * @param int $queue_id * The Queue Event ID of the recipient. * @param string $hash * The hash. * @param bool $return * If true return the list of groups. * * @return array|null * $groups Array of all groups from which the contact was removed, or null if the queue event could not be found. */ public static function &unsub_from_mailing($job_id, $queue_id, $hash, $return = FALSE) { // First make sure there's a matching queue event. $q = CRM_Mailing_Event_BAO_Queue::verify($job_id, $queue_id, $hash); $success = NULL; if (!$q) { return $success; } $contact_id = $q->contact_id; $transaction = new CRM_Core_Transaction(); $do = new CRM_Core_DAO(); $mgObject = new CRM_Mailing_DAO_MailingGroup(); $mg = $mgObject->getTableName(); $jobObject = new CRM_Mailing_BAO_MailingJob(); $job = $jobObject->getTableName(); $mailingObject = new CRM_Mailing_BAO_Mailing(); $mailing = $mailingObject->getTableName(); $groupObject = new CRM_Contact_BAO_Group(); $group = $groupObject->getTableName(); $gcObject = new CRM_Contact_BAO_GroupContact(); $gc = $gcObject->getTableName(); //We Need the mailing Id for the hook... $do->query("SELECT {$job}.mailing_id as mailing_id\n FROM {$job}\n WHERE {$job}.id = " . CRM_Utils_Type::escape($job_id, 'Integer')); $do->fetch(); $mailing_id = $do->mailing_id; $do->query("\n SELECT {$mg}.entity_table as entity_table,\n {$mg}.entity_id as entity_id,\n {$mg}.group_type as group_type\n FROM {$mg}\n INNER JOIN {$job}\n ON {$job}.mailing_id = {$mg}.mailing_id\n INNER JOIN {$group}\n ON {$mg}.entity_id = {$group}.id\n WHERE {$job}.id = " . CRM_Utils_Type::escape($job_id, 'Integer') . "\n AND {$mg}.group_type IN ('Include', 'Base')\n AND {$group}.is_hidden = 0"); // Make a list of groups and a list of prior mailings that received // this mailing. $groups = array(); $base_groups = array(); $mailings = array(); while ($do->fetch()) { if ($do->entity_table == $group) { if ($do->group_type == 'Base') { $base_groups[$do->entity_id] = NULL; } else { $groups[$do->entity_id] = NULL; } } elseif ($do->entity_table == $mailing) { $mailings[] = $do->entity_id; } } // As long as we have prior mailings, find their groups and add to the // list. while (!empty($mailings)) { $do->query("\n SELECT {$mg}.entity_table as entity_table,\n {$mg}.entity_id as entity_id\n FROM {$mg}\n WHERE {$mg}.mailing_id IN (" . implode(', ', $mailings) . ")\n AND {$mg}.group_type = 'Include'"); $mailings = array(); while ($do->fetch()) { if ($do->entity_table == $group) { $groups[$do->entity_id] = TRUE; } elseif ($do->entity_table == $mailing) { $mailings[] = $do->entity_id; } } } //Pass the groups to be unsubscribed from through a hook. $group_ids = array_keys($groups); $base_group_ids = array_keys($base_groups); CRM_Utils_Hook::unsubscribeGroups('unsubscribe', $mailing_id, $contact_id, $group_ids, $base_group_ids); // Now we have a complete list of recipient groups. Filter out all // those except smart groups, those that the contact belongs to and // base groups from search based mailings. $baseGroupClause = ''; if (!empty($base_group_ids)) { $baseGroupClause = "OR {$group}.id IN(" . implode(', ', $base_group_ids) . ")"; } $groupIdClause = ''; if ($group_ids || $base_group_ids) { $groupIdClause = "AND {$group}.id IN (" . implode(', ', array_merge($group_ids, $base_group_ids)) . ")"; } $do->query("\n SELECT {$group}.id as group_id,\n {$group}.title as title,\n {$group}.description as description\n FROM {$group}\n LEFT JOIN {$gc}\n ON {$gc}.group_id = {$group}.id\n WHERE {$group}.is_hidden = 0\n {$groupIdClause}\n AND ({$group}.saved_search_id is not null\n OR ({$gc}.contact_id = {$contact_id}\n AND {$gc}.status = 'Added')\n {$baseGroupClause}\n )"); if ($return) { $returnGroups = array(); while ($do->fetch()) { $returnGroups[$do->group_id] = array('title' => $do->title, 'description' => $do->description); } return $returnGroups; } else { while ($do->fetch()) { $groups[$do->group_id] = $do->title; } } $contacts = array($contact_id); foreach ($groups as $group_id => $group_name) { $notremoved = FALSE; if ($group_name) { if (in_array($group_id, $base_group_ids)) { list($total, $removed, $notremoved) = CRM_Contact_BAO_GroupContact::addContactsToGroup($contacts, $group_id, 'Email', 'Removed'); } else { list($total, $removed, $notremoved) = CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contacts, $group_id, 'Email'); } } if ($notremoved) { unset($groups[$group_id]); } } $ue = new CRM_Mailing_Event_BAO_Unsubscribe(); $ue->event_queue_id = $queue_id; $ue->org_unsubscribe = 0; $ue->time_stamp = date('YmdHis'); $ue->save(); $transaction->commit(); return $groups; }
/** * "Pull" sync. * * Updates CiviCRM from Mailchimp using the tmp_mailchimp_push_[cm] tables. * * It is assumed that collections (in 'pull' mode) and `removeInSync` have * already run. * * 1. Loop the full tmp_mailchimp_push_m table: * * 1. Contact identified by collectMailchimp()? * - Yes: update name if different. * - No: Create or find-and-update the contact. * * 2. Check for changes in groups; record what needs to be changed for a * batch update. * * 2. Batch add/remove contacts from groups. * * @return array With the following keys: * * - created: was in MC not CiviCRM so a new contact was created * - joined : email matched existing contact that was joined to the membership * group. * - in_sync: was in MC and on membership group already. * - removed: was not in MC but was on membership group, so removed from * membership group. * - updated: No. in_sync or joined contacts that were updated. * * The initials of these categories c, j, i, r correspond to this diagram: * * From Mailchimp: ************ * From CiviCRM : ******** * Result : ccccjjjjiiiirrrr * * Of the contacts known in both systems (j, i) we also record how many were * updated (e.g. name, interests). * * Work in pass 1: * * - create|find * - join * - update names * - update interests * * Work in pass 2: * * - remove */ public function updateCiviFromMailchimp() { // Ensure posthooks don't trigger while we make GroupContact changes. CRM_Mailchimp_Utils::$post_hook_enabled = FALSE; // This is a functional variable, not a stats. one $changes = ['removals' => [], 'additions' => []]; CRM_Mailchimp_Utils::checkDebug("updateCiviFromMailchimp for group #{$this->membership_group_id}"); // Stats. $stats = ['created' => 0, 'joined' => 0, 'in_sync' => 0, 'removed' => 0, 'updated' => 0]; // all Mailchimp table *except* titanics: where the contact matches multiple // contacts in CiviCRM. $dao = CRM_Core_DAO::executeQuery("SELECT m.*,\n c.contact_id c_contact_id,\n c.interests c_interests, c.first_name c_first_name, c.last_name c_last_name\n FROM tmp_mailchimp_push_m m\n LEFT JOIN tmp_mailchimp_push_c c ON m.cid_guess = c.contact_id\n WHERE m.cid_guess IS NOT NULL\n ;"); // Create lookup hash to map Mailchimp Interest Ids to CiviCRM Groups. $interest_to_group_id = []; foreach ($this->interest_group_details as $group_id => $details) { $interest_to_group_id[$details['interest_id']] = $group_id; } // Loop records found at Mailchimp, creating/finding contacts in CiviCRM. while ($dao->fetch()) { $existing_contact_changed = FALSE; if (!empty($dao->cid_guess)) { // Matched existing contact: result: joined or in_sync $contact_id = $dao->cid_guess; if ($dao->c_contact_id) { // Contact is already in the membership group. $stats['in_sync']++; } else { // Contact needs joining to the membership group. $stats['joined']++; if (!$this->dry_run) { // Live. $changes['additions'][$this->membership_group_id][] = $contact_id; } else { // Dry Run. CRM_Mailchimp_Utils::checkDebug("Would add existing contact to membership group. Email: {$dao->email} Contact Id: {$dao->cid_guess}"); } } // Update the first name and last name of the contacts we know // if needed and making sure we don't overwrite // something with nothing. See issue #188. $edits = static::updateCiviFromMailchimpContactLogic(['first_name' => $dao->first_name, 'last_name' => $dao->last_name], ['first_name' => $dao->c_first_name, 'last_name' => $dao->c_last_name]); if ($edits) { if (!$this->dry_run) { // There are changes to be made so make them now. civicrm_api3('Contact', 'create', ['id' => $contact_id] + $edits); } else { // Dry run. CRM_Mailchimp_Utils::checkDebug("Would update CiviCRM contact {$dao->cid_guess} " . (empty($edits['first_name']) ? '' : "First name from {$dao->c_first_name} to {$dao->first_name} ") . (empty($edits['last_name']) ? '' : "Last name from {$dao->c_last_name} to {$dao->last_name} ")); } $existing_contact_changed = TRUE; } } else { // Contact does not exist, create a new one. if (!$this->dry_run) { // Live: $result = civicrm_api3('Contact', 'create', ['contact_type' => 'Individual', 'first_name' => $dao->first_name, 'last_name' => $dao->last_name, 'email' => $dao->email, 'sequential' => 1]); $contact_id = $result['values'][0]['id']; $changes['additions'][$this->membership_group_id][] = $contact_id; } else { // Dry Run: CRM_Mailchimp_Utils::checkDebug("Would create new contact with email: {$dao->email}, name: {$dao->first_name} {$dao->last_name}"); $contact_id = 'dry-run'; } $stats['created']++; } // Do interests need updating? if ($dao->c_interests && $dao->c_interests == $dao->interests) { // Nothing to change. } else { // Unpack the interests reported by MC $mc_interests = unserialize($dao->interests); if ($dao->c_interests) { // Existing contact. $existing_contact_changed = TRUE; $civi_interests = unserialize($dao->c_interests); } else { // Newly created contact is not in any interest groups. $civi_interests = []; } // Discover what needs changing to bring CiviCRM inline with Mailchimp. foreach ($mc_interests as $interest => $member_has_interest) { if ($member_has_interest && empty($civi_interests[$interest])) { // Member is interested in something, but CiviCRM does not know yet. if (!$this->dry_run) { $changes['additions'][$interest_to_group_id[$interest]][] = $contact_id; } else { CRM_Mailchimp_Utils::checkDebug("Would add CiviCRM contact {$dao->cid_guess} to interest group " . $interest_to_group_id[$interest]); } } elseif (!$member_has_interest && !empty($civi_interests[$interest])) { // Member is not interested in something, but CiviCRM thinks it is. if (!$this->dry_run) { $changes['removals'][$interest_to_group_id[$interest]][] = $contact_id; } else { CRM_Mailchimp_Utils::checkDebug("Would remove CiviCRM contact {$dao->cid_guess} from interest group " . $interest_to_group_id[$interest]); } } } } if ($existing_contact_changed) { $stats['updated']++; } } // And now, what if a contact is not in the Mailchimp list? // We must remove them from the membership group. // Accademic interest (#188): what's faster, this or a 'WHERE NOT EXISTS' // construct? $dao = CRM_Core_DAO::executeQuery("\n SELECT c.contact_id\n FROM tmp_mailchimp_push_c c\n LEFT OUTER JOIN tmp_mailchimp_push_m m ON m.cid_guess = c.contact_id\n WHERE m.email IS NULL;\n "); // Collect the contact_ids that need removing from the membership group. while ($dao->fetch()) { if (!$this->dry_run) { $changes['removals'][$this->membership_group_id][] = $dao->contact_id; } else { CRM_Mailchimp_Utils::checkDebug("Would remove CiviCRM contact {$dao->contact_id} from membership group - no longer subscribed at Mailchimp."); } $stats['removed']++; } if (!$this->dry_run) { // Log group contacts which are going to be added/removed to/from CiviCRM CRM_Mailchimp_Utils::checkDebug('Mailchimp $changes', $changes); // Make the changes. if ($changes['additions']) { // We have some contacts to add into groups... foreach ($changes['additions'] as $groupID => $contactIDs) { CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIDs, $groupID, 'Admin', 'Added'); } } if ($changes['removals']) { // We have some contacts to add into groups... foreach ($changes['removals'] as $groupID => $contactIDs) { CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contactIDs, $groupID, 'Admin', 'Removed'); } } } // Re-enable the post hooks. CRM_Mailchimp_Utils::$post_hook_enabled = TRUE; return $stats; }