This repository has been archived by the owner on Oct 25, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathSurvey.php
216 lines (198 loc) · 9.02 KB
/
Survey.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
<?php
namespace Alphagov\GovWifi;
use PDO;
/**
* Class Survey
*
* Handles sending out surveys to our users based on survey settings in the database.
*
* @package Alphagov\GovWifi
*/
class Survey extends GovWifiBase {
const SUCCESSFUL_EMAIL_SELF = "Successful Email - self signup";
const SUCCESSFUL_EMAIL_SPONSORED = "Successful Email - sponsored";
const SUCCESSFUL_TEXT_SELF = "Successful Text - self signup";
const UNSUCCESSFUL_EMAIL_SELF = "Unsuccessful Email - self signup";
const UNSUCCESSFUL_EMAIL_SPONSORED = "Unsuccessful Email - sponsored";
const UNSUCCESSFUL_TEXT_SELF = "Unsuccessful Text - self signup";
const EMAIL_JOURNEYS = [
self::SUCCESSFUL_EMAIL_SELF,
self::SUCCESSFUL_EMAIL_SPONSORED,
self::UNSUCCESSFUL_EMAIL_SELF,
self::UNSUCCESSFUL_EMAIL_SPONSORED,
];
const TEXT_JOURNEYS = [
self::SUCCESSFUL_TEXT_SELF,
self::UNSUCCESSFUL_TEXT_SELF
];
const SUCCESSFUL_JOURNEYS = [
self::SUCCESSFUL_EMAIL_SELF,
self::SUCCESSFUL_EMAIL_SPONSORED,
self::SUCCESSFUL_TEXT_SELF,
];
const SPONSORED_JOURNEYS = [
self::SUCCESSFUL_EMAIL_SPONSORED,
self::UNSUCCESSFUL_EMAIL_SPONSORED,
];
const SMS_CONTACT_CONDITION = "'+%'";
const EMAIL_CONTACT_CONDITION = "'%@%'";
/**
* Instance of the environment-specific Config class.
* @var Config
*/
private $config;
/**
* Instance of the environment-specific DB class.
* @var DB
*/
private $db;
/**
* Survey constructor. The standard config and db parameters are required.
*
* @param $params
*/
public function __construct($params) {
$defaults = [
'config' => null,
'db' => null,
];
$params = array_merge($defaults, $params);
parent::checkNotEmpty(array_keys($defaults), $params);
parent::checkStandardParams($params);
$this->config = $params['config'];
$this->db = $params['db'];
}
/**
* Send out all active surveys to the users matching survey configuration.
*/
public function sendSurveys() {
error_log("SURVEY - started.");
$configs = $this->getSurveyConfigs();
if (! empty($configs)) {
foreach ($configs as $surveyConfig) {
if (in_array($surveyConfig['journey_type'], self::EMAIL_JOURNEYS)) {
$contactDetails = $this->getContactDetails(
in_array($surveyConfig['journey_type'], self::SUCCESSFUL_JOURNEYS),
self::EMAIL_CONTACT_CONDITION,
$surveyConfig,
true,
in_array($surveyConfig['journey_type'], self::SPONSORED_JOURNEYS)
);
if (! empty($contactDetails)) {
error_log("SURVEY - Sending survey to [" . count($contactDetails) . "] email addresses.");
$this->sendEmailToContacts($contactDetails, $surveyConfig);
} else {
error_log("SURVEY - no contacts found for [" . $surveyConfig['journey_type'] . "]");
}
} else if (in_array($surveyConfig['journey_type'], self::TEXT_JOURNEYS)) {
$contactDetails = $this->getContactDetails(
in_array($surveyConfig['journey_type'], self::SUCCESSFUL_JOURNEYS),
self::SMS_CONTACT_CONDITION,
$surveyConfig
);
if (! empty($contactDetails)) {
error_log("SURVEY - Sending survey to [" . count($contactDetails) . "] mobile numbers.");
$this->sendSmsToContacts($contactDetails, $surveyConfig);
} else {
error_log("SURVEY - no contacts found for [" . $surveyConfig['journey_type'] . "]");
}
} else {
error_log("SURVEY - journey type not recognised. [" . $surveyConfig['journey_type']. "]");
}
}
} else {
error_log("SURVEY - No active configurations found for the current environment.");
}
error_log("SURVEY - finished.");
}
/**
* Retrieve the list of active survey configurations for the current environment.
*
* @return array the survey configurations in an associative array.
*/
public function getSurveyConfigs() {
$handle = $this->db->getConnection()->prepare(
"SELECT * FROM survey_settings_view WHERE survey_active AND environment_name = ?");
$handle->bindValue(1, $this->config->environment);
$handle->execute();
return $handle->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Retrieve the list of contact details for the users who have not opted out and are matching the conditions below.
* Checking the survey_logs table ensures that we never send the same survey twice to the user. However specifying
* the survey_setting_id means that we will potentially send 2 surveys to the same user if after the initial
* unsuccessful state they log in for the first time.
*
* @param $loginSuccessful bool Have ever logged in successfully
* @param $contactCondition string SQL LIKE condition to distinguish between email and mobile contacts
* @param $surveyConfig array The survey configuration associative array (survey_settings_view record)
* @param $sponsoredOnly bool Whether or not the journey is restricted to consider sponsored registrations
* @param $sponsored bool If sponsoredOnly is true, this decides if we are looking at sponsored or self-signup.
*
* @return array Associative array containing the contact details.
*/
public function getContactDetails($loginSuccessful, $contactCondition, $surveyConfig,
$sponsoredOnly = false, $sponsored = false) {
$sql = "SELECT distinct(userdetails.contact), userdetails.username FROM userdetails " .
"LEFT JOIN session_logs ON userdetails.username = session_logs.username ".
"LEFT JOIN survey_logs " .
"ON (userdetails.username = survey_logs.username " .
"AND survey_logs.survey_setting_id = ?) " .
"WHERE ".
"survey_logs.username IS NULL AND " .
"NOT userdetails.survey_opt_out AND " .
"session_logs.username IS " . ($loginSuccessful ? "NOT " : "") . "NULL AND " .
($sponsoredOnly ?
($sponsored ?
" userdetails.contact <> userdetails.sponsor AND " :
" userdetails.contact = userdetails.sponsor AND "
) : ""
) .
"((hour(timediff(now(), userdetails.created_at)) * 60) ".
"+ minute(timediff(now(), userdetails.created_at))) BETWEEN ? AND ? AND " .
"userdetails.contact LIKE " . $contactCondition;
error_log("SURVEY - Contact details SQL [" . $sql . "]");
$handle = $this->db->getConnection()->prepare($sql);
$handle->bindValue(1, $surveyConfig['survey_setting_id']);
$handle->bindValue(2, $surveyConfig['min_delay_minutes']);
$handle->bindValue(3, $surveyConfig['max_delay_minutes']);
$handle->execute();
return $handle->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Send the survey emails to the contacts provided.
* @param $contactDetails array of contacts - email addresses in an associative array, key: 'contact'/
* @param $surveyConfig array The survey configurations array.
*/
public function sendEmailToContacts($contactDetails, $surveyConfig) {
foreach ($contactDetails as $contactDetail) {
$emailResponse = new EmailResponse();
$emailResponse->sendSurvey($contactDetail['contact'], $surveyConfig);
$this->logSurvey($surveyConfig['survey_setting_id'], $contactDetail['username']);
}
}
/**
* Send the survey text messages to the contacts provided.
* @param $contactDetails
* @param $surveyConfig
*/
public function sendSmsToContacts($contactDetails, $surveyConfig) {
foreach ($contactDetails as $contactDetail) {
$smsResponse = new SmsResponse($contactDetail['contact']);
$smsResponse->sendSurvey($surveyConfig);
$this->logSurvey($surveyConfig['survey_setting_id'], $contactDetail['username']);
}
}
/**
* Save username and survey setting ID to the logs table.
* @param $surveySettingId
* @param $userName
*/
public function logSurvey($surveySettingId, $userName) {
$sql = "INSERT INTO survey_logs(survey_setting_id, username) VALUES (:survey_setting_id, :username)";
$handle = $this->db->getConnection()->prepare($sql);
$handle->bindValue(':survey_setting_id', $surveySettingId, PDO::PARAM_INT);
$handle->bindValue(':username', $userName, PDO::PARAM_STR);
$handle->execute();
}
}