/** * Takes an associative array and creates a campaign object. * * the function extract all the params it needs to initialize the create a * contact object. the params array could contain additional unused name/value * pairs * * @param array $params * (reference ) an assoc array of name/value pairs. * * @return CRM_Campaign_DAO_Campaign */ public static function create(&$params) { if (empty($params)) { return NULL; } if (!CRM_Utils_Array::value('id', $params)) { if (!CRM_Utils_Array::value('created_id', $params)) { $session = CRM_Core_Session::singleton(); $params['created_id'] = $session->get('userID'); } if (!CRM_Utils_Array::value('created_date', $params)) { $params['created_date'] = date('YmdHis'); } if (!CRM_Utils_Array::value('name', $params)) { $params['name'] = CRM_Utils_String::titleToVar($params['title'], 64); } CRM_Utils_Hook::pre('create', 'Campaign', NULL, $params); } else { CRM_Utils_Hook::pre('edit', 'Campaign', $params['id'], $params); } $campaign = new CRM_Campaign_DAO_Campaign(); $campaign->copyValues($params); $campaign->save(); if (!empty($params['id'])) { CRM_Utils_Hook::post('edit', 'Campaign', $campaign->id, $campaign); } else { CRM_Utils_Hook::post('create', 'Campaign', $campaign->id, $campaign); } /* Create the campaign group record */ $groupTableName = CRM_Contact_BAO_Group::getTableName(); if (isset($params['groups']) && !empty($params['groups']['include']) && is_array($params['groups']['include'])) { foreach ($params['groups']['include'] as $entityId) { $dao = new CRM_Campaign_DAO_CampaignGroup(); $dao->campaign_id = $campaign->id; $dao->entity_table = $groupTableName; $dao->entity_id = $entityId; $dao->group_type = 'Include'; $dao->save(); $dao->free(); } } //store custom data if (!empty($params['custom']) && is_array($params['custom'])) { CRM_Core_BAO_CustomValueTable::store($params['custom'], 'civicrm_campaign', $campaign->id); } return $campaign; }
/** * takes an associative array and creates a campaign object * * the function extract all the params it needs to initialize the create a * contact object. the params array could contain additional unused name/value * pairs * * @param array $params (reference ) an assoc array of name/value pairs * * @return object CRM_Campaign_DAO_Campaign object * @access public * @static */ static function create(&$params) { if (empty($params)) { return; } if (!CRM_Utils_Array::value('id', $params)) { if (!CRM_Utils_Array::value('created_id', $params)) { $session = CRM_Core_Session::singleton(); $params['created_id'] = $session->get('userID'); } if (!CRM_Utils_Array::value('created_date', $params)) { $params['created_date'] = date('YmdHis'); } if (!CRM_Utils_Array::value('name', $params)) { $params['name'] = CRM_Utils_String::titleToVar($params['title'], 64); } } $campaign = new CRM_Campaign_DAO_Campaign(); $campaign->copyValues($params); $campaign->save(); /* Create the campaign group record */ $groupTableName = CRM_Contact_BAO_Group::getTableName(); require_once 'CRM/Campaign/DAO/CampaignGroup.php'; $dao = new CRM_Campaign_DAO_CampaignGroup(); if (CRM_Utils_Array::value('include', $params['groups']) && is_array($params['groups']['include'])) { foreach ($params['groups']['include'] as $entityId) { $dao->reset(); $dao->campaign_id = $campaign->id; $dao->entity_table = $groupTableName; $dao->entity_id = $entityId; $dao->group_type = 'include'; $dao->save(); } } return $campaign; }
public function postProcess() { $values = $this->controller->exportValues($this->_name); //build hidden smart group. when user want to send mailing //through search contact-> more action -> send Mailing. CRM-3711 $groups = array(); if ($this->_searchBasedMailing && $this->_contactIds) { $session = CRM_Core_Session::singleton(); if ($this->_resultSelectOption == 'ts_sel') { // create a static grp if only a subset of result set was selected: $randID = md5(time()); $grpTitle = "Hidden Group {$randID}"; $grpID = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $grpTitle, 'id', 'title'); if (!$grpID) { $groupParams = array('title' => $grpTitle, 'is_active' => 1, 'is_hidden' => 1, 'group_type' => array('2' => 1)); $group = CRM_Contact_BAO_Group::create($groupParams); $grpID = $group->id; CRM_Contact_BAO_GroupContact::addContactsToGroup($this->_contactIds, $group->id); $newGroupTitle = "Hidden Group {$grpID}"; $groupParams = array('id' => $grpID, 'name' => CRM_Utils_String::titleToVar($newGroupTitle), 'title' => $newGroupTitle); $group = CRM_Contact_BAO_Group::create($groupParams); } // note at this point its a static group $smartGroupId = $grpID; } else { //get the hidden smart group id. $ssId = $this->get('ssID'); $hiddenSmartParams = array('group_type' => array('2' => 1), 'form_values' => $this->get('formValues'), 'saved_search_id' => $ssId, 'search_custom_id' => $this->get('customSearchID'), 'search_context' => $this->get('context')); list($smartGroupId, $savedSearchId) = CRM_Contact_BAO_Group::createHiddenSmartGroup($hiddenSmartParams); //set the saved search id. if (!$ssId) { if ($savedSearchId) { $this->set('ssID', $savedSearchId); } else { CRM_Core_Error::fatal(); } } } //get the base group for this mailing, CRM-3711 $groups['base'] = array($values['baseGroup']); $values['includeGroups'][] = $smartGroupId; } foreach (array('name', 'group_id', 'search_id', 'search_args', 'campaign_id', 'dedupe_email') as $n) { if (CRM_Utils_Array::value($n, $values)) { $params[$n] = $values[$n]; } } $qf_Group_submit = $this->controller->exportValue($this->_name, '_qf_Group_submit'); $this->set('name', $params['name']); $inGroups = $values['includeGroups']; $outGroups = $values['excludeGroups']; $inMailings = $values['includeMailings']; $outMailings = $values['excludeMailings']; if (is_array($inGroups)) { foreach ($inGroups as $key => $id) { if ($id) { $groups['include'][] = $id; } } } if (is_array($outGroups)) { foreach ($outGroups as $key => $id) { if ($id) { $groups['exclude'][] = $id; } } } $mailings = array(); if (is_array($inMailings)) { foreach ($inMailings as $key => $id) { if ($id) { $mailings['include'][] = $id; } } } if (is_array($outMailings)) { foreach ($outMailings as $key => $id) { if ($id) { $mailings['exclude'][] = $id; } } } $session = CRM_Core_Session::singleton(); $params['groups'] = $groups; $params['mailings'] = $mailings; if ($this->get('mailing_id')) { $ids = array(); // don't create a new mailing if already exists $ids['mailing_id'] = $this->get('mailing_id'); $groupTableName = CRM_Contact_BAO_Group::getTableName(); $mailingTableName = CRM_Mailing_BAO_Mailing::getTableName(); // delete previous includes/excludes, if mailing already existed foreach (array('groups', 'mailings') as $entity) { $mg = new CRM_Mailing_DAO_Group(); $mg->mailing_id = $ids['mailing_id']; $mg->entity_table = $entity == 'groups' ? $groupTableName : $mailingTableName; $mg->find(); while ($mg->fetch()) { $mg->delete(); } } } else { // new mailing, so lets set the created_id $session = CRM_Core_Session::singleton(); $params['created_id'] = $session->get('userID'); $params['created_date'] = date('YmdHis'); } $mailing = CRM_Mailing_BAO_Mailing::create($params, $ids); $this->set('mailing_id', $mailing->id); $dedupeEmail = FALSE; if (isset($params['dedupe_email'])) { $dedupeEmail = $params['dedupe_email']; } // also compute the recipients and store them in the mailing recipients table CRM_Mailing_BAO_Mailing::getRecipients($mailing->id, $mailing->id, NULL, NULL, TRUE, $dedupeEmail); $count = CRM_Mailing_BAO_Recipients::mailingSize($mailing->id); $this->set('count', $count); $this->assign('count', $count); $this->set('groups', $groups); $this->set('mailings', $mailings); if ($qf_Group_submit) { //when user perform mailing from search context //redirect it to search result CRM-3711. $ssID = $this->get('ssID'); $context = $this->get('context'); if ($ssID && $this->_searchBasedMailing) { if ($this->_action == CRM_Core_Action::BASIC) { $fragment = 'search'; } elseif ($this->_action == CRM_Core_Action::PROFILE) { $fragment = 'search/builder'; } elseif ($this->_action == CRM_Core_Action::ADVANCED) { $fragment = 'search/advanced'; } else { $fragment = 'search/custom'; } $context = $this->get('context'); if (!CRM_Contact_Form_Search::isSearchContext($context)) { $context = 'search'; } $urlParams = "force=1&reset=1&ssID={$ssID}&context={$context}"; $qfKey = CRM_Utils_Request::retrieve('qfKey', 'String', $this); if (CRM_Utils_Rule::qfKey($qfKey)) { $urlParams .= "&qfKey={$qfKey}"; } $draftURL = CRM_Utils_System::url('civicrm/mailing/browse/unscheduled', 'scheduled=false&reset=1'); $status = ts("Your mailing has been saved. You can continue later by clicking the 'Continue' action to resume working on it.<br /> From <a href='%1'>Draft and Unscheduled Mailings</a>.", array(1 => $draftURL)); CRM_Core_Session::setStatus($status); //replace user context to search. $url = CRM_Utils_System::url('civicrm/contact/' . $fragment, $urlParams); return $this->controller->setDestination($url); } else { $status = ts("Your mailing has been saved. Click the 'Continue' action to resume working on it."); CRM_Core_Session::setStatus($status); $url = CRM_Utils_System::url('civicrm/mailing/browse/unscheduled', 'scheduled=false&reset=1'); return $this->controller->setDestination($url); } } }
/** * Get all of the ACLs for a contact through ACL groups owned by Contact * groups. * * @param int $contact_id - ID of a contact to search for * * @return array - Array of assoc. arrays of ACL rules * @access public * @static */ public static function &getGroupACLRoles($contact_id) { $contact_id = CRM_Utils_Type::escape($contact_id, 'Integer'); $rule = new CRM_ACL_BAO_ACL(); $acl = self::getTableName(); $aclRole = 'civicrm_acl_role'; $aclER = CRM_ACL_DAO_EntityRole::getTableName(); $c2g = CRM_Contact_BAO_GroupContact::getTableName(); $group = CRM_Contact_BAO_Group::getTableName(); $query = " SELECT {$acl}.*\n FROM {$acl}\n INNER JOIN civicrm_option_group og\n ON og.name = 'acl_role'\n INNER JOIN civicrm_option_value ov\n ON {$acl}.entity_table = '{$aclRole}'\n AND ov.option_group_id = og.id\n AND {$acl}.entity_id = ov.value\n AND ov.is_active = 1\n INNER JOIN {$aclER}\n ON {$aclER}.acl_role_id = {$acl}.entity_id\n AND {$aclER}.is_active = 1\n INNER JOIN {$c2g}\n ON {$aclER}.entity_id = {$c2g}.group_id\n AND {$aclER}.entity_table = 'civicrm_group'\n WHERE {$acl}.entity_table = '{$aclRole}'\n AND {$acl}.is_active = 1\n AND {$c2g}.contact_id = {$contact_id}\n AND {$c2g}.status = 'Added'"; $results = array(); $rule->query($query); while ($rule->fetch()) { $results[$rule->id] =& $rule->toArray(); } // also get all acls for "Any Role" case // and authenticated User Role if present $roles = "0"; $session = CRM_Core_Session::singleton(); if ($session->get('ufID') > 0) { $roles .= ",2"; } $query = "\nSELECT {$acl}.*\n FROM {$acl}\n WHERE {$acl}.entity_id IN ( {$roles} )\n AND {$acl}.entity_table = 'civicrm_acl_role'\n"; $rule->query($query); while ($rule->fetch()) { $results[$rule->id] =& $rule->toArray(); } return $results; }
/** * 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; }
/** * Generate a report. Fetch event count information, mailing data, and job * status. * * @param int $id * The mailing id to report. * @param bool $skipDetails * Whether return all detailed report. * * @param bool $isSMS * * @return array * Associative array of reporting data */ public static function &report($id, $skipDetails = FALSE, $isSMS = FALSE) { $mailing_id = CRM_Utils_Type::escape($id, 'Integer'); $mailing = new CRM_Mailing_BAO_Mailing(); $t = array('mailing' => self::getTableName(), 'mailing_group' => CRM_Mailing_DAO_MailingGroup::getTableName(), 'group' => CRM_Contact_BAO_Group::getTableName(), 'job' => CRM_Mailing_BAO_MailingJob::getTableName(), 'queue' => CRM_Mailing_Event_BAO_Queue::getTableName(), 'delivered' => CRM_Mailing_Event_BAO_Delivered::getTableName(), 'opened' => CRM_Mailing_Event_BAO_Opened::getTableName(), 'reply' => CRM_Mailing_Event_BAO_Reply::getTableName(), 'unsubscribe' => CRM_Mailing_Event_BAO_Unsubscribe::getTableName(), 'bounce' => CRM_Mailing_Event_BAO_Bounce::getTableName(), 'forward' => CRM_Mailing_Event_BAO_Forward::getTableName(), 'url' => CRM_Mailing_BAO_TrackableURL::getTableName(), 'urlopen' => CRM_Mailing_Event_BAO_TrackableURLOpen::getTableName(), 'component' => CRM_Mailing_BAO_Component::getTableName(), 'spool' => CRM_Mailing_BAO_Spool::getTableName()); $report = array(); $additionalWhereClause = " AND "; if (!$isSMS) { $additionalWhereClause .= " {$t['mailing']}.sms_provider_id IS NULL "; } else { $additionalWhereClause .= " {$t['mailing']}.sms_provider_id IS NOT NULL "; } /* Get the mailing info */ $mailing->query("\n SELECT {$t['mailing']}.*\n FROM {$t['mailing']}\n WHERE {$t['mailing']}.id = {$mailing_id} {$additionalWhereClause}"); $mailing->fetch(); $report['mailing'] = array(); foreach (array_keys(self::fields()) as $field) { $report['mailing'][$field] = $mailing->{$field}; } //get the campaign if ($campaignId = CRM_Utils_Array::value('campaign_id', $report['mailing'])) { $campaigns = CRM_Campaign_BAO_Campaign::getCampaigns($campaignId); $report['mailing']['campaign'] = $campaigns[$campaignId]; } //mailing report is called by activity //we dont need all detail report if ($skipDetails) { return $report; } /* Get the component info */ $query = array(); $components = array('header' => ts('Header'), 'footer' => ts('Footer'), 'reply' => ts('Reply'), 'unsubscribe' => ts('Unsubscribe'), 'optout' => ts('Opt-Out')); foreach (array_keys($components) as $type) { $query[] = "SELECT {$t['component']}.name as name,\n '{$type}' as type,\n {$t['component']}.id as id\n FROM {$t['component']}\n INNER JOIN {$t['mailing']}\n ON {$t['mailing']}.{$type}_id =\n {$t['component']}.id\n WHERE {$t['mailing']}.id = {$mailing_id}"; } $q = '(' . implode(') UNION (', $query) . ')'; $mailing->query($q); $report['component'] = array(); while ($mailing->fetch()) { $report['component'][] = array('type' => $components[$mailing->type], 'name' => $mailing->name, 'link' => CRM_Utils_System::url('civicrm/mailing/component', "reset=1&action=update&id={$mailing->id}")); } /* Get the recipient group info */ $mailing->query("\n SELECT {$t['mailing_group']}.group_type as group_type,\n {$t['group']}.id as group_id,\n {$t['group']}.title as group_title,\n {$t['group']}.is_hidden as group_hidden,\n {$t['mailing']}.id as mailing_id,\n {$t['mailing']}.name as mailing_name\n FROM {$t['mailing_group']}\n LEFT JOIN {$t['group']}\n ON {$t['mailing_group']}.entity_id = {$t['group']}.id\n AND {$t['mailing_group']}.entity_table =\n '{$t['group']}'\n LEFT JOIN {$t['mailing']}\n ON {$t['mailing_group']}.entity_id =\n {$t['mailing']}.id\n AND {$t['mailing_group']}.entity_table =\n '{$t['mailing']}'\n\n WHERE {$t['mailing_group']}.mailing_id = {$mailing_id}\n "); $report['group'] = array('include' => array(), 'exclude' => array(), 'base' => array()); while ($mailing->fetch()) { $row = array(); if (isset($mailing->group_id)) { $row['id'] = $mailing->group_id; $row['name'] = $mailing->group_title; $row['link'] = CRM_Utils_System::url('civicrm/group/search', "reset=1&force=1&context=smog&gid={$row['id']}"); } else { $row['id'] = $mailing->mailing_id; $row['name'] = $mailing->mailing_name; $row['mailing'] = TRUE; $row['link'] = CRM_Utils_System::url('civicrm/mailing/report', "mid={$row['id']}"); } /* Rename hidden groups */ if ($mailing->group_hidden == 1) { $row['name'] = "Search Results"; } if ($mailing->group_type == 'Include') { $report['group']['include'][] = $row; } elseif ($mailing->group_type == 'Base') { $report['group']['base'][] = $row; } else { $report['group']['exclude'][] = $row; } } /* Get the event totals, grouped by job (retries) */ $mailing->query("\n SELECT {$t['job']}.*,\n COUNT(DISTINCT {$t['queue']}.id) as queue,\n COUNT(DISTINCT {$t['delivered']}.id) as delivered,\n COUNT(DISTINCT {$t['reply']}.id) as reply,\n COUNT(DISTINCT {$t['forward']}.id) as forward,\n COUNT(DISTINCT {$t['bounce']}.id) as bounce,\n COUNT(DISTINCT {$t['urlopen']}.id) as url,\n COUNT(DISTINCT {$t['spool']}.id) as spool\n FROM {$t['job']}\n LEFT JOIN {$t['queue']}\n ON {$t['queue']}.job_id = {$t['job']}.id\n LEFT JOIN {$t['reply']}\n ON {$t['reply']}.event_queue_id = {$t['queue']}.id\n LEFT JOIN {$t['forward']}\n ON {$t['forward']}.event_queue_id = {$t['queue']}.id\n LEFT JOIN {$t['bounce']}\n ON {$t['bounce']}.event_queue_id = {$t['queue']}.id\n LEFT JOIN {$t['delivered']}\n ON {$t['delivered']}.event_queue_id = {$t['queue']}.id\n AND {$t['bounce']}.id IS null\n LEFT JOIN {$t['urlopen']}\n ON {$t['urlopen']}.event_queue_id = {$t['queue']}.id\n LEFT JOIN {$t['spool']}\n ON {$t['spool']}.job_id = {$t['job']}.id\n WHERE {$t['job']}.mailing_id = {$mailing_id}\n AND {$t['job']}.is_test = 0\n GROUP BY {$t['job']}.id"); $report['jobs'] = array(); $report['event_totals'] = array(); $elements = array('queue', 'delivered', 'url', 'forward', 'reply', 'unsubscribe', 'optout', 'opened', 'bounce', 'spool'); // initialize various counters foreach ($elements as $field) { $report['event_totals'][$field] = 0; } while ($mailing->fetch()) { $row = array(); foreach ($elements as $field) { if (isset($mailing->{$field})) { $row[$field] = $mailing->{$field}; $report['event_totals'][$field] += $mailing->{$field}; } } // compute open total separately to discount duplicates // CRM-1258 $row['opened'] = CRM_Mailing_Event_BAO_Opened::getTotalCount($mailing_id, $mailing->id, TRUE); $report['event_totals']['opened'] += $row['opened']; // compute unsub total separately to discount duplicates // CRM-1783 $row['unsubscribe'] = CRM_Mailing_Event_BAO_Unsubscribe::getTotalCount($mailing_id, $mailing->id, TRUE, TRUE); $report['event_totals']['unsubscribe'] += $row['unsubscribe']; $row['optout'] = CRM_Mailing_Event_BAO_Unsubscribe::getTotalCount($mailing_id, $mailing->id, TRUE, FALSE); $report['event_totals']['optout'] += $row['optout']; foreach (array_keys(CRM_Mailing_BAO_MailingJob::fields()) as $field) { $row[$field] = $mailing->{$field}; } if ($mailing->queue) { $row['delivered_rate'] = 100.0 * $mailing->delivered / $mailing->queue; $row['bounce_rate'] = 100.0 * $mailing->bounce / $mailing->queue; $row['unsubscribe_rate'] = 100.0 * $row['unsubscribe'] / $mailing->queue; $row['optout_rate'] = 100.0 * $row['optout'] / $mailing->queue; } else { $row['delivered_rate'] = 0; $row['bounce_rate'] = 0; $row['unsubscribe_rate'] = 0; $row['optout_rate'] = 0; } $row['links'] = array('clicks' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=click&mid={$mailing_id}&jid={$mailing->id}"), 'queue' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=queue&mid={$mailing_id}&jid={$mailing->id}"), 'delivered' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=delivered&mid={$mailing_id}&jid={$mailing->id}"), 'bounce' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=bounce&mid={$mailing_id}&jid={$mailing->id}"), 'unsubscribe' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=unsubscribe&mid={$mailing_id}&jid={$mailing->id}"), 'forward' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=forward&mid={$mailing_id}&jid={$mailing->id}"), 'reply' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=reply&mid={$mailing_id}&jid={$mailing->id}"), 'opened' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=opened&mid={$mailing_id}&jid={$mailing->id}")); foreach (array('scheduled_date', 'start_date', 'end_date') as $key) { $row[$key] = CRM_Utils_Date::customFormat($row[$key]); } $report['jobs'][] = $row; } $newTableSize = CRM_Mailing_BAO_Recipients::mailingSize($mailing_id); // we need to do this for backward compatibility, since old mailings did not // use the mailing_recipients table if ($newTableSize > 0) { $report['event_totals']['queue'] = $newTableSize; } else { $report['event_totals']['queue'] = self::getRecipientsCount($mailing_id, $mailing_id); } if (!empty($report['event_totals']['queue'])) { $report['event_totals']['delivered_rate'] = 100.0 * $report['event_totals']['delivered'] / $report['event_totals']['queue']; $report['event_totals']['bounce_rate'] = 100.0 * $report['event_totals']['bounce'] / $report['event_totals']['queue']; $report['event_totals']['unsubscribe_rate'] = 100.0 * $report['event_totals']['unsubscribe'] / $report['event_totals']['queue']; $report['event_totals']['optout_rate'] = 100.0 * $report['event_totals']['optout'] / $report['event_totals']['queue']; } else { $report['event_totals']['delivered_rate'] = 0; $report['event_totals']['bounce_rate'] = 0; $report['event_totals']['unsubscribe_rate'] = 0; $report['event_totals']['optout_rate'] = 0; } /* Get the click-through totals, grouped by URL */ $mailing->query("\n SELECT {$t['url']}.url,\n {$t['url']}.id,\n COUNT({$t['urlopen']}.id) as clicks,\n COUNT(DISTINCT {$t['queue']}.id) as unique_clicks\n FROM {$t['url']}\n LEFT JOIN {$t['urlopen']}\n ON {$t['urlopen']}.trackable_url_id = {$t['url']}.id\n LEFT JOIN {$t['queue']}\n ON {$t['urlopen']}.event_queue_id = {$t['queue']}.id\n LEFT JOIN {$t['job']}\n ON {$t['queue']}.job_id = {$t['job']}.id\n WHERE {$t['url']}.mailing_id = {$mailing_id}\n AND {$t['job']}.is_test = 0\n GROUP BY {$t['url']}.id"); $report['click_through'] = array(); while ($mailing->fetch()) { $report['click_through'][] = array('url' => $mailing->url, 'link' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=click&mid={$mailing_id}&uid={$mailing->id}"), 'link_unique' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=click&mid={$mailing_id}&uid={$mailing->id}&distinct=1"), 'clicks' => $mailing->clicks, 'unique' => $mailing->unique_clicks, 'rate' => CRM_Utils_Array::value('delivered', $report['event_totals']) ? 100.0 * $mailing->unique_clicks / $report['event_totals']['delivered'] : 0); } $report['event_totals']['links'] = array('clicks' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=click&mid={$mailing_id}"), 'clicks_unique' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=click&mid={$mailing_id}&distinct=1"), 'queue' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=queue&mid={$mailing_id}"), 'delivered' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=delivered&mid={$mailing_id}"), 'bounce' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=bounce&mid={$mailing_id}"), 'unsubscribe' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=unsubscribe&mid={$mailing_id}"), 'optout' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=optout&mid={$mailing_id}"), 'forward' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=forward&mid={$mailing_id}"), 'reply' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=reply&mid={$mailing_id}"), 'opened' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=opened&mid={$mailing_id}")); $actionLinks = array(CRM_Core_Action::VIEW => array('name' => ts('Report'))); if (CRM_Core_Permission::check('view all contacts')) { $actionLinks[CRM_Core_Action::ADVANCED] = array('name' => ts('Advanced Search'), 'url' => 'civicrm/contact/search/advanced'); } $action = array_sum(array_keys($actionLinks)); $report['event_totals']['actionlinks'] = array(); foreach (array('clicks', 'clicks_unique', 'queue', 'delivered', 'bounce', 'unsubscribe', 'forward', 'reply', 'opened', 'optout') as $key) { $url = 'mailing/detail'; $reportFilter = "reset=1&mailing_id_value={$mailing_id}"; $searchFilter = "force=1&mailing_id=%%mid%%"; switch ($key) { case 'delivered': $reportFilter .= "&delivery_status_value=successful"; $searchFilter .= "&mailing_delivery_status=Y"; break; case 'bounce': $url = "mailing/bounce"; $searchFilter .= "&mailing_delivery_status=N"; break; case 'forward': $reportFilter .= "&is_forwarded_value=1"; $searchFilter .= "&mailing_forward=1"; break; case 'reply': $reportFilter .= "&is_replied_value=1"; $searchFilter .= "&mailing_reply_status=Y"; break; case 'unsubscribe': $reportFilter .= "&is_unsubscribed_value=1"; $searchFilter .= "&mailing_unsubscribe=1"; break; case 'optout': $reportFilter .= "&is_optout_value=1"; $searchFilter .= "&mailing_optout=1"; break; case 'opened': $url = "mailing/opened"; $searchFilter .= "&mailing_open_status=Y"; break; case 'clicks': case 'clicks_unique': $url = "mailing/clicks"; $searchFilter .= "&mailing_click_status=Y"; break; } $actionLinks[CRM_Core_Action::VIEW]['url'] = CRM_Report_Utils_Report::getNextUrl($url, $reportFilter, FALSE, TRUE); if (array_key_exists(CRM_Core_Action::ADVANCED, $actionLinks)) { $actionLinks[CRM_Core_Action::ADVANCED]['qs'] = $searchFilter; } $report['event_totals']['actionlinks'][$key] = CRM_Core_Action::formLink($actionLinks, $action, array('mid' => $mailing_id), ts('more'), FALSE, 'mailing.report.action', 'Mailing', $mailing_id); } return $report; }
/** * Returns array of contacts who are members of the specified group. * * @param CRM_Contact $group A valid group object (passed by reference) * @param array $returnProperties Which properties * should be included in the returned Contact object(s). If NULL, * the default set of contact properties will be * included. group_contact properties (such as 'status', * ' in_date', etc.) are included automatically.Note:Do not inclue * Id releted properties. * @param text $status A valid status value ('Added', 'Pending', 'Removed'). * @param text $sort Associative array of * one or more "property_name"=>"sort direction" * pairs which will control order of Contact objects returned. * @param Int $offset Starting row index. * @param Int $row_count Maximum number of rows to returns. * * * @return $contactArray Array of contacts who are members of the specified group * * @access public */ function getGroupContacts(&$group, $returnProperties = null, $status = 'Added', $sort = null, $offset = null, $row_count = null) { $query = "SELECT * FROM civicrm_group WHERE id = " . CRM_Utils_Type::escape($group->id, 'Integer'); $groupDAO =& new CRM_Contact_DAO_Group(); $groupDAO->id = $group->id; if (!$groupDAO->find(true)) { return CRM_Core_Error::createError("Could not locate group with id: {$id}"); } // make sure user has got permission to view this group if (!CRM_Contact_BAO_Group::checkPermission($groupDAO->id, $groupDAO->title)) { return CRM_Core_Error::createError("You do not have permission to access group with id: {$id}"); } $query = ''; if (empty($returnProperties)) { $query = "SELECT civicrm_contact.id as contact_id,\n civicrm_email.email as email"; //$query = "SELECT *,civicrm_contact.id as contact_id, (talk to lobo before re-enabling this) //civicrm_email.email as email"; } else { $query = "SELECT civicrm_contact.id as contact_id ,"; $query .= implode(',', $returnProperties); } $fv = array('group' => array($group->id => true)); if ($status) { $fv['group_contact_status'] = array($status => true); } else { $fv['group_contact_status'] = array('Added' => true, 'Removed' => true, 'Pending' => true); } $tables = array(CRM_Contact_BAO_GroupContact::getTableName() => true, CRM_Core_BAO_Email::getTableName() => true, CRM_Contact_BAO_Contact::getTableName() => true, CRM_Contact_BAO_Group::getTableName() => true); $inner = array(); $whereTables = array(); $where = CRM_Contact_BAO_Query::getWhereClause($fv, null, $tables, $whereTables); $permission = CRM_Core_Permission::whereClause(CRM_CORE_PERMISSION_VIEW, $tables, $whereTables); $from = CRM_Contact_BAO_Query::fromClause($tables, $inner); $query .= " {$from} WHERE {$permission} AND {$where} "; if ($sort != null) { $order = array(); foreach ($sort as $key => $direction) { $order[] = " {$key} {$direction} "; } $query .= " ORDER BY " . implode(',', $order); } if ($offset != null && $row_count != null) { $query .= " LIMIT {$offset}, {$row_count}"; } // CRM_Core_Error::debug( 'q', $query ); $dao =& new CRM_Contact_DAO_Contact(); $dao->query($query); // this is quite inefficient, we need to change the return // values in docs $contactArray = array(); while ($dao->fetch()) { $contactArray[] = clone $dao; } return $contactArray; }
/** * 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; }
/** * Get all of the ACLs for a contact through ACL groups owned by Contact * groups. * * @param int $contact_id - ID of a contact to search for * @return array - Array of assoc. arrays of ACL rules * @access public * @static */ function &getGroupACLGroups($contact_id) { $contact_id = CRM_Utils_Type::escape($contact_id, 'Integer'); $rule =& new CRM_Core_BAO_ACL(); $acl = CRM_Core_BAO_ACL::getTableName(); $aclGroup = CRM_Core_BAO_ACLGroup::getTableName(); $c2g = CRM_Contact_BAO_GroupContact::getTableName(); $group = CRM_Contact_BAO_Group::getTableName(); $query = " SELECT {$acl}.* \n FROM {$acl}\n INNER JOIN {$aclGroup}\n ON {$acl}.entity_table = '{$aclGroup}'\n AND {$acl}.entity_id = {$aclGroup}.id\n \n INNER JOIN {$c2g}\n ON {$aclGroup}.entity_id = {$c2g}.group_id\n \n WHERE {$aclGroup}.entity_table = '{$group}'\n AND {$aclGroup}.is_active = 1\n AND {$c2g}.contact_id = {$contact_id}\n AND {$c2g}.status = 'Added'"; $results = array(); $rule->query($query); while ($rule->fetch()) { $results[] =& $rule->toArray(); } return $results; }
/** * Form submission of new/edit campaign is processed. * * * @return void */ public function postProcess() { // store the submitted values in an array $params = $this->controller->exportValues($this->_name); $session = CRM_Core_Session::singleton(); $groups = array(); if (isset($this->_campaignId)) { if ($this->_action & CRM_Core_Action::DELETE) { CRM_Campaign_BAO_Campaign::del($this->_campaignId); CRM_Core_Session::setStatus(ts('Campaign has been deleted.'), ts('Record Deleted'), 'success'); $session->replaceUserContext(CRM_Utils_System::url('civicrm/campaign', 'reset=1&subPage=campaign')); return; } $params['id'] = $this->_campaignId; } else { $params['created_id'] = $session->get('userID'); $params['created_date'] = date('YmdHis'); } // format params $params['start_date'] = CRM_Utils_Date::processDate($params['start_date'], $params['start_date_time']); $params['end_date'] = CRM_Utils_Date::processDate($params['end_date'], $params['end_date_time'], TRUE); $params['is_active'] = CRM_Utils_Array::value('is_active', $params, FALSE); $params['last_modified_id'] = $session->get('userID'); $params['last_modified_date'] = date('YmdHis'); if (is_array($params['includeGroups'])) { foreach ($params['includeGroups'] as $key => $id) { if ($id) { $groups['include'][] = $id; } } } $params['groups'] = $groups; // delete previous includes/excludes, if campaign already existed $groupTableName = CRM_Contact_BAO_Group::getTableName(); $dao = new CRM_Campaign_DAO_CampaignGroup(); $dao->campaign_id = $this->_campaignId; $dao->entity_table = $groupTableName; $dao->find(); while ($dao->fetch()) { $dao->delete(); } //process custom data. $customFields = CRM_Core_BAO_CustomField::getFields('Campaign', FALSE, FALSE, CRM_Utils_Array::value('campaign_type_id', $params)); $params['custom'] = CRM_Core_BAO_CustomField::postProcess($params, $customFields, $this->_campaignId, 'Campaign'); $result = CRM_Campaign_BAO_Campaign::create($params); if ($result) { CRM_Core_Session::setStatus(ts('Campaign %1 has been saved.', array(1 => $result->title)), ts('Saved'), 'success'); $session->pushUserContext(CRM_Utils_System::url('civicrm/campaign', 'reset=1&subPage=campaign')); } $buttonName = $this->controller->getButtonName(); if ($buttonName == $this->getButtonName('upload', 'new')) { CRM_Core_Session::setStatus(ts(' You can add another Campaign.'), '', 'info'); $session->replaceUserContext(CRM_Utils_System::url('civicrm/campaign/add', 'reset=1&action=add')); } else { $session->replaceUserContext(CRM_Utils_System::url('civicrm/campaign', 'reset=1&subPage=campaign')); } }
/** * Whitelist of possible values for the entity_table field * @return array */ public static function mailingGroupEntityTables() { $tables = array(CRM_Contact_BAO_Group::getTableName(), CRM_Mailing_BAO_Mailing::getTableName()); // Identical keys & values return array_combine($tables, $tables); }
/** * Generate a report. Fetch event count information, mailing data, and job * status. * * @param int $id The mailing id to report * @param boolean $skipDetails whether return all detailed report * @return array Associative array of reporting data * @access public * @static */ public static function &report($id, $skipDetails = false) { $mailing_id = CRM_Utils_Type::escape($id, 'Integer'); $mailing = new CRM_Mailing_BAO_Mailing(); require_once 'CRM/Mailing/Event/BAO/Opened.php'; require_once 'CRM/Mailing/Event/BAO/Reply.php'; require_once 'CRM/Mailing/Event/BAO/Unsubscribe.php'; require_once 'CRM/Mailing/Event/BAO/Forward.php'; require_once 'CRM/Mailing/Event/BAO/TrackableURLOpen.php'; require_once 'CRM/Mailing/BAO/Spool.php'; $t = array('mailing' => self::getTableName(), 'mailing_group' => CRM_Mailing_DAO_Group::getTableName(), 'group' => CRM_Contact_BAO_Group::getTableName(), 'job' => CRM_Mailing_BAO_Job::getTableName(), 'queue' => CRM_Mailing_Event_BAO_Queue::getTableName(), 'delivered' => CRM_Mailing_Event_BAO_Delivered::getTableName(), 'opened' => CRM_Mailing_Event_BAO_Opened::getTableName(), 'reply' => CRM_Mailing_Event_BAO_Reply::getTableName(), 'unsubscribe' => CRM_Mailing_Event_BAO_Unsubscribe::getTableName(), 'bounce' => CRM_Mailing_Event_BAO_Bounce::getTableName(), 'forward' => CRM_Mailing_Event_BAO_Forward::getTableName(), 'url' => CRM_Mailing_BAO_TrackableURL::getTableName(), 'urlopen' => CRM_Mailing_Event_BAO_TrackableURLOpen::getTableName(), 'component' => CRM_Mailing_BAO_Component::getTableName(), 'spool' => CRM_Mailing_BAO_Spool::getTableName()); $report = array(); /* Get the mailing info */ $mailing->query("\n SELECT {$t['mailing']}.*\n FROM {$t['mailing']}\n WHERE {$t['mailing']}.id = {$mailing_id}"); $mailing->fetch(); $report['mailing'] = array(); foreach (array_keys(self::fields()) as $field) { $report['mailing'][$field] = $mailing->{$field}; } //mailing report is called by activity //we dont need all detail report if ($skipDetails) { return $report; } /* Get the component info */ $query = array(); $components = array('header' => ts('Header'), 'footer' => ts('Footer'), 'reply' => ts('Reply'), 'unsubscribe' => ts('Unsubscribe'), 'optout' => ts('Opt-Out')); foreach (array_keys($components) as $type) { $query[] = "SELECT {$t['component']}.name as name,\n '{$type}' as type,\n {$t['component']}.id as id\n FROM {$t['component']}\n INNER JOIN {$t['mailing']}\n ON {$t['mailing']}.{$type}_id =\n {$t['component']}.id\n WHERE {$t['mailing']}.id = {$mailing_id}"; } $q = '(' . implode(') UNION (', $query) . ')'; $mailing->query($q); $report['component'] = array(); while ($mailing->fetch()) { $report['component'][] = array('type' => $components[$mailing->type], 'name' => $mailing->name, 'link' => CRM_Utils_System::url('civicrm/mailing/component', "reset=1&action=update&id={$mailing->id}")); } /* Get the recipient group info */ $mailing->query("\n SELECT {$t['mailing_group']}.group_type as group_type,\n {$t['group']}.id as group_id,\n {$t['group']}.title as group_title,\n {$t['mailing']}.id as mailing_id,\n {$t['mailing']}.name as mailing_name\n FROM {$t['mailing_group']}\n LEFT JOIN {$t['group']}\n ON {$t['mailing_group']}.entity_id = {$t['group']}.id\n AND {$t['mailing_group']}.entity_table =\n '{$t['group']}'\n LEFT JOIN {$t['mailing']}\n ON {$t['mailing_group']}.entity_id =\n {$t['mailing']}.id\n AND {$t['mailing_group']}.entity_table =\n '{$t['mailing']}'\n\n WHERE {$t['mailing_group']}.mailing_id = {$mailing_id}\n "); $report['group'] = array('include' => array(), 'exclude' => array()); while ($mailing->fetch()) { $row = array(); if (isset($mailing->group_id)) { $row['id'] = $mailing->group_id; $row['name'] = $mailing->group_title; $row['link'] = CRM_Utils_System::url('civicrm/group/search', "reset=1&force=1&context=smog&gid={$row['id']}"); } else { $row['id'] = $mailing->mailing_id; $row['name'] = $mailing->mailing_name; $row['mailing'] = true; $row['link'] = CRM_Utils_System::url('civicrm/mailing/report', "mid={$row['id']}"); } if ($mailing->group_type == 'Include') { $report['group']['include'][] = $row; } else { $report['group']['exclude'][] = $row; } } /* Get the event totals, grouped by job (retries) */ $mailing->query("\n SELECT {$t['job']}.*,\n COUNT(DISTINCT {$t['queue']}.id) as queue,\n COUNT(DISTINCT {$t['delivered']}.id) as delivered,\n COUNT(DISTINCT {$t['reply']}.id) as reply,\n COUNT(DISTINCT {$t['forward']}.id) as forward,\n COUNT(DISTINCT {$t['bounce']}.id) as bounce,\n COUNT(DISTINCT {$t['urlopen']}.id) as url,\n COUNT(DISTINCT {$t['spool']}.id) as spool\n FROM {$t['job']}\n LEFT JOIN {$t['queue']}\n ON {$t['queue']}.job_id = {$t['job']}.id\n LEFT JOIN {$t['reply']}\n ON {$t['reply']}.event_queue_id = {$t['queue']}.id\n LEFT JOIN {$t['forward']}\n ON {$t['forward']}.event_queue_id = {$t['queue']}.id\n LEFT JOIN {$t['bounce']}\n ON {$t['bounce']}.event_queue_id = {$t['queue']}.id\n LEFT JOIN {$t['delivered']}\n ON {$t['delivered']}.event_queue_id = {$t['queue']}.id\n AND {$t['bounce']}.id IS null\n LEFT JOIN {$t['urlopen']}\n ON {$t['urlopen']}.event_queue_id = {$t['queue']}.id\n LEFT JOIN {$t['spool']}\n ON {$t['spool']}.job_id = {$t['job']}.id\n WHERE {$t['job']}.mailing_id = {$mailing_id}\n AND {$t['job']}.is_test = 0\n GROUP BY {$t['job']}.id"); $report['jobs'] = array(); $report['event_totals'] = array(); $elements = array('queue', 'delivered', 'url', 'forward', 'reply', 'unsubscribe', 'opened', 'bounce', 'spool'); // initialize various counters foreach ($elements as $field) { $report['event_totals'][$field] = 0; } while ($mailing->fetch()) { $row = array(); foreach ($elements as $field) { if (isset($mailing->{$field})) { $row[$field] = $mailing->{$field}; $report['event_totals'][$field] += $mailing->{$field}; } } // compute open total separately to discount duplicates // CRM-1258 $row['opened'] = CRM_Mailing_Event_BAO_Opened::getTotalCount($mailing_id, $mailing->id, true); $report['event_totals']['opened'] += $row['opened']; // compute unsub total separately to discount duplicates // CRM-1783 $row['unsubscribe'] = CRM_Mailing_Event_BAO_Unsubscribe::getTotalCount($mailing_id, $mailing->id, true); $report['event_totals']['unsubscribe'] += $row['unsubscribe']; foreach (array_keys(CRM_Mailing_BAO_Job::fields()) as $field) { $row[$field] = $mailing->{$field}; } if ($mailing->queue) { $row['delivered_rate'] = 100.0 * $mailing->delivered / $mailing->queue; $row['bounce_rate'] = 100.0 * $mailing->bounce / $mailing->queue; $row['unsubscribe_rate'] = 100.0 * $row['unsubscribe'] / $mailing->queue; } else { $row['delivered_rate'] = 0; $row['bounce_rate'] = 0; $row['unsubscribe_rate'] = 0; } $row['links'] = array('clicks' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=click&mid={$mailing_id}&jid={$mailing->id}"), 'queue' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=queue&mid={$mailing_id}&jid={$mailing->id}"), 'delivered' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=delivered&mid={$mailing_id}&jid={$mailing->id}"), 'bounce' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=bounce&mid={$mailing_id}&jid={$mailing->id}"), 'unsubscribe' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=unsubscribe&mid={$mailing_id}&jid={$mailing->id}"), 'forward' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=forward&mid={$mailing_id}&jid={$mailing->id}"), 'reply' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=reply&mid={$mailing_id}&jid={$mailing->id}"), 'opened' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=opened&mid={$mailing_id}&jid={$mailing->id}")); foreach (array('scheduled_date', 'start_date', 'end_date') as $key) { $row[$key] = CRM_Utils_Date::customFormat($row[$key]); } $report['jobs'][] = $row; } $report['event_totals']['queue'] = self::getRecipientsCount($mailing_id, false, $mailing_id); if (CRM_Utils_Array::value('queue', $report['event_totals'])) { $report['event_totals']['delivered_rate'] = 100.0 * $report['event_totals']['delivered'] / $report['event_totals']['queue']; $report['event_totals']['bounce_rate'] = 100.0 * $report['event_totals']['bounce'] / $report['event_totals']['queue']; $report['event_totals']['unsubscribe_rate'] = 100.0 * $report['event_totals']['unsubscribe'] / $report['event_totals']['queue']; } else { $report['event_totals']['delivered_rate'] = 0; $report['event_totals']['bounce_rate'] = 0; $report['event_totals']['unsubscribe_rate'] = 0; } /* Get the click-through totals, grouped by URL */ $mailing->query("\n SELECT {$t['url']}.url,\n {$t['url']}.id,\n COUNT({$t['urlopen']}.id) as clicks,\n COUNT(DISTINCT {$t['queue']}.id) as unique_clicks\n FROM {$t['url']}\n LEFT JOIN {$t['urlopen']}\n ON {$t['urlopen']}.trackable_url_id = {$t['url']}.id\n LEFT JOIN {$t['queue']}\n ON {$t['urlopen']}.event_queue_id = {$t['queue']}.id\n LEFT JOIN {$t['job']}\n ON {$t['queue']}.job_id = {$t['job']}.id\n WHERE {$t['url']}.mailing_id = {$mailing_id}\n AND {$t['job']}.is_test = 0\n GROUP BY {$t['url']}.id"); $report['click_through'] = array(); while ($mailing->fetch()) { $report['click_through'][] = array('url' => $mailing->url, 'link' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=click&mid={$mailing_id}&uid={$mailing->id}"), 'link_unique' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=click&mid={$mailing_id}&uid={$mailing->id}&distinct=1"), 'clicks' => $mailing->clicks, 'unique' => $mailing->unique_clicks, 'rate' => CRM_Utils_Array::value('delivered', $report['event_totals']) ? 100.0 * $mailing->unique_clicks / $report['event_totals']['delivered'] : 0); } $report['event_totals']['links'] = array('clicks' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=click&mid={$mailing_id}"), 'clicks_unique' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=click&mid={$mailing_id}&distinct=1"), 'queue' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=queue&mid={$mailing_id}"), 'delivered' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=delivered&mid={$mailing_id}"), 'bounce' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=bounce&mid={$mailing_id}"), 'unsubscribe' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=unsubscribe&mid={$mailing_id}"), 'forward' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=forward&mid={$mailing_id}"), 'reply' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=reply&mid={$mailing_id}"), 'opened' => CRM_Utils_System::url('civicrm/mailing/report/event', "reset=1&event=opened&mid={$mailing_id}")); return $report; }
/** * Get the domain object given a subscribe event * * @param int $subscribe_id ID of the subscribe event * @return object $domain The domain owning the event * @access public * @static */ function &getDomain($subscribe_id) { $dao =& new CRM_Core_Dao(); $subscribe = CRM_Mailing_Event_BAO_Subscribe::getTableName(); require_once 'CRM/Contact/BAO/Group.php'; $group = CRM_Contact_BAO_Group::getTableName(); $dao->query("SELECT {$group}.domain_id as domain_id\n FROM {$group}\n INNER JOIN {$subscribe}\n ON {$subscribe}.group_id = {$group}.id\n WHERE {$subscribe}.id = " . CRM_Utils_Type::escape($subscribe_id, 'Integer')); $dao->fetch(); if (empty($dao->domain_id)) { return null; } require_once 'CRM/Core/BAO/Domain.php'; return CRM_Core_BAO_Domain::getDomainById($dao->domain_id); }
/** * Add exclude group to mailing. * @param int $mailingId * @param int $groupId * * @throws \CiviCRM_API3_Exception */ function excludeGroup($mailingId, $groupId) { $params = array('mailing_id' => $mailingId, 'group_type' => 'Exclude', 'entity_table' => CRM_Contact_BAO_Group::getTableName(), 'values' => array(array('entity_id' => $groupId))); civicrm_api3('mailing_group', 'replace', $params); }
public function postProcess() { $values = $this->controller->exportValues($this->_name); //build hidden smart group. when user want to send mailing //through search contact-> more action -> send Mailing. CRM-3711 $groups = array(); if ($this->_searchBasedMailing && $this->_contactIds) { //get the hidden smart group id. $ssId = $this->get('ssID'); $session = CRM_Core_Session::singleton(); $hiddenSmartParams = array('group_type' => array('2' => 1), 'form_values' => $this->get('formValues'), 'saved_search_id' => $ssId, 'search_custom_id' => $this->get('customSearchID'), 'search_context' => $this->get('context')); require_once 'CRM/Contact/BAO/Group.php'; list($smartGroupId, $savedSearchId) = CRM_Contact_BAO_Group::createHiddenSmartGroup($hiddenSmartParams); //set the saved search id. if (!$ssId) { if ($savedSearchId) { $this->set('ssID', $savedSearchId); } else { CRM_Core_Error::fatal(); } } //get the base group for this mailing, CRM-3711 $groups['base'] = array($values['baseGroup']); $values['includeGroups'][] = $smartGroupId; } foreach (array('name', 'group_id', 'search_id', 'search_args') as $n) { if (CRM_Utils_Array::value($n, $values)) { $params[$n] = $values[$n]; } } $qf_Group_submit = $this->controller->exportValue($this->_name, '_qf_Group_submit'); $this->set('name', $params['name']); $inGroups = $values['includeGroups']; $outGroups = $values['excludeGroups']; $inMailings = $values['includeMailings']; $outMailings = $values['excludeMailings']; if (is_array($inGroups)) { foreach ($inGroups as $key => $id) { if ($id) { $groups['include'][] = $id; } } } if (is_array($outGroups)) { foreach ($outGroups as $key => $id) { if ($id) { $groups['exclude'][] = $id; } } } $mailings = array(); if (is_array($inMailings)) { foreach ($inMailings as $key => $id) { if ($id) { $mailings['include'][] = $id; } } } if (is_array($outMailings)) { foreach ($outMailings as $key => $id) { if ($id) { $mailings['exclude'][] = $id; } } } $session = CRM_Core_Session::singleton(); $params['groups'] = $groups; $params['mailings'] = $mailings; if ($this->get('mailing_id')) { $ids = array(); // don't create a new mailing if already exists $ids['mailing_id'] = $this->get('mailing_id'); $groupTableName = CRM_Contact_BAO_Group::getTableName(); $mailingTableName = CRM_Mailing_BAO_Mailing::getTableName(); // delete previous includes/excludes, if mailing already existed require_once 'CRM/Contact/DAO/Group.php'; foreach (array('groups', 'mailings') as $entity) { $mg = new CRM_Mailing_DAO_Group(); $mg->mailing_id = $ids['mailing_id']; $mg->entity_table = $entity == 'groups' ? $groupTableName : $mailingTableName; $mg->find(); while ($mg->fetch()) { $mg->delete(); } } } else { // new mailing, so lets set the created_id $session = CRM_Core_Session::singleton(); $params['created_id'] = $session->get('userID'); $params['created_date'] = date('YmdHis'); } require_once 'CRM/Mailing/BAO/Mailing.php'; $mailing = CRM_Mailing_BAO_Mailing::create($params, $ids); $this->set('mailing_id', $mailing->id); $count = CRM_Mailing_BAO_Mailing::getRecipientsCount(true, false, $mailing->id); $this->set('count', $count); $this->assign('count', $count); $this->set('groups', $groups); $this->set('mailings', $mailings); if ($qf_Group_submit) { //when user perform mailing from search context //redirect it to search result CRM-3711. $ssID = $this->get('ssID'); $context = $this->get('context'); if ($ssID && $this->_searchBasedMailing) { if ($this->_action == CRM_Core_Action::BASIC) { $fragment = 'search'; } else { if ($this->_action == CRM_Core_Action::PROFILE) { $fragment = 'search/builder'; } else { if ($this->_action == CRM_Core_Action::ADVANCED) { $fragment = 'search/advanced'; } else { $fragment = 'search/custom'; } } } $context = $this->get('context'); if (!CRM_Contact_Form_Search::isSearchContext($context)) { $context = 'search'; } $urlParams = "force=1&reset=1&ssID={$ssID}&context={$context}"; $qfKey = CRM_Utils_Request::retrieve('qfKey', 'String', $this); if (CRM_Utils_Rule::qfKey($qfKey)) { $urlParams .= "&qfKey={$qfKey}"; } $draftURL = CRM_Utils_System::url('civicrm/mailing/browse/unscheduled', 'scheduled=false&reset=1'); $status = ts("Your mailing has been saved. You can continue later by clicking the 'Continue' action to resume working on it.<br /> From <a href='%1'>Draft and Unscheduled Mailings</a>.", array(1 => $draftURL)); CRM_Core_Session::setStatus($status); //replace user context to search. $url = CRM_Utils_System::url('civicrm/contact/' . $fragment, $urlParams); CRM_Utils_System::redirect($url); } else { $status = ts("Your mailing has been saved. Click the 'Continue' action to resume working on it."); CRM_Core_Session::setStatus($status); $url = CRM_Utils_System::url('civicrm/mailing/browse/unscheduled', 'scheduled=false&reset=1'); CRM_Utils_System::redirect($url); } } }
/** * Resubscribe a contact to the groups, he/she was unsubscribed from. * * @param int $job_id * The job ID. * @param int $queue_id * The Queue Event ID of the recipient. * @param string $hash * The hash. * * @return array|null * $groups Array of all groups to which the contact was added, or null if the queue event could not be found. */ public static function &resub_to_mailing($job_id, $queue_id, $hash) { // 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; } // check if this queue_id was actually unsubscribed $ue = new CRM_Mailing_Event_BAO_Unsubscribe(); $ue->event_queue_id = $queue_id; $ue->org_unsubscribe = 0; if (!$ue->find(TRUE)) { return $success; } $contact_id = $q->contact_id; $transaction = new CRM_Core_Transaction(); $do = new CRM_Core_DAO(); $mg = CRM_Mailing_DAO_MailingGroup::getTableName(); $job = CRM_Mailing_BAO_MailingJob::getTableName(); $mailing = CRM_Mailing_BAO_Mailing::getTableName(); $group = CRM_Contact_BAO_Group::getTableName(); $gc = CRM_Contact_BAO_GroupContact::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 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(); $mailings = array(); while ($do->fetch()) { if ($do->entity_table == $group) { $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; } } } $group_ids = array_keys($groups); $base_groups = NULL; CRM_Utils_Hook::unsubscribeGroups('resubscribe', $mailing_id, $contact_id, $group_ids, $base_groups); // 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 FROM {$group}\n LEFT JOIN {$gc}\n ON {$gc}.group_id = {$group}.id\n WHERE {$group}.id IN (" . implode(', ', $group_ids) . ")\n AND ({$group}.saved_search_id is not null\n OR ({$gc}.contact_id = {$contact_id}\n AND {$gc}.status = 'Removed')\n )"); while ($do->fetch()) { $groups[$do->group_id] = $do->title; } $contacts = array($contact_id); foreach ($groups as $group_id => $group_name) { $notadded = 0; if ($group_name) { list($total, $added, $notadded) = CRM_Contact_BAO_GroupContact::addContactsToGroup($contacts, $group_id, 'Email'); } if ($notadded) { unset($groups[$group_id]); } } // remove entry from Unsubscribe table. $ue = new CRM_Mailing_Event_BAO_Unsubscribe(); $ue->event_queue_id = $queue_id; $ue->org_resubscribe = 0; if ($ue->find(TRUE)) { $ue->delete(); } $transaction->commit(); return $groups; }
public function postProcess() { $values = $this->controller->exportValues($this->_name); $groups = array(); foreach (array('name', 'group_id', 'is_sms') as $n) { if (!empty($values[$n])) { $params[$n] = $values[$n]; } } $qf_Group_submit = $this->controller->exportValue($this->_name, '_qf_Group_submit'); $this->set('name', $params['name']); $inGroups = $values['includeGroups']; $outGroups = $values['excludeGroups']; $inMailings = $values['includeMailings']; $outMailings = $values['excludeMailings']; if (is_array($inGroups)) { foreach ($inGroups as $key => $id) { if ($id) { $groups['include'][] = $id; } } } if (is_array($outGroups)) { foreach ($outGroups as $key => $id) { if ($id) { $groups['exclude'][] = $id; } } } $mailings = array(); if (is_array($inMailings)) { foreach ($inMailings as $key => $id) { if ($id) { $mailings['include'][] = $id; } } } if (is_array($outMailings)) { foreach ($outMailings as $key => $id) { if ($id) { $mailings['exclude'][] = $id; } } } $session = CRM_Core_Session::singleton(); $params['groups'] = $groups; $params['mailings'] = $mailings; $ids = array(); if ($this->get('mailing_id')) { // don't create a new mass sms if already exists $ids['mailing_id'] = $this->get('mailing_id'); $groupTableName = CRM_Contact_BAO_Group::getTableName(); $mailingTableName = CRM_Mailing_BAO_Mailing::getTableName(); // delete previous includes/excludes, if mailing already existed foreach (array('groups', 'mailings') as $entity) { $mg = new CRM_Mailing_DAO_MailingGroup(); $mg->mailing_id = $ids['mailing_id']; $mg->entity_table = $entity == 'groups' ? $groupTableName : $mailingTableName; $mg->find(); while ($mg->fetch()) { $mg->delete(); } } } else { // new mailing, so lets set the created_id $session = CRM_Core_Session::singleton(); $params['created_id'] = $session->get('userID'); $params['created_date'] = date('YmdHis'); } $mailing = CRM_Mailing_BAO_Mailing::create($params, $ids); $this->set('mailing_id', $mailing->id); // also compute the recipients and store them in the mailing recipients table CRM_Mailing_BAO_Mailing::getRecipients($mailing->id, $mailing->id, TRUE, FALSE, 'sms'); $count = CRM_Mailing_BAO_Recipients::mailingSize($mailing->id); $this->set('count', $count); $this->assign('count', $count); $this->set('groups', $groups); $this->set('mailings', $mailings); if ($qf_Group_submit) { $status = ts("Your Mass SMS has been saved."); CRM_Core_Session::setStatus($status, ts('Saved'), 'success'); $url = CRM_Utils_System::url('civicrm/mailing', 'reset=1&sms=1'); return $this->controller->setDestination($url); } }
/** * Form submission of new/edit campaign is processed. * * @access public * @return None */ public function postProcess() { // store the submitted values in an array $params = $this->controller->exportValues($this->_name); $session = CRM_Core_Session::singleton(); $groups = array(); if (isset($this->_campaignId)) { if ($this->_action & CRM_Core_Action::DELETE) { CRM_Campaign_BAO_Campaign::del($this->_campaignId); CRM_Core_Session::setStatus(ts(' Campaign has been deleted.')); $session->replaceUserContext(CRM_Utils_System::url('civicrm/campaign', 'reset=1&subPage=campaign')); return; } $params['id'] = $this->_campaignId; } else { $params['created_id'] = $session->get('userID'); $params['created_date'] = date('YmdHis'); } // format params $params['start_date'] = CRM_Utils_Date::processDate($params['start_date'], $params['start_date_time']); $params['end_date'] = CRM_Utils_Date::processDate($params['end_date'], $params['end_date_time'], true); $params['is_active'] = CRM_Utils_Array::value('is_active', $params, false); $params['last_modified_id'] = $session->get('userID'); $params['last_modified_date'] = date('YmdHis'); if (is_array($params['includeGroups'])) { foreach ($params['includeGroups'] as $key => $id) { if ($id) { $groups['include'][] = $id; } } } $params['groups'] = $groups; // delete previous includes/excludes, if campaign already existed $groupTableName = CRM_Contact_BAO_Group::getTableName(); $dao = new CRM_Campaign_DAO_CampaignGroup(); $dao->campaign_id = $this->_campaignId; $dao->entity_table = $groupTableName; $dao->find(); while ($dao->fetch()) { $dao->delete(); } require_once 'CRM/Campaign/BAO/Campaign.php'; $result = CRM_Campaign_BAO_Campaign::create($params); if ($result) { CRM_Core_Session::setStatus(ts('Campaign %1 has been saved.', array(1 => $result->title))); $session->pushUserContext(CRM_Utils_System::url('civicrm/campaign', 'reset=1&subPage=campaign')); } if ($this->_context == 'dialog') { $returnArray = array('returnSuccess' => true); echo json_encode($returnArray); CRM_Utils_System::civiExit(); } $buttonName = $this->controller->getButtonName(); if ($buttonName == $this->getButtonName('next', 'new')) { CRM_Core_Session::setStatus(ts(' You can add another Campaign.')); $session->replaceUserContext(CRM_Utils_System::url('civicrm/campaign/add', 'reset=1&action=add')); } else { $session->replaceUserContext(CRM_Utils_System::url('civicrm/campaign', 'reset=1&subPage=campaign')); } }