Edit file File name : utils.php Content :<?php if (!defined('sugarEntry') || !sugarEntry) { die('Not A Valid Entry Point'); } /** * * SugarCRM Community Edition is a customer relationship management program developed by * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc. * * SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd. * Copyright (C) 2011 - 2018 SalesAgility Ltd. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License version 3 as published by the * Free Software Foundation with the addition of the following permission added * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License along with * this program; if not, see http://www.gnu.org/licenses or write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. * * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com. * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU Affero General Public License version 3. * * In accordance with Section 7(b) of the GNU Affero General Public License version 3, * these Appropriate Legal Notices must retain the display of the "Powered by * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not * reasonably feasible for technical reasons, the Appropriate Legal Notices must * display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM". */ /********************************************************************************* * Description: Defines the English language pack for the base application. * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc. * All Rights Reserved. * Contributor(s): ______________________________________.. ********************************************************************************/ /* *returns a list of objects a message can be scoped by, the list contacts the current campaign *name and list of all prospects associated with this campaign.. * */ function get_message_scope_dom($campaign_id, $campaign_name, $db = null, $mod_strings = array()) { if (empty($db)) { $db = DBManagerFactory::getInstance(); } if (empty($mod_strings) or !isset($mod_strings['LBL_DEFAULT'])) { global $current_language; $mod_strings = return_module_language($current_language, 'Campaigns'); } //find prospect list attached to this campaign.. $query = "SELECT prospect_list_id, prospect_lists.name "; $query .= "FROM prospect_list_campaigns "; $query .= "INNER join prospect_lists on prospect_lists.id = prospect_list_campaigns.prospect_list_id "; $query .= "WHERE prospect_lists.deleted = 0 "; $query .= "AND prospect_list_campaigns.deleted=0 "; $query .= "AND campaign_id='". $db->quote($campaign_id)."'"; $query.=" and prospect_lists.list_type not like 'exempt%'"; //add campaign to the result array. //$return_array[$campaign_id]= $campaign_name . ' (' . $mod_strings['LBL_DEFAULT'] . ')'; $result=$db->query($query); while (($row=$db->fetchByAssoc($result))!= null) { $return_array[$row['prospect_list_id']]=$row['name']; } if (empty($return_array)) { $return_array=array(); } else { return $return_array; } } /** * Return bounce handling mailboxes for campaign. * * @param unknown_type $emails * @param unknown_type $get_box_name, Set it to false if want to get "From Name" other than the InboundEmail Name. * @return $get_name=true, bounce handling mailboxes' name; $get_name=false, bounce handling mailboxes' from name. */ function get_campaign_mailboxes(&$emails, $get_name=true) { if (!class_exists('InboundEmail')) { require('modules/InboundEmail/InboundEmail.php'); } $query = "select id,name,stored_options from inbound_email where mailbox_type='bounce' and status='Active' and deleted='0'"; $db = DBManagerFactory::getInstance(); $result=$db->query($query); while (($row=$db->fetchByAssoc($result))!= null) { if ($get_name) { $return_array[$row['id']] = $row['name']; } else { $return_array[$row['id']]= InboundEmail::get_stored_options_static('from_name', $row['name'], $row['stored_options']); } $emails[$row['id']]=InboundEmail::get_stored_options_static('from_addr', 'nobody@example.com', $row['stored_options']); } if (empty($return_array)) { $return_array=array(''=>''); } return $return_array; } function get_campaign_mailboxes_with_stored_options() { $ret = array(); if (!class_exists('InboundEmail')) { require('modules/InboundEmail/InboundEmail.php'); } $q = "SELECT id, name, stored_options FROM inbound_email WHERE mailbox_type='bounce' AND status='Active' AND deleted='0'"; $db = DBManagerFactory::getInstance(); $r = $db->query($q); while ($a = $db->fetchByAssoc($r)) { $ret[$a['id']] = unserialize(base64_decode($a['stored_options'])); } return $ret; } function get_campaign_mailboxes_with_stored_options_outbound() { $ret = array(); if (!class_exists('OutboundEmail')) { require('modules/OutboundEmail/OutboundEmail.php'); } $q = "SELECT * FROM outbound_email WHERE deleted='0'"; $db = DBManagerFactory::getInstance(); $r = $db->query($q); while ($a = $db->fetchByAssoc($r)) { $ret[$a['id']] = $a; } return $ret; } function log_campaign_activity($identifier, $activity, $update = true, $clicked_url_key = null) { $return_array = array(); $db = DBManagerFactory::getInstance(); //check to see if the identifier has been replaced with Banner string if ($identifier == 'BANNER' && isset($clicked_url_key) && !empty($clicked_url_key)) { // create md5 encrypted string using the client ip, this will be used for tracker id purposes $enc_id = 'BNR' . md5($_SERVER['REMOTE_ADDR']); //default the identifier to ip address $identifier = $enc_id; //if user has chosen to not use this mode of id generation, then replace identifier with plain guid. //difference is that guid will generate a new campaign log for EACH CLICK!! //encrypted generation will generate 1 campaign log and update the hit counter for each click if (isset($sugar_config['campaign_banner_id_generation']) && $sugar_config['campaign_banner_id_generation'] != 'md5') { $identifier = create_guid(); } //retrieve campaign log. // quote variable first $identifierQuoted = $db->quote($identifier); $clickedUrlKeyQuoted = $db->quote($clicked_url_key); $trkr_query = "select * from campaign_log where target_tracker_key='$identifierQuoted' and related_id = '$clickedUrlKeyQuoted'"; $current_trkr = $db->query($trkr_query); $row = $db->fetchByAssoc($current_trkr); //if campaign log is not retrieved (this is a new ip address or we have chosen to create //unique entries for each click if ($row == null || empty($row)) { //retrieve campaign id $clickedUrlKeyQuoted = $db->quote($clicked_url_key); $trkr_query = "select ct.campaign_id from campaign_trkrs ct, campaigns c where c.id = ct.campaign_id and ct.id = '$clickedUrlKeyQuoted'"; $current_trkr = $db->query($trkr_query); $row = $db->fetchByAssoc($current_trkr); //create new campaign log with minimal info. Note that we are creating new unique id //as target id, since we do not link banner/web campaigns to any users $data['target_id'] = "'" . create_guid() . "'"; $data['target_type'] = "'Prospects'"; $data['id'] = "'" . create_guid() . "'"; $data['campaign_id'] = $db->quoted($row['campaign_id']); $data['target_tracker_key'] = $db->quoted($identifier); $data['activity_type'] = $db->quoted($activity); $data['activity_date'] = "'" . TimeDate::getInstance()->nowDb() . "'"; $data['hits'] = 1; $data['deleted'] = 0; if (!empty($clicked_url_key)) { $data['related_id'] = $db->quoted($clicked_url_key); $data['related_type'] = "'" . 'CampaignTrackers' . "'"; } //values for return array.. $return_array['target_id'] = $data['target_id']; $return_array['target_type'] = $data['target_type']; //create insert query for new campaign log // quote variable first $dataArrayKeys = array_keys($data); $dataArrayKeysQuoted = array(); foreach ($dataArrayKeys as $dataArrayKey) { $dataArrayKeysQuoted[] = $db->quote($dataArrayKey); } $dataArrayKeysQuotedImplode = implode(', ', $dataArrayKeysQuoted); $insert_query = "INSERT into campaign_log (" . $dataArrayKeysQuotedImplode . ")"; $dataArrayValuesQuotedImplode = implode(', ', array_values($data)); $insert_query .= " VALUES (" . $dataArrayValuesQuotedImplode . ")"; $db->query($insert_query); } else { //campaign log already exists, so just set the return array and update hits column $return_array['target_id'] = $row['target_id']; $return_array['target_type'] = $row['target_type']; // quote variable first $rowIdQuoted = $db->quote($row['id']); $query1 = "update campaign_log set hits=hits+1 where id='$rowIdQuoted'"; $current = $db->query($query1); } //return array and exit return $return_array; } // quote variable first $identifierQuoted = $db->quote($identifier); $activityQuoted = $db->quote($activity); $query1 = "select * from campaign_log where target_tracker_key='$identifierQuoted' and activity_type='$activityQuoted'"; if (!empty($clicked_url_key)) { // quote variable first $clickedUrlKeyQuoted = $db->quote($clicked_url_key); $query1 .= " AND related_id='$clickedUrlKeyQuoted'"; } $current = $db->query($query1); $row = $db->fetchByAssoc($current); if ($row == null) { // quote variable first $identifierQuoted = $db->quote($identifier); $query = "select * from campaign_log where target_tracker_key='$identifierQuoted' and activity_type='targeted'"; $targeted = $db->query($query); $row = $db->fetchByAssoc($targeted); //if activity is removed and target type is users, then a user is trying to opt out //of emails. This is not possible as Users Table does not have opt out column. if ($row && (strtolower($row['target_type']) == 'users' && $activity == 'removed')) { $return_array['target_id'] = $row['target_id']; $return_array['target_type'] = $row['target_type']; return $return_array; } elseif ($row) { $data['id'] = "'" . create_guid() . "'"; $data['campaign_id'] = $db->quoted($row['campaign_id']); $data['target_tracker_key'] = $db->quoted($identifier); $data['target_id'] = $db->quoted($row['target_id']); $data['target_type'] = $db->quoted($row['target_type']); $data['activity_type'] = $db->quoted($activity); $data['activity_date'] = "'" . TimeDate::getInstance()->nowDb() . "'"; $data['list_id'] = $db->quoted($row['list_id']); $data['marketing_id'] = $db->quoted($row['marketing_id']); $data['hits'] = 1; $data['deleted'] = 0; if (!empty($clicked_url_key)) { $data['related_id'] = $db->quoted($clicked_url_key); $data['related_type'] = "'" . 'CampaignTrackers' . "'"; } //values for return array.. $return_array['target_id'] = $row['target_id']; $return_array['target_type'] = $row['target_type']; // quote variable first $dataArrayKeys = array_keys($data); $dataArrayKeysQuoted = array(); foreach ($dataArrayKeys as $dataArrayKey) { $dataArrayKeysQuoted[] = $db->quote($dataArrayKey); } $dataArrayKeysQuotedImplode = implode(', ', $dataArrayKeysQuoted); $insert_query = "INSERT into campaign_log (" . $dataArrayKeysQuotedImplode . ")"; $dataArrayValuesQuotedImplode = implode(', ', array_values($data)); $insert_query .= " VALUES (" . $dataArrayValuesQuotedImplode . ")"; $db->query($insert_query); } } else { $return_array['target_id'] = $row['target_id']; $return_array['target_type'] = $row['target_type']; // quote variable first $rowIdQuoted = $db->quote($row['id']); $query1 = "update campaign_log set hits=hits+1 where id='$rowIdQuoted'"; $current = $db->query($query1); } //check to see if this is a removal action if ($row && $activity == 'removed') { //retrieve campaign and check it's type, we are looking for newsletter Campaigns // // quote variable first $rowCampaignIdQuoted = $db->quote($row['campaign_id']); $query = "SELECT campaigns.* FROM campaigns WHERE campaigns.id = '" . $rowCampaignIdQuoted . "' "; $result = $db->query($query); if (!empty($result)) { $c_row = $db->fetchByAssoc($result); //if type is newsletter, then add campaign id to return_array for further processing. if (isset($c_row['campaign_type']) && $c_row['campaign_type'] == 'NewsLetter') { $return_array['campaign_id'] = $c_row['id']; } } } return $return_array; } /** * * This method is deprecated * @deprecated 62_Joneses - June 24, 2011 * @see campaign_log_lead_or_contact_entry() */ function campaign_log_lead_entry($campaign_id, $parent_bean, $child_bean, $activity_type) { campaign_log_lead_or_contact_entry($campaign_id, $parent_bean, $child_bean, $activity_type); } function campaign_log_lead_or_contact_entry($campaign_id, $parent_bean, $child_bean, $activity_type) { global $timedate; //create campaign tracker id and retrieve related bio bean $tracker_id = create_guid(); //create new campaign log record. $campaign_log = BeanFactory::newBean('CampaignLog'); $campaign_log->campaign_id = $campaign_id; $campaign_log->target_tracker_key = $tracker_id; $campaign_log->related_id = $parent_bean->id; $campaign_log->related_type = $parent_bean->module_dir; $campaign_log->target_id = $child_bean->id; $campaign_log->target_type = $child_bean->module_dir; $campaign_log->activity_date = $timedate->now(); $campaign_log->activity_type = $activity_type; //save the campaign log entry $campaign_log->save(); } function get_campaign_urls($campaign_id) { $return_array=array(); if (!empty($campaign_id)) { $db = DBManagerFactory::getInstance(); $campaign_id = $db->quote($campaign_id); $query1="select * from campaign_trkrs where campaign_id='$campaign_id' and deleted=0"; $current=$db->query($query1); while (($row=$db->fetchByAssoc($current)) != null) { $return_array['{'.$row['tracker_name'].'}']=$row['tracker_name'] . ' : ' . $row['tracker_url']; } } return $return_array; } /** * Queries for the list */ function get_subscription_lists_query($focus, $additional_fields = null) { //get all prospect lists belonging to Campaigns of type newsletter $all_news_type_pl_query = "select c.name, pl.list_type, plc.campaign_id, plc.prospect_list_id"; if (is_array($additional_fields) && !empty($additional_fields)) { $all_news_type_pl_query .= ', ' . implode(', ', $additional_fields); } $all_news_type_pl_query .= " from prospect_list_campaigns plc , prospect_lists pl, campaigns c "; $all_news_type_pl_query .= "where plc.campaign_id = c.id "; $all_news_type_pl_query .= "and plc.prospect_list_id = pl.id "; $all_news_type_pl_query .= "and c.campaign_type = 'NewsLetter' and pl.deleted = 0 and c.deleted=0 and plc.deleted=0 "; $all_news_type_pl_query .= "and (pl.list_type like 'exempt%' or pl.list_type ='default') "; $campaign = BeanFactory::newBean('Campaigns'); $campaign->table_name = 'c'; $accessWhere = $campaign->buildAccessWhere('list'); if (!empty($accessWhere)) { $all_news_type_pl_query .= ' AND ' . $accessWhere; } $all_news_type_list =$focus->db->query($all_news_type_pl_query); //build array of all newsletter campaigns $news_type_list_arr = array(); while ($row = $focus->db->fetchByAssoc($all_news_type_list)) { $news_type_list_arr[] = $row; } //now get all the campaigns that the current user is assigned to $all_plp_current = "select prospect_list_id from prospect_lists_prospects where related_id = '$focus->id' and deleted = 0 "; //build array of prospect lists that this user belongs to $current_plp =$focus->db->query($all_plp_current); $current_plp_arr = array(); while ($row = $focus->db->fetchByAssoc($current_plp)) { $current_plp_arr[] = $row; } return array('current_plp_arr' => $current_plp_arr, 'news_type_list_arr' => $news_type_list_arr); } /* * This function takes in a bean from a lead, prospect, or contact and returns an array containing * all subscription lists that the bean is a part of, and all the subscriptions that the bean is not * a part of. The array elements have the key names of "subscribed" and "unsusbscribed". These elements contain an array * of the corresponding list. In other words, the "subscribed" element holds another array that holds the subscription information. * * The subscription information is a concatenated string that holds the prospect list id and the campaign id, separated by at "@" character. * To parse these information string into something more usable, use the "process subscriptions()" function * * */ function get_subscription_lists($focus, $descriptions = false) { $subs_arr = array(); $unsubs_arr = array(); $results = get_subscription_lists_query($focus, $descriptions); $news_type_list_arr = $results['news_type_list_arr']; $current_plp_arr = $results['current_plp_arr']; //For each prospect list of type 'NewsLetter', check to see if current user is already in list, foreach ($news_type_list_arr as $news_list) { $match = 'false'; //perform this check against each prospect list this user belongs to foreach ($current_plp_arr as $current_list_key => $current_list) {//echo " new entry from current lists user is subscribed to-------------"; //compare current user list id against newsletter id if ($news_list['prospect_list_id'] == $current_list['prospect_list_id']) { //if id's match, user is subscribed to this list, check to see if this is an exempt list, if (strpos($news_list['list_type'], 'exempt')!== false) { //this is an exempt list, so process if (array_key_exists($news_list['name'], $subs_arr)) { //first, add to unsubscribed array $unsubs_arr[$news_list['name']] = $subs_arr[$news_list['name']]; //now remove from exempt subscription list unset($subs_arr[$news_list['name']]); } else { //we know this is an exempt list the user belongs to, but the //non exempt list has not been processed yet, so just add to exempt array $unsubs_arr[$news_list['name']] = "prospect_list@".$news_list['prospect_list_id']."@campaign@".$news_list['campaign_id']; } $match = 'false';//although match is false, this is an exempt array, so //it will not be added a second time down below } else { //this list is not exempt, and user is subscribed, so add to subscribed array, and unset from the unsubs_arr //as long as this list is not in exempt array if (!array_key_exists($news_list['name'], $unsubs_arr)) { $subs_arr[$news_list['name']] = "prospect_list@".$news_list['prospect_list_id']."@campaign@".$news_list['campaign_id']; $match = 'true'; unset($unsubs_arr[$news_list['name']]); } } } else { //do nothing, there is no match } } //if this newsletter id never matched a user subscription.. //..then add to available(unsubscribed) NewsLetters if list is not of type exempt if (($match == 'false') && (strpos($news_list['list_type'], 'exempt') === false) && (!array_key_exists($news_list['name'], $subs_arr))) { $unsubs_arr[$news_list['name']] = "prospect_list@".$news_list['prospect_list_id']."@campaign@".$news_list['campaign_id']; } } $return_array['unsubscribed'] = $unsubs_arr; $return_array['subscribed'] = $subs_arr; return $return_array; } /** * same function as get_subscription_lists, but with the data separated in an associated array */ function get_subscription_lists_keyed($focus) { $subs_arr = array(); $unsubs_arr = array(); $results = get_subscription_lists_query($focus, array('c.content', 'c.frequency')); $news_type_list_arr = $results['news_type_list_arr']; $current_plp_arr = $results['current_plp_arr']; //For each prospect list of type 'NewsLetter', check to see if current user is already in list, foreach ($news_type_list_arr as $news_list) { $match = false; $news_list_data = array('prospect_list_id' => $news_list['prospect_list_id'], 'campaign_id' => $news_list['campaign_id'], 'description' => $news_list['content'], 'frequency' => $news_list['frequency']); //perform this check against each prospect list this user belongs to foreach ($current_plp_arr as $current_list_key => $current_list) {//echo " new entry from current lists user is subscribed to-------------"; //compare current user list id against newsletter id if ($news_list['prospect_list_id'] == $current_list['prospect_list_id']) { //if id's match, user is subscribed to this list, check to see if this is an exempt list, if ($news_list['list_type'] == 'exempt') { //this is an exempt list, so process if (array_key_exists($news_list['name'], $subs_arr)) { //first, add to unsubscribed array $unsubs_arr[$news_list['name']] = $subs_arr[$news_list['name']]; //now remove from exempt subscription list unset($subs_arr[$news_list['name']]); } else { //we know this is an exempt list the user belongs to, but the //non exempt list has not been processed yet, so just add to exempt array $unsubs_arr[$news_list['name']] = $news_list_data; } $match = false;//although match is false, this is an exempt array, so //it will not be added a second time down below } else { //this list is not exempt, and user is subscribed, so add to subscribed array //as long as this list is not in exempt array if (!array_key_exists($news_list['name'], $unsubs_arr)) { $subs_arr[$news_list['name']] = $news_list_data; $match = 'true'; } } } else { //do nothing, there is no match } } //if this newsletter id never matched a user subscription.. //..then add to available(unsubscribed) NewsLetters if list is not of type exempt if (($match == false) && ($news_list['list_type'] != 'exempt')) { $unsubs_arr[$news_list['name']] = $news_list_data; } } $return_array['unsubscribed'] = $unsubs_arr; $return_array['subscribed'] = $subs_arr; return $return_array; } /* * This function will take an array of strings that have been created by the "get_subscription_lists()" method * and parses it into an array. The returned array has it's key's labeled in a specific fashion. * * Each string produces a campaign and a prospect id. The keys are appended with a number specifying the order * it was process in. So an input array containing 3 strings will have the following key values: * "prospect_list0", "campaign0" * "prospect_list1", "campaign1" * "prospect_list2", "campaign2" * * */ function process_subscriptions($subscription_string_to_parse) { $subs_change = array(); //parse through and build list of id's'. We are retrieving the campaign_id and //the prospect_list id from the selected subscriptions $i = 0; foreach ($subscription_string_to_parse as $subs_changes) { $subs_changes = trim($subs_changes); if (!empty($subs_changes)) { $ids_arr = explode("@", $subs_changes); $subs_change[$ids_arr[0].$i] = $ids_arr[1]; $subs_change[$ids_arr[2].$i] = $ids_arr[3]; $i = $i+1; } } return $subs_change; } /*This function is used by the Manage Subscriptions page in order to add the user * to the default prospect lists of the passed in campaign * Takes in campaign and prospect list id's we are subscribing to. * It also takes in a bean of the user (lead,target,prospect) we are subscribing * */ function subscribe($campaign, $prospect_list, $focus, $default_list = false) { $relationship = strtolower($focus->getObjectName()).'s'; //--grab all the lists for the passed in campaign id $pl_qry ="select id, list_type from prospect_lists where id in (select prospect_list_id from prospect_list_campaigns "; $pl_qry .= "where campaign_id = " . $focus->db->quoted($campaign) . ") and deleted = 0 "; $GLOBALS['log']->debug("In Campaigns Util: subscribe function, about to run query: ".$pl_qry); $pl_qry_result = $focus->db->query($pl_qry); //build the array of all prospect_lists $pl_arr = array(); while ($row = $focus->db->fetchByAssoc($pl_qry_result)) { $pl_arr[] = $row; } //--grab all the prospect_lists this user belongs to $curr_pl_qry ="select prospect_list_id, related_id from prospect_lists_prospects "; $curr_pl_qry .="where related_id = " . $focus->db->quoted($focus->id) . " and deleted = 0 "; $GLOBALS['log']->debug("In Campaigns Util: subscribe function, about to run query: ".$curr_pl_qry); $curr_pl_qry_result = $focus->db->query($curr_pl_qry); //build the array of all prospect lists that this current user belongs to $curr_pl_arr = array(); while ($row = $focus->db->fetchByAssoc($curr_pl_qry_result)) { $curr_pl_arr[] = $row; } //search through prospect lists for this campaign and identifiy the "unsubscription list" $exempt_id = ''; foreach ($pl_arr as $subscription_list) { if (strpos($subscription_list['list_type'], 'exempt')!== false) { $exempt_id = $subscription_list['id']; } if ($subscription_list['list_type'] == 'default' && $default_list) { $prospect_list = $subscription_list['id']; } } //now that we have exempt (unsubscription) list id, compare against user list id's if (!empty($exempt_id)) { $exempt_array['exempt_id'] = $exempt_id; foreach ($curr_pl_arr as $curr_subscription_list) { if ($curr_subscription_list['prospect_list_id'] == $exempt_id) { //--if we are in here then user is subscribing to a list in which they are exempt. // we need to remove the user from this unsubscription list. //Begin by retrieving unsubscription prospect list $exempt_subscription_list = BeanFactory::newBean('ProspectLists'); $exempt_result = $exempt_subscription_list->retrieve($exempt_id); if ($exempt_result == null) {//error happened while retrieving this list return; } //load realationships and delete user from unsubscription list $exempt_subscription_list->load_relationship($relationship); $exempt_subscription_list->$relationship->delete($exempt_id, $focus->id); } } } //Now we need to check if user is already in subscription list $already_here = 'false'; //for each list user is subscribed to, compare id's with current list id' foreach ($curr_pl_arr as $user_list) { if (in_array($prospect_list, $user_list)) { //if user already exists, then set flag to true $already_here = 'true'; } } if ($already_here ==='true') { //do nothing, user is already subscribed } else { //user is not subscribed already, so add to subscription list $subscription_list = BeanFactory::newBean('ProspectLists'); $subs_result = $subscription_list->retrieve($prospect_list); if ($subs_result == null) {//error happened while retrieving this list, iterate and continue return; } //load subscription list and add this user $GLOBALS['log']->debug("In Campaigns Util, loading relationship: ".$relationship); $subscription_list->load_relationship($relationship); $subscription_list->$relationship->add($focus->id); } } /*This function is used by the Manage Subscriptions page in order to add the user * to the exempt prospect lists of the passed in campaign * Takes in campaign and focus parameters. * */ function unsubscribe($campaign, $focus) { $relationship = strtolower($focus->getObjectName()).'s'; //--grab all the list for this campaign id $pl_qry ="select id, list_type from prospect_lists where id in (select prospect_list_id from prospect_list_campaigns "; $pl_qry .= "where campaign_id = " . $focus->db->quoted($campaign) . ") and deleted = 0 "; $pl_qry_result = $focus->db->query($pl_qry); //build the array with list information $pl_arr = array(); $GLOBALS['log']->debug("In Campaigns Util, about to run query: ".$pl_qry); while ($row = $focus->db->fetchByAssoc($pl_qry_result)) { $pl_arr[] = $row; } //retrieve lists that this user belongs to $curr_pl_qry ="select prospect_list_id, related_id from prospect_lists_prospects "; $curr_pl_qry .="where related_id = '$focus->id' and deleted = 0 "; $GLOBALS['log']->debug("In Campaigns Util, unsubscribe function about to run query: ".$curr_pl_qry); $curr_pl_qry_result = $focus->db->query($curr_pl_qry); //build the array with current user list information $curr_pl_arr = array(); while ($row = $focus->db->fetchByAssoc($curr_pl_qry_result)) { $curr_pl_arr[] = $row; } //check to see if user is already there in prospect list $already_here = 'false'; $exempt_id = ''; foreach ($curr_pl_arr as $user_list) { foreach ($pl_arr as $v) { //if list is exempt list if ($v['list_type'] == 'exempt') { //save the exempt list id for later use $exempt_id = $v['id']; //check to see if user is already in this exempt list if (in_array($v['id'], $user_list)) { $already_here = 'true'; } break 2; } } } //unsubscribe subscripted newsletter foreach ($pl_arr as $subscription_list) { //create a new instance of the prospect list $exempt_list = BeanFactory::newBean('ProspectLists'); $exempt_list->retrieve($subscription_list['id']); $exempt_list->load_relationship($relationship); //if list type is default, then delete the relationship //if list type is exempt, then add the relationship to unsubscription list if ($subscription_list['list_type'] == 'exempt') { $exempt_list->$relationship->add($focus->id); } elseif ($subscription_list['list_type'] == 'default' || $subscription_list['list_type'] == 'test') { //if list type is default or test, then delete the relationship //$exempt_list->$relationship->delete($subscription_list['id'],$focus->id); } } if ($already_here =='true') { //do nothing, user is already exempted } else { //user is not exempted yet , so add to unsubscription list $exempt_result = $exempt_list->retrieve($exempt_id); if ($exempt_result == null) {//error happened while retrieving this list return; } $GLOBALS['log']->debug("In Campaigns Util, loading relationship: ".$relationship); $exempt_list->load_relationship($relationship); $exempt_list->$relationship->add($focus->id); } } /* *This function will return a string to the newsletter wizard if campaign check *does not return 100% healthy. */ function diagnose(&$errors = array(), &$links = array()) { global $mod_strings; global $current_user; $errors = array( 'mailbox1' => false, 'mailbox2' => false, 'admin' => false, 'scheduler1' => false, 'scheduler2' => false, ); $links = array( 'scheduler' => false, 'email' => false, ); $msg = " <table class='diagnose_messages detail view small' width='100%'><tr><td> ".$mod_strings['LNK_CAMPAIGN_DIGNOSTIC_LINK']."</td></tr>"; //Start with email components //monitored mailbox section $focus = BeanFactory::newBean('Administration'); $focus->retrieveSettings(); //retrieve all admin settings. //run query for mail boxes of type 'bounce' $email_health = 0; $email_components = 2; $mbox_qry = "select * from inbound_email where deleted ='0' and mailbox_type = 'bounce'"; $mbox_res = $focus->db->query($mbox_qry); $mbox = array(); while ($mbox_row = $focus->db->fetchByAssoc($mbox_res)) { $mbox[] = $mbox_row; } //if the array is not empty, then set "good" message if (isset($mbox) && count($mbox)>0) { //everything is ok, do nothing } else { //if array is empty, then increment health counter $email_health =$email_health +1; $msg .= "<tr><td ><font color='red'><b>". $mod_strings['LBL_MAILBOX_CHECK1_BAD']."</b></font></td></tr>"; $errors['mailbox1'] = $mod_strings['LBL_MAILBOX_CHECK1_BAD']; } if (strstr($focus->settings['notify_fromaddress'], 'example.com')) { //if "from_address" is the default, then set "bad" message and increment health counter $email_health =$email_health +1; $msg .= "<tr><td ><font color='red'><b> ".$mod_strings['LBL_MAILBOX_CHECK2_BAD']." </b></font></td></tr>"; $errors['mailbox2'] = $mod_strings['LBL_MAILBOX_CHECK2_BAD']; } else { //do nothing, address has been changed } //do nothing, address has been changed //if health counter is above 1, then show admin link if ($email_health>0) { if (is_admin($current_user)) { $lnk = 'index.php?module=Campaigns&action=WizardEmailSetup'; $msg.="<tr><td ><a href='"; if (isset($_REQUEST['return_module'])) { $lnk .="&return_module=".$_REQUEST['return_module']; } if (isset($_REQUEST['return_action'])) { $lnk .="&return_action=".$_REQUEST['return_action']; } $msg .= $lnk; $links['email'] = $lnk; $msg.="'>".$mod_strings['LBL_EMAIL_SETUP_WIZ']."</a></td></tr>"; } else { $msg.="<tr><td >".$mod_strings['LBL_NON_ADMIN_ERROR_MSG']."</td></tr>"; $errors['admin'] = $mod_strings['LBL_NON_ADMIN_ERROR_MSG']; } } // proceed with scheduler components //create and run the scheduler queries $sched_qry = "select job, name, status from schedulers where deleted = 0 and status = 'Active'"; $sched_res = $focus->db->query($sched_qry); $sched_health = 0; $sched = array(); $check_sched1 = 'function::runMassEmailCampaign'; $check_sched2 = 'function::pollMonitoredInboxesForBouncedCampaignEmails'; $sched_mes = ''; $sched_mes_body = ''; $scheds = array(); while ($sched_row = $focus->db->fetchByAssoc($sched_res)) { $scheds[] = $sched_row; } //iterate through and see which jobs were found foreach ($scheds as $funct) { if (($funct['job']==$check_sched1) || ($funct['job']==$check_sched2)) { if ($funct['job']==$check_sched1) { $check_sched1 ="found"; } else { $check_sched2 ="found"; } } } //determine if error messages need to be displayed for schedulers if ($check_sched2 != 'found') { $sched_health =$sched_health +1; $msg.= "<tr><td><font color='red'><b>".$mod_strings['LBL_SCHEDULER_CHECK1_BAD']."</b></font></td></tr>"; $errors['scheduler1'] = $mod_strings['LBL_SCHEDULER_CHECK1_BAD']; } if ($check_sched1 != 'found') { $sched_health =$sched_health +1; $msg.= "<tr><td><font color='red'><b>".$mod_strings['LBL_SCHEDULER_CHECK2_BAD']."</b></font></td></tr>"; $errors['scheduler2'] = $mod_strings['LBL_SCHEDULER_CHECK2_BAD']; } //if health counter is above 1, then show admin link if ($sched_health>0) { global $current_user; if (is_admin($current_user)) { $link = 'index.php?module=Schedulers&action=index'; $msg.="<tr><td ><a href='$link'>".$mod_strings['LBL_SCHEDULER_LINK']."</a></td></tr>"; $links['scheduler'] = $link; } else { $msg.="<tr><td >".$mod_strings['LBL_NON_ADMIN_ERROR_MSG']."</td></tr>"; $errors['admin'] = $mod_strings['LBL_NON_ADMIN_ERROR_MSG']; } } //determine whether message should be returned if (($sched_health + $email_health)>0) { $msg .= "</table> "; } else { $msg = ''; } return $msg; } /** * Handle campaign log entry creation for mail-merge activity. The function will be called by the soap component. * * @param String campaign_id Primary key of the campaign * @param array targets List of keys for entries from prospect_lists_prosects table */ function campaign_log_mail_merge($campaign_id, $targets) { $campaign= BeanFactory::newBean('Campaigns'); $campaign->retrieve($campaign_id); if (empty($campaign->id)) { $GLOBALS['log']->debug('set_campaign_merge: Invalid campaign id'. $campaign_id); } else { foreach ($targets as $target_list_id) { $pl_query = "select * from prospect_lists_prospects where id='".DBManagerFactory::getInstance()->quote($target_list_id)."'"; $result=DBManagerFactory::getInstance()->query($pl_query); $row=DBManagerFactory::getInstance()->fetchByAssoc($result); if (!empty($row)) { write_mail_merge_log_entry($campaign_id, $row); } } } } /** * Function creates a campaign_log entry for campaigns processesed using the mail-merge feature. If any entry * exist the hit counter is updated. target_tracker_key is used to locate duplicate entries. * @param string campaign_id Primary key of the campaign * @param array $pl_row A row of data from prospect_lists_prospects table. */ function write_mail_merge_log_entry($campaign_id, $pl_row) { //Update the log entry if it exists. $update="update campaign_log set hits=hits+1 where campaign_id='".DBManagerFactory::getInstance()->quote($campaign_id)."' and target_tracker_key='" . DBManagerFactory::getInstance()->quote($pl_row['id']) . "'"; $result=DBManagerFactory::getInstance()->query($update); //get affected row count... $count=DBManagerFactory::getInstance()->getAffectedRowCount(); if ($count==0) { $data=array(); $data['id']="'" . create_guid() . "'"; $data['campaign_id']="'" . DBManagerFactory::getInstance()->quote($campaign_id) . "'"; $data['target_tracker_key']="'" . DBManagerFactory::getInstance()->quote($pl_row['id']) . "'"; $data['target_id']="'" . DBManagerFactory::getInstance()->quote($pl_row['related_id']) . "'"; $data['target_type']="'" . DBManagerFactory::getInstance()->quote($pl_row['related_type']) . "'"; $data['activity_type']="'targeted'"; $data['activity_date']="'" . TimeDate::getInstance()->nowDb() . "'"; $data['list_id']="'" . DBManagerFactory::getInstance()->quote($pl_row['prospect_list_id']) . "'"; $data['hits']=1; $data['deleted']=0; $insert_query="INSERT into campaign_log (" . implode(",", array_keys($data)) . ")"; $insert_query.=" VALUES (" . implode(",", array_values($data)) . ")"; DBManagerFactory::getInstance()->query($insert_query); } } function track_campaign_prospects($focus) { $campaign_id = DBManagerFactory::getInstance()->quote($focus->id); $delete_query="delete from campaign_log where campaign_id='".$campaign_id."' and activity_type='targeted'"; $focus->db->query($delete_query); $current_date = $focus->db->now(); $guidSQL = $focus->db->getGuidSQL(); $insert_query= "INSERT INTO campaign_log (id,activity_date, campaign_id, target_tracker_key,list_id, target_id, target_type, activity_type, deleted"; $insert_query.=')'; $insert_query.="SELECT {$guidSQL}, $current_date, plc.campaign_id,{$guidSQL},plp.prospect_list_id, plp.related_id, plp.related_type,'targeted',0 "; $insert_query.="FROM prospect_lists INNER JOIN prospect_lists_prospects plp ON plp.prospect_list_id = prospect_lists.id"; $insert_query.=" INNER JOIN prospect_list_campaigns plc ON plc.prospect_list_id = prospect_lists.id"; $insert_query.=" WHERE plc.campaign_id='".DBManagerFactory::getInstance()->quote($focus->id)."'"; $insert_query.=" AND prospect_lists.deleted=0"; $insert_query.=" AND plc.deleted=0"; $insert_query.=" AND plp.deleted=0"; $insert_query.=" AND prospect_lists.list_type!='test' AND prospect_lists.list_type not like 'exempt%'"; $focus->db->query($insert_query); global $mod_strings; //return success message return $mod_strings['LBL_DEFAULT_LIST_ENTRIES_WERE_PROCESSED']; } function create_campaign_log_entry($campaign_id, $focus, $rel_name, $rel_bean, $target_id = '') { global $timedate; $target_ids = array(); //check if this is specified for one target/contact/prospect/lead (from contact/lead detail subpanel) if (!empty($target_id)) { $target_ids[] = $target_id; } else { //this is specified for all, so load target/prospect relationships (mark as sent button) $focus->load_relationship($rel_name); $target_ids = $focus->$rel_name->get(); } if (count($target_ids)>0) { //retrieve the target beans and create campaign log entry foreach ($target_ids as $id) { //perform duplicate check $dup_query = "select id from campaign_log where campaign_id = '$campaign_id' and target_id = '$id'"; $dup_result = $focus->db->query($dup_query); $row = $focus->db->fetchByAssoc($dup_result); //process if this is not a duplicate campaign log entry if (empty($row)) { //create campaign tracker id and retrieve related bio bean $tracker_id = create_guid(); $rel_bean->retrieve($id); //create new campaign log record. $campaign_log = BeanFactory::newBean('CampaignLog'); $campaign_log->campaign_id = $campaign_id; $campaign_log->target_tracker_key = $tracker_id; $campaign_log->target_id = $rel_bean->id; $campaign_log->target_type = $rel_bean->module_dir; $campaign_log->activity_type = 'targeted'; $campaign_log->activity_date=$timedate->now(); //save the campaign log entry $campaign_log->save(); } } } } /* * This function will return an array that has been formatted to work as a Quick Search Object for prospect lists */ function getProspectListQSObjects($source = '', $return_field_name='name', $return_field_id='id') { global $app_strings; //if source has not been specified, then search across all prospect lists if (empty($source)) { $qsProspectList = array('method' => 'query', 'modules'=> array('ProspectLists'), 'group' => 'and', 'field_list' => array('name', 'id'), 'populate_list' => array('prospect_list_name', 'prospect_list_id'), 'conditions' => array( array('name'=>'name','op'=>'like_custom','end'=>'%','value'=>'') ), 'order' => 'name', 'limit' => '30', 'no_match_text' => $app_strings['ERR_SQS_NO_MATCH']); } else { //source has been specified use it to tell quicksearch.js which html input to use to get filter value $qsProspectList = array('method' => 'query', 'modules'=> array('ProspectLists'), 'group' => 'and', 'field_list' => array('name', 'id'), 'populate_list' => array($return_field_name, $return_field_id), 'conditions' => array( array('name'=>'name','op'=>'like_custom','end'=>'%','value'=>''), //this condition has the source parameter defined, meaning the query will take the value specified below array('name'=>'list_type', 'op'=>'like_custom', 'end'=>'%','value'=>'', 'source' => $source) ), 'order' => 'name', 'limit' => '30', 'no_match_text' => $app_strings['ERR_SQS_NO_MATCH']); } return $qsProspectList; } function filterFieldsFromBeans($beans) { global $app_strings; $formattedBeans = array(); foreach ($beans as $b) { $formattedFields = array(); //bug: 47574 - make sure, that webtolead_email1 field has same required attribute as email1 field if (isset($b->field_defs['webtolead_email1']) && isset($b->field_defs['email1']) && isset($b->field_defs['email1']['required'])) { $b->field_defs['webtolead_email1']['required'] = $b->field_defs['email1']['required']; } foreach ($b->field_defs as $field_def) { $email_fields = false; if ($field_def['name']== 'email1' || $field_def['name']== 'email2') { $email_fields = true; } if ($field_def['name']!= 'account_name') { if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) || $field_def['type'] == 'assigned_user_name' || $field_def['type'] =='link' || $field_def['type'] =='function' || (isset($field_def['source']) && $field_def['source']=='non-db' && !$email_fields) || $field_def['type'] == 'id') { continue; } } if ($field_def['name']== 'deleted' || $field_def['name']=='converted' || $field_def['name']=='date_entered' || $field_def['name']== 'date_modified' || $field_def['name']=='modified_user_id' || $field_def['name']=='assigned_user_id' || $field_def['name']=='created_by' || $field_def['name']=='team_id') { continue; } //If the field is hidden in the studio settings, then do not show if (isset($field_def['studio']) && isset($field_def['studio']['editview']) && $field_def['studio']['editview']=== false) { continue; } $field_def['vname'] = preg_replace('/:$/', '', translate($field_def['vname'], $b->module_dir)); //$cols_name = "{'".$field_def['vname']."'}"; $col_arr = array(); if ((isset($field_def['required']) && $field_def['required'] != null && $field_def['required'] != 0) || $field_def['name']=='last_name' ) { $cols_name=$field_def['vname'].' '.$app_strings['LBL_REQUIRED_SYMBOL']; $col_arr[0]=$cols_name; $col_arr[1]=$field_def['name']; $col_arr[2]=true; } else { $cols_name=$field_def['vname']; $col_arr[0]=$cols_name; $col_arr[1]=$field_def['name']; } if (! in_array($cols_name, $formattedFields)) { array_push($formattedFields, $col_arr); } } $holder = new stdClass(); $holder->name = $b->object_name; $holder->fields = $formattedFields; $holder->moduleKnownAs = translate($b->module_name, 'LBL_MODULE_NAME'); $holder->moduleDir = $b->module_dir; $holder->moduleName = $b->module_name; $formattedBeans[] = $holder; } return $formattedBeans; } /** * Get valid web to person modules * @return array */ function getValidWebToPersonModules(): array { $superclass = 'Person'; $modules = []; foreach ($GLOBALS['moduleList'] as $mod) { $item = BeanFactory::getBean($mod); if ($item && is_subclass_of($item, $superclass)) { $modules[] = $item->module_name; } } return $modules; } /** * Check if it is a valid WebToPerson module * @param string $module * @return bool */ function isValidWebToPersonModule(string $module): bool { $validModules = getValidWebToPersonModules(); return in_array($module, $validModules, true); } Save