/** * _getCustomFieldUsedByList * This function get a list of custom fields by list * * @param array $listIDs An array of list where its custom fields to be retrieved * * @return array A list of custom fields used by the lists. */ function _getCustomFieldUsedByList($listIDs) { require_once SENDSTUDIO_API_DIRECTORY . '/lists.php'; $cacheid = implode(':', $listIDs); if (!array_key_exists($cacheid, $this->_cacheCustomFieldsUsedByLists)) { $listapi = new Lists_API(); $tempOutput = array('list' => array(), 'customfields' => array(), 'values' => array()); foreach ($listIDs as $tempID) { $tempStatus = $listapi->GetCustomFields($tempID); if (!array_key_exists($tempID, $tempOutput['list'])) { $tempOutput['list'][$tempID] = array(); } foreach ($tempStatus as $tempEach) { array_push($tempOutput['list'][$tempID], $tempEach['fieldid']); /** * Get list of custom fields */ if (!array_key_exists($tempEach['fieldid'], $tempOutput['customfields'])) { $tempFieldType = 'text'; switch ($tempEach['fieldtype']) { case 'date': $tempFieldType = 'date'; break; case 'number': $tempFieldType = 'number'; break; case 'checkbox': $tempFieldType = 'multiple'; break; case 'radiobutton': case 'dropdown': $tempFieldType = 'dropdown'; break; } $tempOutput['customfields'][$tempEach['fieldid']] = array('name' => htmlspecialchars($tempEach['name'], ENT_QUOTES, SENDSTUDIO_CHARSET), 'fieldtype' => $tempEach['fieldtype'], 'defaultvalue' => $tempEach['defaultvalue'], 'operatortype' => $tempFieldType); } /** * ----- */ /** * Get list of values the custom field uses */ if (!array_key_exists($tempEach['fieldid'], $tempOutput['values'])) { $tempFieldValues = array(); $temp = unserialize($tempEach['fieldsettings']); if (is_array($temp) && array_key_exists('Key', $temp) && array_key_exists('Value', $temp)) { foreach ($temp['Key'] as $index => $value) { array_push($tempFieldValues, array('value' => $value, 'text' => htmlspecialchars($temp['Value'][$index], ENT_QUOTES, SENDSTUDIO_CHARSET))); } } if (count($tempFieldValues) != 0) { $tempOutput['values'][$tempEach['fieldid']] = $tempFieldValues; } } } } if (count($tempOutput['list']) == 0) { $tempOutput['list'] = null; } if (count($tempOutput['customfields']) == 0) { $tempOutput['customfields'] = null; } if (count($tempOutput['values']) == 0) { $tempOutput['values'] = null; } $this->_cacheCustomFieldsUsedByLists[$cacheid] = $tempOutput; } return $this->_cacheCustomFieldsUsedByLists[$cacheid]; }
/** * Show_Send_Step_2 * This handles the second step of the send process where * * 1) the first step is verified in php * - checks you are choosing a list or segment * - checks the list/segment id's are valid (ie they are proper id's and not non-numeric values) * - checks the list or segment has contacts in it * * If that checks out ok, the second step shows the form where you set: * - from details * - bounce details * - whether to send the campaigns as multipart (where possible) * - whether to embed images or not (where possible) * - choose the first/last name custom fields * - when to send the split test (if cron is enabled) * * @uses FlashMessage * @uses GetFlashMessages * @uses List_API::Load * @uses List_API::GetCustomFields * @uses Segment_API::Load * @uses GetUser * @uses User_API::HasAccess * @uses CheckCronEnabled */ public function Show_Send_Step_2() { $send_details = IEM::sessionGet('SplitTestSend'); /** * Check the user has been through step 1 successfully. */ if (!$send_details || !isset($send_details['splitid']) || (int) $send_details['splitid'] <= 0) { FlashMessage(GetLang('Addon_splittest_Send_InvalidSplitTest'), SS_FLASH_MSG_ERROR, $this->admin_url); return; } $step1_url = $this->admin_url . '&Action=Send&id=' . $send_details['splitid']; $flash_messages = GetFlashMessages(); /** * If we are not posting a form, maybe we're being redirected back to this step from step 3. * If we are, we'll have flash messages. * * If there are no post variables and we are not showing any messages, then go back to step 1. */ if (empty($_POST) && empty($flash_messages)) { FlashMessage(GetLang('Addon_splittest_Send_ChooseListOrSegment'), SS_FLASH_MSG_ERROR, $step1_url); return; } /** * If we are posting a form, check we are posting a proper form (we should have lists or segments chosen) */ if (!empty($_POST)) { /** * Work out which option the user chose */ $sending_to = array(); $send_type = ''; switch ((int) $_POST['ShowFilteringOptions']) { case 1: $send_type = 'list'; if (isset($_POST['lists'])) { $sending_to = $_POST['lists']; } break; case 2: $send_type = 'segment'; if (isset($_POST['segments'])) { $sending_to = $_POST['segments']; } break; default: FlashMessage(GetLang('Addon_splittest_Send_ChooseListOrSegment'), SS_FLASH_MSG_ERROR, $step1_url); return; break; } /** * Make sure the user actually chose some options. */ if (empty($sending_to)) { FlashMessage(GetLang('Addon_splittest_Send_ChooseListOrSegment'), SS_FLASH_MSG_ERROR, $step1_url); return; } /** * Make sure the id's the user chose are valid * If any area invalid (not int's), the user is thrown back to the first step. */ foreach ($sending_to as $id) { $id = (int) $id; if ($id <= 0) { FlashMessage(GetLang('Addon_splittest_Send_ChooseListOrSegment'), SS_FLASH_MSG_ERROR, $step1_url); return; } } /** * After everything has been validated, store the settings and display the next form. */ $send_details['sendingto'] = array('sendtype' => $send_type, 'sendids' => $sending_to); IEM::sessionSet('SplitTestSend', $send_details); } $user = GetUser(); /** * Re-set these variables. * They may be coming from the session if we are being redirected back to step 2 from another step. */ $send_type = $send_details['sendingto']['sendtype']; $sending_to = $send_details['sendingto']['sendids']; /** * Get the first list or segment we're sending to. * We need this to set the defaults for the from name, email, reply-to email and bounce details. * It doesn't really matter what the id is, the user can override the options anyway through the form. */ $id = $sending_to[0]; $send_size = 0; /** * We always need the list api * so we can load the right details regardless of whether the user is sending to a segment or list. */ require_once SENDSTUDIO_API_DIRECTORY . '/lists.php'; $list_api = new Lists_API(); switch ($send_type) { case 'list': $list_id = $id; $listids = $sending_to; $user_lists = $user->GetLists(); foreach ($user_lists as $user_list_id => $user_list_details) { if (!in_array($user_list_id, $sending_to)) { continue; } $send_size += $user_list_details['subscribecount']; } // this is used at a later step to check duplicates etc. $send_details['sendingto']['Lists'] = $sending_to; break; case 'segment': require_once SENDSTUDIO_API_DIRECTORY . '/subscribers.php'; $api = new Subscribers_API(); $segment_info = $api->GetSubscribersFromSegment($sending_to, true); $send_size = $segment_info['count']; /** * Since a segment can go across lists, * we only need one list - so just get the first one we come across. * The user can change the details on the fly anyway. */ $listids = $segment_info['lists']; $list_id = $listids[0]; // this is used at a later step to check duplicates etc. $send_details['sendingto']['Lists'] = $listids; break; } if ($send_size <= 0) { $var = 'Addon_splittest_Send_NoContacts_'; if (sizeof($sending_to) == 1) { $var .= 'One_'; } else { $var .= 'Many_'; } $var .= $send_type; FlashMessage(GetLang($var), SS_FLASH_MSG_ERROR, $step1_url); return; } $send_details['sendsize'] = $send_size; IEM::sessionSet('SplitTestSend', $send_details); /** * Get the flashmessage to draw the box. * then add to the existing messages (eg we're back here from step 3). */ if ($send_size == 1) { FlashMessage(GetLang('Addon_splittest_Send_Step2_Size_One'), SS_FLASH_MSG_SUCCESS); } else { FlashMessage(sprintf(GetLang('Addon_splittest_Send_Step2_Size_Many'), $this->PrintNumber($send_size)), SS_FLASH_MSG_SUCCESS); } $flash_messages .= GetFlashMessages(); $this->template_system->Assign('FlashMessages', $flash_messages, false); if (self::CheckCronEnabled()) { $this->template_system->Assign('CronEnabled', true); /** * Get the sendstudio functions file to create the date/time box. */ require_once SENDSTUDIO_FUNCTION_DIRECTORY . '/sendstudio_functions.php'; /** * also need to load the 'send' language file so it can put in the names/descriptions. */ $ssf = new SendStudio_Functions(); $ssf->LoadLanguageFile('send'); $timebox = $ssf->CreateDateTimeBox(0, false, 'datetime', true); $this->template_system->Assign('ScheduleTimeBox', $timebox, false); } $this->template_system->Assign('ShowBounceInfo', $user->HasAccess('Lists', 'BounceSettings')); $this->template_system->Assign('DisplayEmbedImages', SENDSTUDIO_ALLOW_EMBEDIMAGES); $this->template_system->Assign('EmbedImagesByDefault', SENDSTUDIO_DEFAULT_EMBEDIMAGES); $list_api->Load($list_id); $details = array('fromname' => $list_api->Get('ownername'), 'fromemail' => $list_api->Get('owneremail'), 'replytoemail' => $list_api->Get('replytoemail'), 'bounceemail' => $list_api->Get('bounceemail')); $customfield_settings = array(); $list_customfields = $list_api->GetCustomFields($listids); foreach ($list_customfields as $fieldid => $fielddetails) { if (strtolower($fielddetails['fieldtype']) != 'text') { continue; } $customfield_settings[$fieldid] = htmlspecialchars($fielddetails['name'], ENT_QUOTES, SENDSTUDIO_CHARSET); } $show_customfields = false; if (!empty($customfield_settings)) { $show_customfields = true; } $this->template_system->Assign('CustomFields', $customfield_settings); $this->template_system->Assign('ShowCustomFields', $show_customfields); foreach ($details as $name => $value) { $this->template_system->Assign($name, $value); } $this->template_system->Assign('AdminUrl', $this->admin_url, false); $this->template_system->ParseTemplate('send_step2'); }
/** * GenerateQueryFromSegmentRules * Generate query string from segemnt record * * Successful return array wil have the following structure: * - selectQuery => Query to select the subscribers described by the rules * - countQuery => Query to count the subscribers described by the rules * * @param Array $listIDs An array of list IDs to be queried for * @param Array $rules An array of segment rules * * @return Mixed Returns an array of SQL statement (Please see description above) (Array|FALSE) * * @uses Subscribers_API::_GenerateSegmentRuleQuery() * @uses Subscribers_API::$_cacheCustomfields */ function GenerateQueryFromSegmentRules($listIDs, $rules) { $listIDs = $this->CheckIntVars($listIDs); $tables = array( 'subscribers' => SENDSTUDIO_TABLEPREFIX . 'list_subscribers AS subscribers', ); $joins = array(); $conditions = array( 'subscribers.listid IN (' . implode(', ', $listIDs) . ')', ); $columns = array( 'subscribers.subscriberid AS subscriberid', ', subscribers.emailaddress AS emailaddress', ', subscribers.subscribedate AS subscribedate', ', subscribers.format AS format', ', subscribers.unsubscribed AS unsubscribed', ', subscribers.bounced AS bounced', ', subscribers.confirmed AS confirmed', ', subscribers.listid AS listid' ); // Adding list names, as it is always going to be required $tables['lists'] = ''; $tables['subscribers'] .= ' JOIN ' . SENDSTUDIO_TABLEPREFIX . 'lists AS lists' . ' ON lists.listid = subscribers.listid' . ' AND lists.listid IN (' . implode(', ', $listIDs) . ')'; array_push($columns, ', lists.name AS listname'); // Get custom fields cache used by this segment if (is_null($this->_cacheCustomfields)) { require_once(dirname(__FILE__) . '/lists.php'); $listAPI = new Lists_API(); $temp = $listAPI->GetCustomFields($listIDs); $this->_cacheCustomfields = array(); if (is_array($temp)) { foreach ($temp as $each) { $this->_cacheCustomfields[$each['fieldid']] = $each['fieldtype']; } } } $status = $this->_GenerateSegmentRuleQuery($rules, 'AND', $tables, $joins, $conditions, $listIDs); if ($status === false) { return false; } $tempQuery = ' FROM ' . implode(' ', $tables) . ' WHERE ' . (count($joins) > 0? implode(' AND ', $joins) . ' AND ' : '') . implode(' ', $conditions); return array( 'selectQuery' => 'SELECT DISTINCT ' . implode(' ', $columns) . $tempQuery, 'countQuery' => 'SELECT COUNT(DISTINCT subscribers.subscriberid) AS count' . $tempQuery); }
/** * _ProcessJob_RemoveList * Add subscriber to another list(s) * * This function will return an associative array with the following value: * - error => Boolean => Indicates whether or not the function is successful * - halt => Boolean => Indicates whether or not to halt the operation * * @param Array $queue Queue record * @param Array $trigger Trigger record * @param Integer $subscriberid Subscriber ID to be copied to another list * @return Array Returns an array of the status (see comment above) */ private function _ProcessJob_AddList($queueid, $trigger, $subscriberid) { $return = array( 'error' => true, 'halt' => false ); $subscriberapi = new Subscribers_API(); $listapi = new Lists_API(); $subscriber_record = $subscriberapi->LoadSubscriberList($subscriberid); if(empty($subscriber_record)){ trigger_error("Cannot check database for particular subscriber ({$subscriberid})"); $this->_log("Cannot check database for particular subscriber ({$subscriberid})"); $return['halt'] = true; $return['error'] = true; return $return; } $subscriber_customfields = (isset($subscriber_record['CustomFields']) && is_array($subscriber_record['CustomFields'])) ? $subscriber_record['CustomFields'] : array(); $lists = $trigger['triggeractions']['addlist']['listid']; if (!is_array($lists)) { $lists = array($lists); } $this->Db->StartTransaction(); foreach ($lists as $list) { if ($list == $subscriber_record['listid']) { continue; } $duplicate = $subscriberapi->IsSubscriberOnList($subscriber_record['emailaddress'], $list); if ($duplicate) { $unsubscribed_check = $subscriberapi->IsUnSubscriber(false, $list, $duplicate); if ($unsubscribed_check) { $this->_log('Cannot add contact to this list: Is already in the list as unsubscriber'); } else { $this->_log('Cannot add contact to this list: Is already in the list'); } continue; } list($banned, $msg) = $subscriberapi->IsBannedSubscriber($subscriber_record['emailaddress'], $list, false); if ($banned) { $this->_log('Cannot add contact to this list: Email is banned to be added to the list'); continue; } // ----- Save subscriber and custom fields $this->Db->StartTransaction(); $subscriberapi->confirmcode = false; $subscriberapi->confirmed = $subscriber_record['confirmed']; $subscriberapi->confirmdate = 0; $subscriberid = $subscriberapi->AddToList($subscriber_record['emailaddress'], $list); if (!$subscriberid) { $this->Db->RollbackTransaction(); $this->_log('Cannot add contact to this list: API returned FALSE value'); continue; } $ListCustomFields = $listapi->GetCustomFields($list); $allfieldok = true; if (!empty($ListCustomFields)) { $transferred = array(); if (!empty($subscriber_customfields)) { // Match custom field foreach ($subscriber_customfields as $field) { // Found an exact match if (array_key_exists($field['fieldid'], $lists)) { $subscriberapi->SaveSubscriberCustomField($subscriberid, $field['fieldid'], $field['data']); $transferred[] = $field['fieldid']; continue; } // Check if there are any "name" and "type" match foreach ($ListCustomFields as $fieldid => $listfield) { if ((strtolower($listfield['name']) == strtolower($field['fieldname'])) && ($listfield['fieldtype'] == $field['fieldtype'])) { $subscriberapi->SaveSubscriberCustomField($subscriberid, $fieldid, $field['data']); $transferred[] = $field['fieldid']; continue; } } } } // Check if list required fields are all added in $allfieldok = true; foreach ($ListCustomFields as $fieldid => $field) { if ($field['required'] && !in_array($fieldid, $transferred)) { $allfieldok = false; break; } } } if ($allfieldok) { $this->Db->CommitTransaction(); } else { $this->_log('Cannot add contact to this list: Not all of the required custom fields are available to copied across'); $this->Db->RollbackTransaction(); continue; } // ----- } $this->Db->CommitTransaction(); // Record log if (!$this->RecordLogActions($trigger['triggeremailsid'], $subscriberid, 'addlist')) { $this->_log('Cannot write log to the database...'); } $return['error'] = false; return $return; }
/** * _validateRecord * Validate records * * Check whether or not specified resources exists * * @param Array $record Associated array of the trigger record * @param Array $data Associated array of trigger record data * @param Array $actions Associated array of trigger actions data * * @return Boolean Returns TRUE if everything is verified, FALSE otherwise */ private function _validateRecord($record, $data, $actions) { $actions_specified = array(); // The follwing are needed for each trigger type switch ($record['triggertype']) { case 'f': // listid and customfieldid needs to be populated if (!isset($data['listid']) || empty($data['listid']) || !isset($data['customfieldid']) || empty($data['customfieldid'])) { trigger_error('listid and customfieldid data must be sepecified', E_USER_NOTICE); return false; } require_once(dirname(__FILE__) . '/lists.php'); $listapi = new Lists_API(); $customfields = $listapi->GetCustomFields($data['listid']); if (!array_key_exists($data['customfieldid'], $customfields)) { trigger_error('Custom field is not available', E_USER_NOTICE); return false; } break; case 'l': // linkid_newsletterid and linkid must be populated if (!isset($data['linkid_newsletterid']) || empty($data['linkid_newsletterid']) || !isset($data['linkid']) || empty($data['linkid'])) { trigger_error('linkid_newsletterid and linkid data must be specified', E_USER_NOTICE); return false; } require_once(dirname(__FILE__) . '/newsletters.php'); $newsletterapi = new Newsletters_API(); $links = $newsletterapi->GetLinks($data['linkid_newsletterid']); if (!array_key_exists($data['linkid'], $links)) { trigger_error('Links does not exists', E_USER_NOTICE); return false; } break; case 'n': // newsletterid must be populated if (!isset($data['newsletterid']) || empty($data['newsletterid'])) { trigger_error('newsletterid data must be sepecified', E_USER_NOTICE); return false; } require_once(dirname(__FILE__) . '/newsletters.php'); $newsletterapi = new Newsletters_API(); if (!is_array($newsletterapi->GetRecordByID($data['newsletterid']))) { trigger_error('Newsletter does not exits', E_USER_NOTICE); return false; } break; case 's': // staticdate must be populated if (!isset($data['staticdate']) || empty($data['staticdate'])) { trigger_error('staticdate data must be sepecified', E_USER_NOTICE); return false; } list($year, $month, $day) = explode('-', $data['staticdate']); $tempTime = mktime(0, 0, 0, $month, $day, $year); if (!$tempTime || $tempTime == -1) { trigger_error('Invalid date specified', E_USER_NOTICE); return false; } if (!isset($data['staticdate_listids']) || empty($data['staticdate_listids'])) { trigger_error('staticdate must be assigned to a specific list', E_USER_NOTICE); return false; } if (!is_array($data['staticdate_listids'])) { $data['staticdate_listids'] = array($data['staticdate_listids']); } require_once(dirname(__FILE__) . '/lists.php'); $listapi = new Lists_API(); $count = $listapi->GetLists($data['staticdate_listids'], array(), true); if (!$count || count($data['staticdate_listids']) != $count) { trigger_error('Some (or All) the contact list assigned to this record is not available', E_USER_NOTICE); return false; } break; default: trigger_error('Unknown trigger type', E_USER_NOTICE); return false; break; } // ----- The following are required for "send" action if (isset($actions['send']) && isset($actions['send']['enabled']) && $actions['send']['enabled']) { $temp = array('newsletterid', 'sendfromname', 'sendfromemail', 'replyemail', 'bounceemail'); foreach ($temp as $each) { if (!isset($actions['send'][$each])) { trigger_error('Required parameter for send actions are not passed in', E_USER_NOTICE); return false; } } // Check if newsletterid is available require_once(dirname(__FILE__) . '/newsletters.php'); $newsletterapi = new Newsletters_API(); if (!is_array($newsletterapi->GetRecordByID($actions['send']['newsletterid']))) { trigger_error('Newsletter does not exits', E_USER_NOTICE); return false; } array_push($actions_specified, 'send'); } // ----- // ----- The following are required for "addlist" action if (isset($actions['addlist']) && isset($actions['addlist']['enabled']) && $actions['addlist']['enabled']) { if (!isset($actions['addlist']['listid']) || empty($actions['addlist']['listid'])) { trigger_error('Required parameter for "addlist" actions are not passed in', E_USER_NOTICE); return false; } if (!is_array($actions['addlist']['listid'])) { $actions['addlist']['listid'] = array($actions['addlist']['listid']); } // Check if selected lists are available require_once(dirname(__FILE__) . '/lists.php'); $listapi = new Lists_API(); $count = $listapi->GetLists($actions['addlist']['listid'], array(), true); if (!$count || count($actions['addlist']['listid']) != $count) { trigger_error('Some (or All) the contact list assigned to this record is not available', E_USER_NOTICE); return false; } array_push($actions_specified, 'addlist'); } // ----- // ----- The following are required for "removelist" action if (isset($actions['removelist']) && isset($actions['removelist']['enabled']) && $actions['removelist']['enabled']) { // removelist action does not need anything, but we will need to add it to the "actions_specified" array array_push($actions_specified, 'removelist'); } // ----- // At least one action needs to be specified: if (empty($actions_specified)) { trigger_error('At least one trigger actions need to be specified', E_USER_NOTICE); return false; } return true; }