PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 10.1.4
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v10.1.4
11.1.1 11.1.0 11.0.5 11.0.4 11.0.3 11.0.2 11.0.1 11.0.0 10.11.1 10.11.0 10.10.2 10.10.1 10.10.0 10.9.1 trunk 10.0.0 10.0.1 10.1.0 10.1.1 10.1.2 10.1.3 10.1.4 10.2.0 10.2.1 10.2.2 All 62 releases
acymailing / back / Classes / UserStatClass.php

UserStatClass.php in AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress 10.1.4, at back/Classes/UserStatClass.php

344 lines 12.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace AcyMailing\Classes;
4
5 use AcyMailing\Helpers\ScenarioHelper;
6 use AcyMailing\Core\AcymClass;
7
8 class UserStatClass extends AcymClass
9 {
10 public function __construct()
11 {
12 parent::__construct();
13
14 $this->table = 'user_stat';
15 }
16
17 public function save($userStat, $overrideSendDate = false)
18 {
19 $column = [];
20 $valueColumn = [];
21 $columnName = acym_getColumns('user_stat');
22 if (![$userStat] || !is_array($userStat)) {
23 $userStat = (array)$userStat;
24 }
25
26 foreach ($userStat as $key => $value) {
27 if (in_array($key, $columnName)) {
28 $column[] = '`'.acym_secureDBColumn($key).'`';
29
30 if ($key === 'tracking_sale') {
31 $valueColumn[] = strlen($value) === 0 ? 'NULL' : floatval($value);
32 } else {
33 $valueColumn[] = acym_escapeDB($value);
34 }
35 }
36 }
37
38 $query = 'INSERT INTO #__acym_user_stat ('.implode(',', $column).') VALUE ('.implode(', ', $valueColumn).')';
39 $onDuplicate = [];
40
41 if (!empty($userStat['statusSending'])) {
42 $onDuplicate[] = $userStat['statusSending'] == 0 ? 'fail = fail + 1' : 'sent = sent + 1';
43 }
44
45 if ($overrideSendDate && !empty($userStat['send_date'])) {
46 $onDuplicate[] = 'send_date = '.acym_escapeDB($userStat['send_date']);
47 }
48
49 if (!empty($userStat['open'])) {
50 $onDuplicate[] = 'open = open + 1';
51 $automationClass = new AutomationClass();
52 $automationClass->trigger('user_open', ['userId' => $userStat['user_id'], 'mailId' => $userStat['mail_id']]);
53
54 $scenarioHelper = new ScenarioHelper();
55 $scenarioHelper->trigger('user_open', ['userId' => $userStat['user_id'], 'mailId' => $userStat['mail_id']]);
56 }
57
58 if (!empty($userStat['open_date'])) {
59 $onDuplicate[] = 'open_date = '.acym_escapeDB($userStat['open_date']);
60 }
61
62 if (!empty($userStat['tracking_sale'])) {
63 $onDuplicate[] = 'tracking_sale = '.floatval($userStat['tracking_sale']);
64 }
65
66 if (!empty($userStat['currency'])) {
67 $onDuplicate[] = 'currency = '.acym_escapeDB($userStat['currency']);
68 }
69
70 if (!empty($userStat['unsubscribe'])) {
71 $onDuplicate[] = 'unsubscribe = '.intval($userStat['unsubscribe']);
72 }
73
74 if (!empty($userStat['device'])) {
75 $onDuplicate[] = 'device = '.acym_escapeDB($userStat['device']);
76 }
77
78 if (!empty($userStat['opened_with'])) {
79 $onDuplicate[] = 'opened_with = '.acym_escapeDB($userStat['opened_with']);
80 }
81
82 if (!empty($onDuplicate)) {
83 $query .= ' ON DUPLICATE KEY UPDATE ';
84 $query .= implode(',', $onDuplicate);
85 }
86
87 acym_query($query);
88 }
89
90 public function getOneByMailAndUserId($mail_id, $user_id)
91 {
92 $query = 'SELECT * FROM #__acym_user_stat WHERE `mail_id` = '.intval($mail_id).' AND `user_id` = '.intval($user_id);
93
94 return acym_loadObject($query);
95 }
96
97 public function getDetailedStatistics(array $options)
98 {
99 $limit = $options['limit'] ?? 10;
100 $offset = $options['offset'] ?? 0;
101 $mailId = $options['mail_id'] ?? 0;
102
103 return acym_loadObjectList(
104 'SELECT user_stat.*, `user`.email
105 FROM #__acym_user_stat AS user_stat
106 JOIN #__acym_user AS `user` ON user_stat.user_id = `user`.id
107 WHERE `mail_id` = '.intval($mailId),
108 '',
109 $offset,
110 $limit
111 );
112 }
113
114 public function getAllUserStatByUserId($idUser)
115 {
116 $query = 'SELECT * FROM #__acym_user_stat WHERE user_id = '.intval($idUser);
117
118 return acym_loadObjectList($query);
119 }
120
121 public function getDetailedStats(array $settings): array
122 {
123 $mailClass = new MailClass();
124
125 $query = 'SELECT us.*, m.name, m.subject, m.parent_id, u.email, u.name AS username
126 FROM #__acym_user_stat AS us
127 LEFT JOIN #__acym_user AS u ON us.user_id = u.id
128 INNER JOIN #__acym_mail AS m ON us.mail_id = m.id';
129 $queryCount = 'SELECT COUNT(*) AS total FROM #__acym_user_stat as us
130 LEFT JOIN #__acym_user AS u ON us.user_id = u.id
131 INNER JOIN #__acym_mail AS m ON us.mail_id = m.id';
132 $where = [];
133
134 if (!empty($settings['mail_ids'])) {
135 if (!is_array($settings['mail_ids'])) $settings['mail_ids'] = [$settings['mail_ids']];
136 acym_arrayToInteger($settings['mail_ids']);
137 $where[] = 'us.mail_id IN ('.implode(',', $settings['mail_ids']).')';
138 }
139
140 if (!empty($settings['search'])) {
141 $searchTerms = acym_escapeDB('%'.$settings['search'].'%');
142 $where[] = 'm.name LIKE '.$searchTerms.' OR u.email LIKE '.$searchTerms.' OR u.name LIKE '.$searchTerms;
143 }
144
145 if (!empty($where)) {
146 $query .= ' WHERE ('.implode(') AND (', $where).')';
147 $queryCount .= ' WHERE ('.implode(') AND (', $where).')';
148 }
149
150 if (!empty($settings['ordering']) && !empty($settings['ordering_sort_order'])) {
151 if (in_array($settings['ordering'], ['email', 'name'])) {
152 $table = 'u';
153 } elseif ($settings['ordering'] === 'subject') {
154 $table = 'm';
155 } else {
156 $table = 'us';
157 }
158 $query .= ' ORDER BY '.$table.'.'.acym_secureDBColumn($settings['ordering']).' '.acym_secureDBColumn(strtoupper($settings['ordering_sort_order'])).', us.user_id ASC';
159 }
160
161 $mails = acym_loadObjectList($query, '', $settings['offset'], $settings['detailedStatsPerPage']);
162
163 if (!empty($mails)) {
164 if (acym_isTrackingSalesActive()) {
165 $mailIds = [];
166 foreach ($mails as $mail) {
167 if (!in_array($mail->mail_id, $mailIds)) $mailIds[] = $mail->mail_id;
168 }
169
170 $trackingSales = [];
171 $trackingSalesDB = acym_loadObjectList(
172 'SELECT SUM(tracking_sale) as sale, currency, mail_id, user_id FROM #__acym_user_stat WHERE mail_id IN ('.implode(
173 ',',
174 $mailIds
175 ).') AND currency IS NOT NULL GROUP BY user_id, mail_id'
176 );
177 foreach ($trackingSalesDB as $oneMailTrackSales) {
178 $trackingSales[$oneMailTrackSales->mail_id.'-'.$oneMailTrackSales->user_id] = $oneMailTrackSales;
179 }
180 }
181
182 $totalClicksForMails = [];
183 $campaignsForMails = [];
184 foreach ($mails as $key => $mail) {
185 if (!empty($trackingSales[$mail->mail_id.'-'.$mail->user_id])) {
186 acym_trigger('getCurrency', [&$mails[$key]->currency]);
187 $mails[$key]->sales = $trackingSales[$mail->mail_id.'-'.$mail->user_id]->sale;
188 }
189
190 if (!isset($totalClicksForMails[$mail->mail_id])) {
191 $totalClicksForMails[$mail->mail_id] = acym_loadObjectList(
192 'SELECT SUM(click) AS nbClicks, user_id
193 FROM #__acym_url_click
194 WHERE mail_id = '.intval($mail->mail_id).'
195 GROUP BY user_id',
196 'user_id'
197 );
198 }
199 $mails[$key]->total_click = empty($totalClicksForMails[$mail->mail_id][$mail->user_id]) ? 0 : $totalClicksForMails[$mail->mail_id][$mail->user_id]->nbClicks;
200
201 $mainMailId = empty($mail->parent_id) ? $mail->mail_id : $mail->parent_id;
202 if (!isset($campaignsForMails[$mainMailId])) {
203 $campaignsForMails[$mainMailId] = acym_loadObject('SELECT id AS campaign_id, parent_id FROM #__acym_campaign WHERE mail_id = '.intval($mainMailId));
204 }
205
206 $mails[$key]->campaign_id = empty($campaignsForMails[$mainMailId]) ? 0 : $campaignsForMails[$mainMailId]->campaign_id;
207 $mails[$key]->parent_id = empty($campaignsForMails[$mainMailId]) ? 0 : $campaignsForMails[$mainMailId]->parent_id;
208 }
209 }
210
211 return [
212 'detailed_stats' => $mailClass->decode($mails),
213 'total' => acym_loadObject($queryCount),
214 ];
215 }
216
217 public function getTotalFailClickOpenByMailIds($mailIds)
218 {
219 acym_arrayToInteger($mailIds);
220 if (empty($mailIds)) return [];
221
222 $query = 'SELECT mail_id, SUM(fail) AS fail, SUM(sent) AS sent, SUM(open) AS open FROM #__acym_user_stat WHERE mail_id IN ('.implode(',', $mailIds).') GROUP BY mail_id';
223
224 return acym_loadObjectList($query, 'mail_id');
225 }
226
227 public function getUserWithNoMailOpen()
228 {
229 $query = 'SELECT user_id FROM #__acym_user_stat GROUP BY user_id HAVING MAX(open) = 0';
230
231 return acym_loadResultArray($query);
232 }
233
234 public function getOpenTimeStats($mailIds)
235 {
236
237 if (!is_array($mailIds)) $mailIds = [$mailIds];
238 acym_arrayToInteger($mailIds);
239 $where = empty($mailIds) ? '' : ' AND mail_id in ('.implode(',', $mailIds).')';
240
241 $query = 'SELECT SUM(`open`) AS open_total, DATE_FORMAT(open_date, "%w") AS day, FORMAT(CONVERT(DATE_FORMAT(open_date, "%H"), SIGNED INTEGER) / 3, 0) AS hour, CONCAT(DATE_FORMAT(open_date, "%w"), "_", FORMAT(CONVERT(DATE_FORMAT(open_date, "%H"), SIGNED INTEGER) / 3, 0)) AS date_id FROM `#__acym_user_stat` WHERE open_date IS NOT NULL '.$where.' GROUP BY date_id';
242
243 $return['total_open'] = acym_loadResult('SELECT SUM(`open`) FROM #__acym_user_stat WHERE open_date IS NOT NULL '.$where);
244 $return['stats'] = acym_loadObjectList($query, 'date_id');
245
246 return $return;
247 }
248
249 public function getDefaultStat()
250 {
251 $percentageRemaining = 100;
252 $stats = [];
253
254
255 for ($day = 0 ; $day < 7 ; $day++) {
256 $stats[$day] = [];
257 for ($hour = 0 ; $hour < 8 ; $hour++) {
258 $hourPercentage = $this->getRandomStatOpenTime($percentageRemaining, $hour);
259 $stats[$day][$hour] = $hourPercentage;
260 }
261 }
262
263 return $stats;
264 }
265
266 private function getRandomStatOpenTime(&$percentageRemaining, $hour)
267 {
268 if (empty($percentageRemaining)) return 0;
269 $randoms = [
270 0 => [0, 1],
271 1 => [0, 2],
272 2 => [1, 2],
273 3 => [1, 3],
274 4 => [3, 5],
275 5 => [1, 3],
276 6 => [1, 2],
277 7 => [0, 2],
278 ];
279
280 $percentage = rand($randoms[$hour][0], $randoms[$hour][1]);
281
282 if ($percentageRemaining - $percentage < 0) return 0;
283
284
285 $percentageRemaining -= $percentage;
286
287 return $percentage;
288 }
289
290 public function getOpenSourcesStats($mailIds = [])
291 {
292 if (!is_array($mailIds)) {
293 $mailIds = [$mailIds];
294 }
295 acym_arrayToInteger($mailIds);
296
297 $query = 'SELECT opened_with, COUNT(*) AS number FROM #__acym_user_stat WHERE `open` > 0';
298 if (!empty($mailIds)) {
299 $query .= ' AND mail_id IN ('.implode(',', $mailIds).')';
300 }
301 $query .= ' GROUP BY opened_with';
302
303 return acym_loadObjectList($query);
304 }
305
306 public function deleteDetailedStatsPeriod(): array
307 {
308 $shouldClearExpiredStats = $this->config->get('delete_stats_enabled', 0);
309 if (empty($shouldClearExpiredStats)) {
310 return [];
311 }
312
313 $deleteAfterXSeconds = $this->config->get('delete_stats', 86400 * 360);
314 if (empty($deleteAfterXSeconds)) {
315 return [];
316 }
317
318 $date = acym_date(time() - $deleteAfterXSeconds, 'Y-m-d H:i');
319
320 $queries = [
321 '#__acym_user_stat' => 'DELETE FROM #__acym_user_stat WHERE send_date < '.acym_escapeDB($date),
322 '#__acym_url_click' => 'DELETE FROM #__acym_url_click WHERE date_click < '.acym_escapeDB($date),
323 ];
324
325 $messages = [];
326 foreach ($queries as $table => $query) {
327 try {
328 $status = acym_query($query);
329 if (!empty($status)) {
330 $messages[] = acym_translationSprintf('ACYM_DELETE_X_ROWS_TABLE_X', $status, acym_translation('ACYM_USER_DETAILED_STATS').' ('.$table.')');
331 }
332 } catch (\Exception $e) {
333 $messages[] = $e->getMessage();
334 }
335 }
336
337 if (empty($messages)) {
338 return [];
339 }
340
341 return ['message' => implode("\r\n", $messages)];
342 }
343 }
344