Example #1
0
 public function run($args)
 {
     exit('Disabled');
     $Organisations = Organisation::model()->findAll(array('index' => 'id'));
     $command = Yii::app()->db->createCommand("\n\t\t\n\t\tSELECT i.id, i.status, i.date,i.contact_warehouse_id,organisation_id,store2contact_id,query_id, count(*) as 'dupe_count' \n\n\t\tFROM invite i\n\t\t\n\t\tGROUP BY i.contact_warehouse_id, i.organisation_id\n\t\t\n\t\tHAVING dupe_count > 1\n\t\t\n\t\tORDER BY dupe_count DESC\n\t\t\n\t\t");
     $results = $command->queryAll();
     $rows = '';
     $mismatchedOrg = [];
     // 4006
     //$results['contact_warehouse_id'] = 1234;
     //$results['organisation_id'] = 1;
     foreach ($results as $result) {
         // All the s2c rows, with store
         $Store2Contact = Store2Contact::model()->with('store')->find(array('condition' => 'contact_warehouse_id = :cwi AND store.origin_organisation_id = :org_id AND store.date_expired IS NULL', 'params' => array(':cwi' => $result['contact_warehouse_id'], ':org_id' => $result['organisation_id'])));
         if ($result['status'] == 3) {
             $acceeded = 'Y';
         } else {
             $acceeded = 'N';
         }
         // If Sent from Seven Stories, but no
         if ($result['organisation_id'] == 6 && $Store2Contact->store->origin_unique_id == 0) {
             $organisationName = 'Northern Stage (Sent from Seven Stories)';
         } else {
             $organisationName = $Organisations[$result['organisation_id']]->title;
         }
         $rows .= $Store2Contact->store->origin_unique_id . ',' . $result['store2contact_id'] . ',' . $Store2Contact->id . ',' . $organisationName . ',' . $Store2Contact->store->email . ',' . $Store2Contact->store->first_name . ',' . $Store2Contact->store->last_name . ',' . $result['date'] . ',' . $acceeded . "\n";
     }
     $myFile = Yii::app()->basePath . "/../../protected-file-uploads/misc/dupes.csv";
     $fh = fopen($myFile, 'w') or die("can't open file");
     fwrite($fh, $rows);
     fclose($fh);
 }
Example #2
0
 public function run($args)
 {
     exit('Disabled');
     ini_set('memory_limit', '512M');
     $Organisations = Organisation::model()->findAll(array('index' => 'id'));
     /*
     $command = Yii::app()->db->createCommand("
     
     SELECT s2c.id, s.email, o.title, CONCAT(i.contact_warehouse_id,organisation_id) AS conc FROM suppression_list sl
     
     INNER JOIN store2contact s2c ON s2c.store_id = sl.store_id
     
     LEFT JOIN store s ON s.id = s2c.store_id
     
     LEFT JOIN invite i ON s2c.id = i.store2contact_id
     
     LEFT JOIN organisation o ON o.id = i.organisation_id
     
     WHERE sl.`date` >= '2014-12-05' AND s.email IS NOT NULL AND type = 1
     
     GROUP BY conc
     
     ");
     */
     $command = Yii::app()->db->createCommand("\n\t\tSELECT i.organisation_id, s2c.contact_warehouse_id, sl.*, s2c.id AS store2contact_id FROM suppression_list sl\n\t\t\n\t\tLEFT JOIN store2contact s2c ON s2c.store_id = sl.store_id\n\t\t\n\t\tLEFT JOIN invite i ON s2c.id = i.store2contact_id\n\t\t\n\t\tWHERE sl.`date` >= '2014-12-05'  AND type = 1\n\t\t\n\t\tGROUP BY sl.store_id\n\t\t");
     $results = $command->queryAll();
     //print count($results) . ' unsubscribes' . "\n\n";
     $rows = '';
     $StoreModel = new Store();
     foreach ($results as $result) {
         $Store2Contact = Store2Contact::model()->with('store')->find(array('condition' => 'contact_warehouse_id = :cwi AND store.origin_organisation_id = :org_id AND store.date_expired IS NULL', 'params' => array(':cwi' => $result['contact_warehouse_id'], ':org_id' => $result['organisation_id'])));
         if (!is_null($Store2Contact)) {
             // If Sent from Seven Stories, but no
             if ($result['organisation_id'] == 6 && $Store2Contact->store->origin_unique_id == 0) {
                 $organisationName = 'Northern Stage (Sent from Seven Stories)';
             } else {
                 $organisationName = $Organisations[$result['organisation_id']]->title;
             }
             $rows .= $Store2Contact->store->origin_unique_id . ',' . $result['store2contact_id'] . ',' . $Store2Contact->id . ',' . $organisationName . ',' . $Store2Contact->store->email . ',' . $Store2Contact->store->first_name . ',' . $Store2Contact->store->last_name . "\n";
         } else {
             print_r($result);
         }
     }
     $myFile = Yii::app()->basePath . "/../../protected-file-uploads/misc/unsubs.csv";
     $fh = fopen($myFile, 'w') or die("can't open file");
     fwrite($fh, $rows);
     fclose($fh);
 }
Example #3
0
 public function actionDownload($id)
 {
     // no limit for this. See #472
     ini_set('memory_limit', '-1');
     // ensure no timeout occurs during the creation of csv
     ini_set('max_execution_time', '180');
     // do not include log info in generated file
     foreach (Yii::app()->log->routes as $route) {
         if ($route instanceof CProfileLogRoute) {
             $route->enabled = false;
         }
     }
     $Store = new Store();
     $Campaign = Campaign::model()->findByPk($id, array('select' => array('name'), 'with' => array('contacts' => array('select' => array('id', 'opened', 'bounced', 'warehouse_id'), 'index' => 'warehouse_id', 'with' => array('contact2outcomes' => array('with' => 'campaign_outcome', 'select' => array('outcome')), 'group')), 'outcomes' => array('select' => array('id', 'name')))));
     $implodedContactKeys = implode(', ', array_keys($Campaign->contacts));
     if (!sizeof($implodedContactKeys)) {
         throw new CHttpException('404', 'That campaign has no data to return');
     }
     $Accessions = Accession::model()->findAll(array('condition' => 'warehouse_id IN (' . $implodedContactKeys . ')', 'index' => 'warehouse_id'));
     $Store2Contacts = Store2Contact::model()->findAll(array('condition' => 'contact_warehouse_id IN (' . $implodedContactKeys . ')', 'index' => 'contact_warehouse_id', 'with' => array('store')));
     unset($implodedContactKeys);
     // build the csv
     $rows = array();
     $outcomeColumns = array();
     $headings = array('campaign_contact_id' => 'campaign_contact_id', 'salutation' => 'Prefix', 'first_name' => 'Forename', 'last_name' => 'Surname', 'email' => 'Email', 'culture_segment' => 'Culture Segment');
     $csvHeader = array_values($headings);
     // add each outcome as a column heading
     foreach ($Campaign->outcomes as $Outcome) {
         $csvHeader[] = 'outcome_' . $Outcome->id . ' - ' . $Outcome->name;
     }
     // add an empty one for
     $csvHeader[] = "Group";
     $csvHeader[] = "Opened";
     $csvHeader[] = "Bounced";
     header("Expires: Tue, 03 Jul 2001 06:00:00 GMT");
     header("Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate");
     header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
     header('Content-Encoding: UTF-8');
     header('Content-type: text/csv; charset=UTF-8');
     // disposition / encoding on response body
     header("Content-Disposition: attachment;filename=Contacts - " . $Campaign->name . ".csv");
     header("Content-Transfer-Encoding: binary");
     flush();
     $csv = fopen('php://output', 'w');
     fputcsv($csv, $csvHeader);
     // build each row
     $loop = 0;
     foreach ($Campaign->contacts as $warehouse_id => $CampaignContact) {
         $row = array();
         // use headings to get data for basic details
         foreach ($headings as $key => $value) {
             switch ($key) {
                 case 'campaign_contact_id':
                     $row['campaign_contact_id'] = $Campaign->contacts[$warehouse_id]->id;
                     break;
                 case 'email':
                     // already decrypted on find
                     $row[$value] = $Store2Contacts[$warehouse_id]->store->{$key};
                     break;
                 case 'last_name':
                     // already decrypted on find
                     $row[$value] = $Store2Contacts[$warehouse_id]->store->{$key};
                     break;
                 case 'culture_segment':
                     $row[$value] = $Accessions[$warehouse_id]->culture_segment;
                     break;
                 default:
                     $row[$value] = $Store2Contacts[$warehouse_id]->store->{$key};
             }
         }
         // do outcome row values
         foreach ($CampaignContact->contact2outcomes as $Outcome) {
             $row[$Outcome->campaign_outcome->name] = $Outcome->outcome;
         }
         $row['Group'] = $CampaignContact->group->name;
         // open and bounce. Once will likely be null / blank.
         $row['Opened'] = $CampaignContact->opened;
         $row['Bounced'] = $CampaignContact->bounced;
         //$rows[] = $row;
         fputcsv($csv, $row, ',', '"');
         if (!($loop++ % 100)) {
             ob_flush();
             flush();
             // Attempt to flush output to the browser every 100 lines.
             // You may want to tweak this number based upon the size of your CSV rows.
         }
         unset($row);
         unset($CampaignContact);
     }
     fclose($csv);
 }
Example #4
0
<div class="alert alert-warning">
	<p>You are on the server <em><?php 
print $_SERVER['HTTP_HOST'];
?>
</em>, which is the <?php 
print ENVIRONMENT;
?>
 environment.</p>
</div>

<p>Your current data is as follows:</p>

<?php 
$Store = Store::model()->count();
$Store2Contact = Store2Contact::model()->count();
$Accession = Accession::model()->count();
$CleanWarehouse = Yii::app()->db->createCommand("SELECT COUNT(*) as tot FROM clean_warehouse")->queryRow();
?>

<table class="table table-bordered">
	<tr>
		<th>Table</th>
		<th>Rows</th>
	</tr>
	<tr>
		<td>store</td>
		<td><?php 
print $Store;
?>
</td>
Example #5
0
 public function actionInviteUnsubscribe()
 {
     // campaign_id -> used to send the invite
     // campaign_hash -> used to check the id isn't manipulated
     // invite_id -> use to store the invite row
     // invite_hash_partial -> used to store the first 8 characters of the much longer 40 char invite hash
     // match the invite to a contact?
     $Invite = Invite::model()->find(array('condition' => 'id = :invite_id AND SUBSTR(hash,1,8) = :invite_hash_partial', 'params' => array(':invite_id' => $_GET['invite_id'], ':invite_hash_partial' => $_GET['invite_hash_partial'])));
     // matches an invite
     if (is_null($Invite) || ($Invite->campaign->id !== $_GET['campaign_id'] || $Invite->campaign->hash !== $_GET['campaign_hash'])) {
         $this->layout = 'vanilla';
         $this->pageTitle = '404 not found';
         $this->render('unsubscribed', array('title' => 'We couldn\'t find that.', 'message' => 'We weren\'t able to find the page you were looking for. Sorry about that.'));
         Yii::app()->end();
     }
     $Store2Contact = Store2Contact::model()->with(array('store' => array('with' => array('organisation'))))->findByPk($Invite->store2contact_id);
     if (is_null($Store2Contact)) {
         $this->layout = 'vanilla';
         $this->pageTitle = '404 not found';
         $this->render('unsubscribed', array('title' => 'We couldn\'t find that.', 'message' => 'We weren\'t able to find the page you were looking for. Sorry about that.'));
         Yii::app()->end();
     }
     // check for existing suppression row. Should only be one row per campaign
     $SuppressionList = SuppressionList::model()->findByAttributes(array('store2contact_id' => $Store2Contact->id, 'campaign_id' => $Invite->campaign_id));
     // add a suppression row
     if (is_null($SuppressionList)) {
         $NewSuppressionList = new SuppressionList();
         // Warehouse ID is null because we only want to supress from this single org...
         $NewSuppressionList->warehouse_id = null;
         // ... which represented by a single Store row
         $NewSuppressionList->store_id = $Store2Contact->store_id;
         $NewSuppressionList->store2contact_id = $Store2Contact->id;
         $NewSuppressionList->campaign_id = $Invite->campaign_id;
         $NewSuppressionList->type = SuppressionList::TYPE_UNSUBSCRIBE;
         if (!$NewSuppressionList->save()) {
             var_dump($NewSuppressionList->errors);
             exit;
         }
     }
     // show the success message page
     $this->layout = 'vanilla';
     $this->pageTitle = 'You have been unsubscribed';
     $this->render('unsubscribed', array('title' => 'You\'ve unsubscribed successfully.', 'message' => 'We\'re registered your unsubscribe request. You may still receive already queued email correspondance from ' . $Store2Contact->store->organisation->title . '.'));
     Yii::app()->end();
 }
Example #6
0
 private function import()
 {
     $db = new PDO(Yii::app()->params['db']['connectionString'], Yii::app()->params['db']['username'], Yii::app()->params['db']['password'], array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
     $resultRows = $db->query('SELECT * FROM raw_import WHERE id > ' . $this->lastRowProcessed . ' LIMIT ' . $this->rowsToProcess);
     $suppressionCount = 0;
     echo "\n\n" . 'Pointer is at ' . $this->lastRowProcessed . "\n\n";
     while ($data = $resultRows->fetch(PDO::FETCH_ASSOC)) {
         $StoreView = null;
         $DupeMatch = null;
         $CodeMatch = null;
         $Store2Contact = null;
         //20532
         // 1 yes 0 no 2 unknown
         $contact_email = 2;
         //unkown
         $contact_post = 2;
         $contact_sms = 2;
         $organisation_id = null;
         // create base Store instance.
         $StoreView = new Store();
         $data['CCR_Client_URN'] = $this->emptyToNull($data['CCR_Client_URN']);
         if (is_null($data['CCR_Client_URN'])) {
             // no URN no insert
             continue;
         }
         $StoreView['origin_unique_id'] = trim($data['CCR_Client_URN']);
         $StoreView['csv_file_uuid'] = $data['Cleaning_UUID'];
         $StoreView['date_imported'] = date('Y-m-d H:i:s');
         //Get organisation id
         switch ($data['CCR_Organisation']) {
             case 'Example 1':
                 $organisation_id = 1;
                 switch ($data['CCR_Email_Allow']) {
                     case 'Allow':
                         $contact_email = 1;
                         break;
                     case 'Do Not Allow':
                         $contact_email = 0;
                         break;
                 }
                 break;
             default:
                 break;
         }
         $StoreView['contact_email'] = $contact_email;
         $StoreView['contact_sms'] = $contact_sms;
         $StoreView['contact_post'] = $contact_post;
         $StoreView['origin_organisation_id'] = $organisation_id;
         $StoreView['salutation'] = $this->emptyToNull($data['CCR_Title']);
         $StoreView['first_name'] = $this->emptyToNull($data['CCR_Forename']);
         $StoreView['last_name'] = $this->emptyToNull($data['CCR_Surname']);
         if (!is_null($StoreView['last_name'])) {
             $StoreView['last_name'] = rtrim(mcrypt_decrypt($this->cipher, $this->key3, base64_decode($StoreView['last_name']), $this->mode, $this->iv));
         }
         $StoreView['address_line_1'] = $this->emptyToNull($data['CCR_Address1']);
         if (!is_null($StoreView['address_line_1'])) {
             $StoreView['address_line_1'] = rtrim(mcrypt_decrypt($this->cipher, $this->key2, base64_decode($StoreView['address_line_1']), $this->mode, $this->iv));
         }
         $StoreView['address_line_2'] = $this->emptyToNull($data['CCR_Address2']);
         $StoreView['address_line_3'] = $this->emptyToNull($data['CCR_Address3']);
         $StoreView['address_line_4'] = $this->emptyToNull($data['CCR_Address4']);
         $StoreView['address_town'] = $this->emptyToNull($data['CCR_Town']);
         $data['CCR_Postcode'] = trim($data['CCR_Postcode']);
         if ($this->isPostcode($data['CCR_Postcode'])) {
             $StoreView['address_postcode'] = $data['CCR_Postcode'];
         } else {
             $StoreView['address_postcode'] = null;
         }
         $StoreView['address_county'] = $this->emptyToNull($data['CCR_County']);
         // phone and mobile
         //regex to to see if provided phone number is mobile
         $phone1 = intval(rtrim(mcrypt_decrypt($this->cipher, $this->key4, base64_decode($data['CCR_Phone1']), $this->mode, $this->iv)));
         $phone2 = intval(rtrim(mcrypt_decrypt($this->cipher, $this->key5, base64_decode($data['CCR_Phone2']), $this->mode, $this->iv)));
         if ($phone1 && $phone2) {
             if ($this->isMobile($phone1)) {
                 $StoreView['mobile'] = $phone1;
                 $StoreView['phone'] = $phone2;
             }
             if ($this->isMobile($phone2)) {
                 $StoreView['mobile'] = $phone2;
                 $StoreView['phone'] = $phone1;
             }
         } else {
             if ($phone1) {
                 if ($this->isMobile($phone1)) {
                     $StoreView['mobile'] = $phone1;
                 } else {
                     $StoreView['phone'] = $phone1;
                 }
             } else {
                 if ($phone2) {
                     if ($this->isMobile($phone2)) {
                         $StoreView['mobile'] = $phone2;
                     } else {
                         $StoreView['phone'] = $phone2;
                     }
                 }
             }
         }
         // end phone and mobile
         // email
         $StoreView->email = $data['CCR_Email'];
         if (!is_null($StoreView->email)) {
             $StoreView->email = rtrim(mcrypt_decrypt($this->cipher, $this->key1, base64_decode($StoreView['email']), $this->mode, $this->iv));
         }
         if (!is_null($StoreView['email']) && !filter_var($StoreView->email, FILTER_VALIDATE_EMAIL)) {
             $StoreView->email = null;
         }
         // end email
         // Save the contact in the store
         if (!$StoreView->validate()) {
             print '$StoreView->errors:' . "\n";
             print_r($StoreView->errors);
         } else {
             $this->totalImported++;
             //in dupe set
             $data['CCR_Ind_Set'] = (int) trim($data['CCR_Ind_Set']);
             /*
             if(this row has (int)CCR_Ind_Set > 0){
             	
             	select existing 1+ duplicates
             
             	if(this row (int)CCR_Ind_Set matches a ccr_duplicate_id with the same organisation_id){
             	
             		// mega dupe
             		if( existing record has 'Yes' for CCR_Ind_Dupe1 ){
             	
             			insert and expire this row
             		}
             		else
             		{
             			expire existing
             			insert this row
             		}
             	}
             	else
             	{
             		// no other rows in same org
             		insert this row
             	}
             }
             else
             {
             	// not a duplicate
             }
             */
             // is this the ccr dupe favoured row?
             $StoreView['ccr_ind_dupe1'] = trim($data['CCR_Ind_Dupe1']) === 'Yes' ? 1 : 0;
             // If CCR has detected a duplicate...
             if ($data['CCR_Ind_Set'] > 0) {
                 $this->totalDupes++;
                 $StoreView->ccr_duplicate_id = $data['CCR_Ind_Set'];
                 //print "CCR_Ind_Set > 0\n";
                 //first of all, let see if the dupe has the same origin id as a previous in the database
                 $DupeMatches = Store::model()->with(array('store2contact'))->findAllByAttributes(array('ccr_duplicate_id' => $data['CCR_Ind_Set'], 'date_expired' => null), array('index' => 'origin_organisation_id'));
                 // print ('starting new loop with dupes');
                 if (sizeof($DupeMatches)) {
                     // print "size DupeMatches > 0\n";
                     $Store2Contact = null;
                     // print_r(array_keys($DupeMatches));
                     // print "\nDupeMatch orgs: " . $organisation_id . "\n";
                     if (array_key_exists((int) $organisation_id, $DupeMatches)) {
                         // we have a match from the same organisation
                         // print "org exists in dupes data\n";
                         //not do in the correct order, needs to be done with CCR_Ind_Set
                         //we need to expire the match and update the warehouse record
                         //we the new one
                         //echo 'DupeMatch';
                         if ($DupeMatches[$organisation_id]->ccr_ind_dupe1) {
                             // print "Alread have trusted row, expire row\n";
                             // already have a trusted row. Expire and insert this one.
                             $StoreView->date_expired = date('Y-m-d H:i:s');
                             $StoreView->ccr_ind_dupe1 = 0;
                             // just in case.
                         } else {
                             // print "Update store row\n";
                             // update store row
                             $DupeMatches[$organisation_id]->date_expired = date('Y-m-d H:i:s');
                             $DupeMatches[$organisation_id]->save();
                             // update any suppression list rows to not have warehouse or store_id. They're old and expired.
                             SuppressionList::model()->deleteAll('store2contact_id = ' . (int) $DupeMatches[$organisation_id]->store2contact->id);
                             // clone the contact_warehouse_id and ind set. Gets saved below.
                             $Store2Contact = $DupeMatches[$organisation_id]->store2contact;
                             // print 'Store2Contact=';
                             // print_r ($Store2Contact->attributes);
                             $Store2Contact->contact_warehouse_id = $DupeMatches[$organisation_id]->store2contact->contact_warehouse_id;
                         }
                     } else {
                         // print "org does not exist in dupes data\n";
                         //is it not a dupe match but someone else has the same dupe id?
                         //if so, lets find their Warehouse ID and then add as a new row
                         $LastDuplicate = end($DupeMatches);
                         $Store2Contact = new Store2Contact();
                         $Store2Contact->contact_warehouse_id = $LastDuplicate->store2contact->contact_warehouse_id;
                     }
                     // the save for dupes is here
                     if (!$StoreView->save()) {
                         print_r($StoreView->errors);
                     }
                     // if we have a store2contact save it here
                     if (!is_null($Store2Contact)) {
                         //update store_id to new one
                         $Store2Contact->store_id = $StoreView->id;
                         $Store2Contact->origin_unique_id = $data['CCR_Client_URN'];
                         $Store2Contact->origin_id = $organisation_id;
                         // print 'saving a (dupe style) store2contact ' . $Store2Contact->id . "\n";
                         if (!$Store2Contact->save()) {
                             print_r($Store2Contact->errors);
                         }
                     }
                     // currently required below.
                     //unset($Store2Contact);
                 }
             }
             // when not a duplicate or there is no other dupe stored yet
             if ($data['CCR_Ind_Set'] == 0 || !sizeof($DupeMatches)) {
                 // save for when no duplicates
                 if (!$StoreView->save()) {
                     print_r($StoreView->errors);
                 }
                 $Warehouse = new Warehouse();
                 if (!$Warehouse->save()) {
                     print_r($Warehouse->errors);
                 }
                 // Create a new Store2Contact row
                 $Store2Contact = new Store2Contact();
                 $Store2Contact->store_id = $StoreView->id;
                 $Store2Contact->contact_warehouse_id = $Warehouse->id;
                 $Store2Contact->origin_unique_id = $data['CCR_Client_URN'];
                 $Store2Contact->origin_id = $organisation_id;
                 if (!$Store2Contact->save()) {
                     print_r($Store2Contact->errors);
                 }
             }
             // Check for non-contactable by email, and add to the supression list
             if ($StoreView->contact_email == 0) {
                 if (!is_null($Store2Contact) && (int) $Store2Contact->id) {
                     $Suppression = new SuppressionList();
                     $Suppression->type = SuppressionList::TYPE_UNSUBSCRIBE;
                     // always save the store id against this row
                     $Suppression->store_id = $StoreView->id;
                     // we have a store2contact row for this person. Add to suppression data.
                     $Suppression->store2contact_id = $Store2Contact->id;
                     //We don't need the warehouse id
                     //$Suppression->warehouse_id = $Store2Contact->contact_warehouse_id;
                     $Suppression->date = date('Y-m-d H:i:s');
                     if ($Suppression->save()) {
                         $suppressionCount++;
                     }
                 }
             }
         }
         unset($data);
         unset($StoreView);
         unset($Store2Contact);
         unset($DupeMatch);
         unset($CodeMatch);
         $this->lastRowProcessed++;
         if (!($this->lastRowProcessed % 100)) {
             $this->completedToNow = $this->lastRowProcessed;
             $timeTotal = microtime(true) - $this->time_start;
             $timeForThis100 = $timeTotal - $this->timeTakenSoFar;
             $this->timeTakenSoFar = $timeTotal;
             $speed = round(1 / $timeForThis100 * 100, 3);
             $currentExecutionTime = round($timeTotal / 60, 2);
             echo $this->lastRowProcessed / 1000 . 'k done in ' . $currentExecutionTime . ' mins. ' . $speed . '  rows/s                    ' . "\r";
         }
     }
     print "\n\n" . $suppressionCount . ' contacts were added to suppression list - not contactable by email' . "\n\n";
 }
Example #7
0
 public function send($Campaign)
 {
     //exit();
     $configs = Yii::app()->db->createCommand("SELECT * FROM `config` WHERE `key` IN ('host', 'https')")->queryAll();
     if (sizeof($configs) < 2) {
         throw new CException("\n\n\n===\nDomain or HTTPS config not yet set. View any admin area page in a browser to remedy this.\n===\n\n");
     }
     foreach ($configs as $config) {
         $params[$config['key']] = $config['value'];
     }
     // Load contacts for this invite from the invite table
     // They'll be marked with this campaign ID, and status=0 - unsent
     $Invite = Invite::model();
     $transaction = $Invite->dbConnection->beginTransaction();
     try {
         $InviteRows = $Invite->with("store")->findAll(array("condition" => "campaign_id = :campaign_id AND processing = 0 AND status = :status", "params" => array(":campaign_id" => $Campaign->id, ":status" => Invite::STATUS_UNSENT)));
         $inviteIDs = [];
         foreach ($InviteRows as $Invite) {
             $inviteIDs[] = $Invite->id;
         }
         $command = Yii::app()->db->createCommand();
         $command->update('invite', array("processing" => 1), array('in', 'id', $inviteIDs));
         $transaction->commit();
     } catch (Exception $e) {
         $transaction->rollback();
         throw $e;
     }
     set_time_limit(0);
     // Load all organisations, we'll need their info
     $Organisations = Organisation::model()->findAll(array('condition' => 'id IN (1,2,3,4,5,6,7,8,9)', 'index' => 'id'));
     // Group by organisation
     $orgContacts = array();
     foreach ($InviteRows as $Invite) {
         $orgContacts[$Invite->organisation_id][] = $Invite;
     }
     // Chunk these into arrays of up to 1000 contacts per organisation - this is the Mailgun limit
     $chunkedOrgContacts = array();
     foreach ($orgContacts as $orgID => $contactArray) {
         $chunkedOrgContacts[$orgID] = array_chunk($orgContacts[$orgID], 1000);
     }
     // Parse the email content, replace tags with the Mailgun recipient params
     $parsedContent = $this->parseEmailContent($Campaign->invite_email_subject, $Campaign->invite_email_body, array('first_name' => '%recipient.first_name%', 'last_name' => '%recipient.last_name%', 'invite_url' => '%recipient.invite_url%', 'unsubscribe_url' => '%recipient.unsubscribe_url%'));
     // Debug / counter vars
     $sentCount = 0;
     $campaignSuccess = false;
     $toEmails = [];
     Yii::import('application.extensions.*');
     foreach ($chunkedOrgContacts as $orgID => $orgChunks) {
         // Only set real email info if we're on production server
         // Let's not send emails to everyone in Newcastle before we're live...
         if (ENVIRONMENT === 'PRODUCTION' || ENVIRONMENT === 'PHOENIX') {
             // Get the correct email domain for the organisation in question
             $fromEmailDomain = $Organisations[$orgID]->email_domain;
             $fromEmailAddress = $Organisations[$orgID]->email_address;
             $fromEmailName = $Organisations[$orgID]->title;
         } else {
             $fromEmailDomain = Yii::app()->params['insiderEmailDomain'];
             $fromEmailAddress = 'email@' . $fromEmailDomain;
             $fromEmailName = $Organisations[$orgID]->title;
         }
         $mailgunApi = new MailgunApi($fromEmailDomain, Yii::app()->params['mailgun']['key']);
         $message = $mailgunApi->newMessage();
         $message->setFrom($fromEmailAddress, $fromEmailName);
         $message->setSubject($parsedContent['subject']);
         $message->addTag('Invite');
         // Tag with invite so it can be filtered in Mailgun admin
         if (ENVIRONMENT !== 'PRODUCTION') {
             $message->addTag('Test');
         }
         /* TEST MODE */
         //$message->enableTestMode();
         // Now loop the contacts, which are in chunks (arrays) of up to 1000
         foreach ($orgChunks as $upTo1000Invites) {
             //start transaction?
             try {
                 $transaction = $Invite->dbConnection->beginTransaction();
                 $invite1000IDs = [];
                 //reset the to fields
                 $message->resetTo();
                 // Add all the contacts in this chunk, there could be up to 1000 of 'em
                 foreach ($upTo1000Invites as $Invite) {
                     $invite1000IDs[] = $Invite->id;
                     if (strlen($Invite->store->email)) {
                         $Store2Contact = Store2Contact::model()->findByPk($Invite->store2contact_id);
                         if (!is_null($Store2Contact)) {
                             // Check values match
                             if ($Store2Contact->contact_warehouse_id === $Invite->contact_warehouse_id && $Store2Contact->store_id === $Invite->store_id) {
                                 // Also save the date they were invited to Store2Contact so we can query it easily
                                 $Store2Contact->most_recent_invite_date = date('Y-m-d H:i:s');
                                 $Store2Contact->save(true, array('most_recent_invite_date'));
                                 unset($Store2Contact);
                                 // Now create the invitation link to pass into the email template
                                 $inviteURL = ($params['https'] === 1 ? 'https://' : 'http://') . $params['host'] . '/accession/invite/' . $Invite->hash;
                                 // Only set real email info if we're on production server
                                 // Let's not send emails to everyone in Newcastle before we're live...
                                 if (ENVIRONMENT === 'PRODUCTION') {
                                     $toEmail = $Invite->store->email;
                                 } else {
                                     $toEmail = '*****@*****.**';
                                 }
                                 $unsubscribeUrl = $Invite->unsubscribeUrl;
                                 // Check first name
                                 $firstName = $Invite->store->first_name;
                                 if (!strlen(trim($firstName))) {
                                     $firstName = 'friend';
                                 }
                                 // Add the recipient to the message object, including the params unique for them
                                 $message->addTo($toEmail, $Invite->store->first_name . ' ' . $Invite->store->last_name, array('first_name' => $firstName, 'last_name' => $Invite->store->last_name, 'invite_url' => $inviteURL, 'unsubscribe_url' => $unsubscribeUrl));
                                 //$toEmails[] = 'Email: ' . $toEmail . " - " . $contact['first_name'] . ' ' . $lastName . '('.$fromEmailName.')' . "\n\n";
                                 // Increment the counter
                                 $sentCount++;
                             } else {
                                 $contactInfo = print_r($contact, true);
                                 mail('*****@*****.**', 'Invite attempted but store2contact row did not match contact found in query', $contactInfo);
                             }
                         } else {
                             $contactInfo = print_r($contact, true);
                             mail('*****@*****.**', 'Invite attempted but store2contact could not be found', $contactInfo);
                         }
                     } else {
                         $contactInfo = print_r($contact, true);
                         mail('*****@*****.**', 'Invite attempted with no email address', $contactInfo);
                     }
                 }
                 // foreach upTo1000Invites
             } catch (Exception $e) {
                 $transaction->rollback();
                 $campaignSuccess = false;
             }
             // Now we have the data for our 1000 contacts set up, render the template for the organisation
             $Controller = new Controller('foo');
             $renderedView = $Controller->renderInternal(Yii::app()->basePath . '/views/mail/organisation-templates/' . $Organisations[$orgID]->email_template . ".php", array('body' => $parsedContent['body']), true);
             $message->setHtml($renderedView);
             // SEND THE MESSAGE
             if (sizeof($message->getTo())) {
                 try {
                     $response = $message->send();
                     $command = Yii::app()->db->createCommand();
                     $command->update('invite', array("status" => Invite::STATUS_SENT, "processing" => 0), array('in', 'id', $invite1000IDs));
                     $transaction->commit();
                     $campaignSuccess = true;
                 } catch (Exception $e) {
                     print $e->getMessage();
                     // mailgun returned an error - we rollback the transaction and remove the number of failed ids from the sent count
                     // consider mainatining a fail count??
                     $sentCount -= count($invite1000IDs);
                     $command = Yii::app()->db->createCommand();
                     $command->update('invite', array("status" => Invite::STATUS_MAILGUN_ERROR, "processing" => 0), array('in', 'id', $invite1000IDs));
                     $transaction->commit();
                     $msg = print_r($e, true);
                     $msg .= print_r($message, true);
                     mail('*****@*****.**', 'Mailgun error', $msg);
                 }
             }
         }
         // end of org 1000 chunk
     }
     // foreach organisations
     if ($campaignSuccess) {
         $Campaign->status = Campaign::STATUS_HAS_BEEN_RUN;
     } else {
         $Campaign->status = Campaign::STATUS_ERROR_SEND;
     }
     $Campaign->save(true, array("status"));
 }
Example #8
0
 public function actionStepOne()
 {
     $this->inAccession = true;
     // Have we arrived here with an accession hash, allowing us to track this contact through accession?
     if (isset($_GET['accessionhash'])) {
         $Accession = $this->getAccessionRecord();
         $this->checkStep($Accession, 1);
     } else {
         $Accession = new Accession();
         $Accession->step = 1;
     }
     $this->pageTitle = 'Welcome to ' . Yii::app()->name . ' | Step One | Accession';
     if (isset($_POST['Accession'])) {
         if ($_POST['Accession']['terms_agreed'] === '1') {
             // Accession hash will be null if they've signed up from the public link
             if (is_null($Accession->accession_hash)) {
                 $Accession->accession_hash = sha1(rand(1, 99999) . microtime(true));
             }
             // TERMS ARE AGREED! We're good to go. Set up all the models
             $Accession->terms_agreed = date('Y-m-d H:i:s');
             if (!$Accession->save()) {
                 print_r($Accession->errors);
                 exit;
             }
             // Now they've agreed terms, update the invite (if they had one)
             if ($Accession->invite_id) {
                 $Invite = Invite::model()->findByPk($Accession->invite_id);
                 if (!is_null($Invite)) {
                     $Invite->status = Invite::STATUS_ACCEPTED;
                     $Invite->save(true, array('status'));
                 }
             }
             $new = false;
             // If it's a new contact coming to the list, we just have a blank row
             // If they've come via an invite then we copy their Store row
             if (is_null($Accession->original_store2contact_id)) {
                 // This contact is new
                 $Store = new Store();
                 // Create a new warehouse row
                 $Warehouse = new Warehouse();
                 $Warehouse->save();
                 // Set the warehouse id to the accession model
                 $Accession->warehouse_id = $Warehouse->id;
                 $Accession->save(true, array('warehouse_id'));
                 $new = true;
             } else {
                 // This contact came from an invite
                 // Grab their previous data
                 $Store2Contact = Store2Contact::model()->findByPk($Accession->original_store2contact_id);
                 // Get the contact's warehouse_id - this identifies them uniquely, even if they have multiple instances in Store
                 $Warehouse = Warehouse::model()->findByPk($Store2Contact->contact_warehouse_id);
                 $ExistingStore = Store::model()->findByPk($Store2Contact->store_id);
                 // Now make a new store to duplicate their info to
                 $Store = new Store();
                 $Store->attributes = $ExistingStore->attributes;
                 $Store->id = null;
             }
             // Set the org ID to THE LIST
             $Store->origin_organisation_id = 10;
             // Try to save the Store
             if (!$Store->save()) {
                 print 'Store errors:<br>';
                 print_r($Store->errors);
                 exit;
             }
             // Also create a new Store2Contact row
             $Store2Contact = new Store2Contact();
             $Store2Contact->store_id = $Store->id;
             $Store2Contact->contact_warehouse_id = $Warehouse->id;
             $Store2Contact->origin_id = 10;
             if (!$Store2Contact->save()) {
                 print 'Store2Contact errors:<br>';
                 print_r($Store2Contact->errors);
                 exit;
             }
             // Now also save the new Store2Contact ID to Accession
             $Accession->store2contact_id = $Store2Contact->id;
             if ($new) {
                 $Accession->original_store2contact_id = $Store2Contact->id;
             }
         }
         if ($Accession->save(true, array('terms_agreed', 'store2contact_id', 'original_store2contact_id'))) {
             $this->updateStep($Accession, 1);
             $this->redirect(array('accession/stepTwo', 'accessionhash' => $Accession->accession_hash));
         }
     }
     $this->render('step1', array('Accession' => $Accession, 'progress' => 1));
 }