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 / Controllers / Stats / GlobalStats.php

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

766 lines 29.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\Controllers\Stats;
4
5 use AcyMailing\Classes\CampaignClass;
6 use AcyMailing\Classes\MailClass;
7 use AcyMailing\Classes\MailStatClass;
8 use AcyMailing\Classes\UrlClickClass;
9 use AcyMailing\Classes\UserStatClass;
10 use AcyMailing\Helpers\ExportHelper;
11 use AcyMailing\Helpers\MailerHelper;
12 use AcyMailing\Helpers\PaginationHelper;
13 use AcyMailing\Helpers\WorkflowHelper;
14 use AcyMailing\Libraries\Browser\BrowserDetection;
15
16 trait GlobalStats
17 {
18 public function globalStats(): void
19 {
20 acym_setVar('layout', 'global_stats');
21
22 $data = [];
23
24 $this->prepareDefaultPageInfo($data);
25
26 $this->prepareOpenTimeChart($data);
27 $this->preparecharts($data);
28 $this->prepareListReceivers($data);
29 $this->prepareDefaultRoundCharts($data);
30 $this->prepareDefaultLineChart($data);
31 $this->prepareDefaultDevicesChart($data);
32 $this->prepareDefaultBrowsersChart($data);
33 if (count($this->selectedMailIds) == 1) {
34 if ($data['isAbTest']) {
35 $this->prepareAbTestMails($data);
36 } elseif (acym_isMultilingual()) {
37 $this->prepareMultilingualMails($data);
38 }
39 }
40 $this->prepareMailFilter($data);
41
42 parent::display($data);
43 }
44
45 private function prepareMailFilter(array &$data): void
46 {
47 $data['input_mail_ids'] = '';
48
49 if (!empty($this->multiLanguageMailAdded) || !empty($this->generatedMailAdded)) {
50 $this->selectedMailIds = array_filter(
51 $this->selectedMailIds,
52 function ($mailId) {
53 return !in_array($mailId, $this->multiLanguageMailAdded) && !in_array($mailId, $this->generatedMailAdded);
54 }
55 );
56 }
57
58 if (count($this->selectedMailIds) > 1) {
59 $data['input_mail_ids'] = '<input type="hidden" value="'.implode(',', $this->selectedMailIds).'" name="mail_ids">';
60 }
61
62 $attributes = [
63 'class' => 'acym__select acym_select2_ajax acym__stats__select__mails',
64 'data-placeholder' => acym_translation('ACYM_ALL_EMAILS'),
65 'data-ctrl' => 'stats',
66 'data-task' => 'searchSentMail',
67 'data-min' => '0',
68 'id' => 'mail_ids',
69 ];
70
71 if (!empty($this->selectedMailIds)) {
72 $attributes['data-selected'] = implode(',', $this->selectedMailIds);
73 }
74
75 $data['mail_filter'] = acym_selectMultiple(
76 [],
77 'mail_ids',
78 [],
79 $attributes
80 );
81
82 $data['emailVersionsFilters'] = '';
83
84 if (!empty($data['emailVersions'])) {
85 $data['emailVersionsFilters'] = acym_select(
86 $data['emailVersions'],
87 'mail_id_version',
88 $this->selectedMailIds[0],
89 [
90 'class' => 'acym__select acym__stats__select__language',
91 ]
92 );
93 }
94 if (!empty($data['emailTranslations'])) {
95 $data['emailVersionsFilters'] = acym_select(
96 $data['emailTranslations'],
97 'mail_id_version',
98 $this->selectedMailIds[0],
99 [
100 'class' => 'acym__select acym__stats__select__language',
101 ]
102 );
103 }
104 }
105
106 private function prepareClickStats(array &$data): void
107 {
108 if (empty($data['selectedMailid'])) {
109 return;
110 }
111
112 $urlClickClass = new UrlClickClass();
113 $allClickInfo = $urlClickClass->getAllLinkFromEmail($this->selectedMailIds[0]);
114
115 $data['url_click'] = [];
116 $data['url_click']['allClick'] = $allClickInfo['allClick'];
117
118 $allPercentage = [];
119 foreach ($allClickInfo['urls_click'] as $url) {
120 $percentage = 0;
121 if (empty($url->click)) {
122 $data['url_click'][$url->name] = ['percentage' => $percentage, 'numberClick' => '0'];
123 } else {
124 $percentage = intval(($url->click * 100) / $allClickInfo['allClick']);
125 $data['url_click'][$url->name] = ['percentage' => $percentage, 'numberClick' => $url->click];
126 }
127 $allPercentage[] = $percentage;
128 }
129
130 $helperMailer = new MailerHelper();
131 if (!empty($data['mailInformation'])) {
132 $helperMailer->body = $data['mailInformation']->body;
133 $helperMailer->statClick(intval($data['mailInformation']->id), 0, true);
134 $data['mailInformation']->body = preg_replace('#&(amp;)?autoSubId=[^"]+"#Uis', '"', $helperMailer->body);
135 }
136
137 if (!empty($allPercentage)) {
138 $maxPercentage = max($allPercentage);
139
140 foreach ($data['url_click'] as $name => $val) {
141 if ($name === 'allClick') continue;
142 $percentageRecalc = intval(($val['percentage'] * 100) / $maxPercentage);
143 if ($percentageRecalc <= 33) {
144 $data['url_click'][$name]['color'] = '0, 164, 255';
145 } elseif ($percentageRecalc <= 66) {
146 $data['url_click'][$name]['color'] = '248, 31, 255';
147 } else {
148 $data['url_click'][$name]['color'] = '255, 82, 89';
149 }
150 }
151 }
152
153 $data['url_click'] = json_encode($data['url_click']);
154
155 $data['url_foundation_email'] = ACYM_CSS.'libraries/foundation_email.min.css?v='.filemtime(ACYM_MEDIA.'css'.DS.'libraries'.DS.'foundation_email.min.css');
156 $data['url_click_map_email'] = ACYM_CSS.'click_map.min.css?v='.filemtime(ACYM_MEDIA.'css'.DS.'click_map.min.css');
157 }
158
159 public function prepareDefaultRoundCharts(array &$data): void
160 {
161 $charts = [
162 'delivery' => [
163 'percentage' => 95,
164 'text' => 'ACYM_SUCCESSFULLY_SENT',
165 ],
166 'open' => [
167 'percentage' => 25,
168 'text' => 'ACYM_OPEN_RATE',
169 ],
170 'click' => [
171 'percentage' => 10,
172 'text' => 'ACYM_CLICK_RATE',
173 ],
174 'fail' => [
175 'percentage' => 2,
176 'text' => 'ACYM_BOUNCE_RATE',
177 ],
178 'unsub' => [
179 'percentage' => 3,
180 'text' => 'ACYM_UNSUBSCRIBE',
181 ],
182 ];
183
184 $data['example_round_chart'] = '';
185 foreach ($charts as $type => $oneChart) {
186 if ($type == 'unsub' && empty($this->selectedMailIds)) continue;
187 $data['example_round_chart'] .= '<div class="cell acym__stats__donut__one-chart">';
188 $data['example_round_chart'] .= acym_roundChart(
189 $oneChart['percentage'],
190 $type,
191 '',
192 acym_translation($oneChart['text'])
193 );
194 $data['example_round_chart'] .= '</div>';
195 }
196 }
197
198 public function prepareDefaultLineChart(array &$data): void
199 {
200 $dataMonth = [];
201 $dataMonth['Jan 18'] = ['open' => '150', 'click' => '40'];
202 $dataDay = [];
203 $dataDay['23 Jan'] = ['open' => '150', 'click' => '40'];
204 $dataHour = [];
205 $dataHour['23 Jan 08:00'] = ['open' => '25', 'click' => '10'];
206 $dataHour['23 Jan 09:00'] = ['open' => '50', 'click' => '10'];
207 $dataHour['23 Jan 10:00'] = ['open' => '16', 'click' => '10'];
208 $dataHour['23 Jan 11:00'] = ['open' => '59', 'click' => '10'];
209 $data['example_line_chart'] = acym_lineChart($dataMonth, $dataDay, $dataHour);
210 }
211
212 public function prepareDefaultDevicesChart(array &$data): void
213 {
214 $defaultData = [
215 'ACYM_MOBILE' => 25662,
216 'ACYM_DESKTOP' => 12471,
217 'ACYM_OTHER' => 3548,
218 'ACYM_UNKNOWN' => 6213,
219 ];
220
221 $data['example_devices_chart'] = acym_pieChart($defaultData, '', acym_translation('ACYM_DEVICES'));
222 }
223
224 public function prepareDefaultBrowsersChart(array &$data): void
225 {
226 $exampleData = [
227 'Apple Mail' => 15835,
228 'Google Chrome' => 13375,
229 'Safari' => 2667,
230 'Outlook' => 2458,
231 'Edge' => 1190,
232 'Firefox' => 826,
233 'ACYM_OTHER' => 4775,
234 'ACYM_UNKNOWN' => 6123,
235 ];
236
237 $data['example_source_chart'] = acym_pieChart($exampleData, '', acym_translation('ACYM_OPENED_WITH'));
238 }
239
240 public function setDataForChartLine(): void
241 {
242 $newStart = acym_date(acym_getVar('string', 'start'), 'Y-m-d H:i:s');
243 $newEnd = acym_date(acym_getVar('string', 'end'), 'Y-m-d H:i:s');
244 $mailIds = acym_getVar('int', 'id');
245
246 if (empty($mailIds)) {
247 $mailIds = [];
248 }
249
250 $mailClass = new MailClass();
251 if (!empty($mailIds)) {
252 $mailIds = $mailClass->getAutomaticMailIds($mailIds);
253 }
254
255 if (!empty($mailIds) && !is_array($mailIds)) {
256 $mailIds = [$mailIds];
257 }
258
259 if ($newStart >= $newEnd) {
260 echo 'error';
261 exit;
262 }
263
264 $statsCampaignSelected = new \stdClass();
265 $this->prepareLineChart($statsCampaignSelected, $mailIds, $newStart, $newEnd);
266
267 echo acym_lineChart($statsCampaignSelected->month, $statsCampaignSelected->day, $statsCampaignSelected->hour, true);
268 exit;
269 }
270
271 private function getValues(string $modifier, string $intervalCode, array $campaignOpens, array $campaignClicks, string $dateCode, bool $hour = false): array
272 {
273 $opens = [];
274 foreach ($campaignOpens as $one) {
275 $opens[acym_date(acym_getTime($one->open_date), $dateCode)] = $one->open;
276 }
277
278 $clicks = [];
279 foreach ($campaignClicks as $one) {
280 $clicks[acym_date(acym_getTime($one->date_click), $dateCode)] = $one->click;
281 }
282
283 $begin = new \DateTime(empty($campaignClicks) ? $campaignOpens[0]->open_date : min([$campaignOpens[0]->open_date, $campaignClicks[0]->date_click]));
284 $end = new \DateTime(empty($campaignClicks) ? end($campaignOpens)->open_date : max([end($campaignOpens)->open_date, end($campaignClicks)->date_click]));
285
286 $end->modify('+1 '.$modifier);
287
288 $interval = new \DateInterval($intervalCode);
289 $daterange = new \DatePeriod($begin, $interval, $end);
290
291 $result = [];
292 foreach ($daterange as $date) {
293 $one = $date->format($dateCode);
294
295 $current = [];
296 $current['open'] = empty($opens[$one]) ? 0 : $opens[$one];
297 $current['click'] = empty($clicks[$one]) ? 0 : $clicks[$one];
298
299 $key = $hour ? $one.':00' : $one;
300 $result[$key] = $current;
301 }
302
303 return $result;
304 }
305
306 public function prepareLineChart(object &$statsCampaignSelected, array $mailIdsOfCampaign, string $newStart = '', string $newEnd = ''): void
307 {
308 $campaignClass = new CampaignClass();
309 $statsCampaignSelected->hasStats = true;
310
311 $campaignOpenByMonth = $campaignClass->getOpenByMonth($mailIdsOfCampaign, $newStart, $newEnd);
312 $campaignOpenByDay = $campaignClass->getOpenByDay($mailIdsOfCampaign, $newStart, $newEnd);
313 $campaignOpenByHour = $campaignClass->getOpenByHour($mailIdsOfCampaign, $newStart, $newEnd);
314
315 if (empty($campaignOpenByMonth) || empty($campaignOpenByDay) || empty($campaignOpenByHour)) {
316 $statsCampaignSelected->hasStats = false;
317
318 return;
319 }
320
321 $urlClickClass = new UrlClickClass();
322 $campaignClickByMonth = $urlClickClass->getAllClickByMailMonth($mailIdsOfCampaign, $newStart, $newEnd);
323 $campaignClickByDay = $urlClickClass->getAllClickByMailDay($mailIdsOfCampaign, $newStart, $newEnd);
324 $campaignClickByHour = $urlClickClass->getAllClickByMailHour($mailIdsOfCampaign, $newStart, $newEnd);
325
326 $statsCampaignSelected->month = $this->getValues('day', 'P1M', $campaignOpenByMonth, $campaignClickByMonth, 'Y-m');
327 $statsCampaignSelected->day = $this->getValues('hour', 'P1D', $campaignOpenByDay, $campaignClickByDay, 'Y-m-d');
328 $statsCampaignSelected->hour = $this->getValues('min', 'PT1H', $campaignOpenByHour, $campaignClickByHour, 'Y-m-d H:i', true);
329
330 $allHour = array_keys($statsCampaignSelected->hour);
331
332 $statsCampaignSelected->startEndDateHour = [];
333 $statsCampaignSelected->startEndDateHour['start'] = $allHour[0];
334 $statsCampaignSelected->startEndDateHour['end'] = end($allHour);
335 }
336
337 public function exportGlobal(): void
338 {
339 $exportType = acym_getVar('string', 'export_type', 'charts');
340
341 $functionName = 'exportGlobal'.ucfirst($exportType);
342
343 if (!method_exists($this, $functionName)) {
344 acym_enqueueMessage(acym_translation('ACYM_EXPORT_METHOD_NOT_FOUND'), 'error');
345 $this->listing();
346
347 return;
348 }
349
350 $this->$functionName();
351 }
352
353 public function prepareOpenTimeChart(array &$data): void
354 {
355 $userStatClass = new UserStatClass();
356 $statsDB = $userStatClass->getOpenTimeStats($this->selectedMailIds);
357
358 if (empty($statsDB['total_open'])) {
359 $data['openTime'] = $userStatClass->getDefaultStat();
360 $data['empty_open'] = true;
361
362 return;
363 }
364 $data['empty_open'] = false;
365
366 $stats = [];
367
368 for ($day = 0 ; $day < 7 ; $day++) {
369 $stats[$day] = [];
370 for ($hour = 0 ; $hour < 8 ; $hour++) {
371 if (empty($statsDB['stats'][$day.'_'.$hour]) || empty($statsDB['total_open'])) {
372 $percentage = 0;
373 } else {
374 $percentage = ($statsDB['stats'][$day.'_'.$hour]->open_total * 100) / $statsDB['total_open'];
375 }
376 $stats[$day][$hour] = round($percentage);
377 }
378 }
379
380 $data['openTime'] = $stats;
381 }
382
383 public function prepareStatByList(array &$data): void
384 {
385 $mailid = (count(array_unique($data['selectedMailid'])) != 1) ? 0 : $data['selectedMailid'][0];
386
387 if (empty($mailid)) {
388 return;
389 }
390
391 $mailSelected = $this->getVarFiltersListing('int', 'mail_id_language', $mailid);
392
393 $mailClass = new MailClass();
394 $mail = $mailClass->getOneById($mailSelected);
395 $mainMailId = empty($mail->parent_id) ? $mail->id : $mail->parent_id;
396
397 $data['lists'] = [];
398 $data['emailsSent'] = [];
399 $data['emailsOpen'] = [];
400 $data['bounces'] = [];
401 $data['unsubscribed'] = [];
402 $data['click'] = [];
403 $data['listsStats'] = [];
404 $data['userPerList'] = [];
405
406 $query = 'SELECT l.id, l.name, l.color FROM #__acym_list l';
407 $query .= ' JOIN #__acym_mail_has_list ml on l.id = ml.list_id';
408 $query .= ' WHERE ml.mail_id = '.$mainMailId;
409
410 $data['lists'] = acym_loadObjectList($query, 'id');
411 $listIds = implode(',', array_keys($data['lists']));
412
413 if (!empty($listIds)) {
414 $query = 'SELECT ul.list_id, SUM(us.sent) as nbSent, SUM(IF(us.open >= 1, 1, 0)) as nbOpen, SUM(us.bounce) as nbBounce, SUM(us.unsubscribe) as nbUnsub from #__acym_user_has_list ul';
415 $query .= ' JOIN #__acym_user_stat us on ul.user_id = us.user_id';
416 $query .= ' WHERE ul.list_id in ('.$listIds.') AND us.mail_id = '.$mailSelected;
417 $query .= ' GROUP BY ul.list_id;';
418 $data['listsStats'] = acym_loadObjectList($query, 'list_id');
419
420 $query = 'SELECT ul.list_id, COUNT(uc.click) as nbClick';
421 $query .= ' FROM #__acym_user_has_list ul ';
422 $query .= ' JOIN #__acym_url_click uc on ul.user_id = uc.user_id';
423 $query .= ' WHERE ul.list_id in ('.$listIds.') AND uc.mail_id = '.$mailSelected;
424 $query .= ' GROUP BY ul.list_id;';
425
426 $data['nbClick'] = acym_loadObjectList($query, 'list_id');
427
428 $query = 'SELECT ul.list_id, COUNT(ul.user_id) as nbUser';
429 $query .= ' FROM #__acym_user_has_list ul';
430 $query .= ' JOIN #__acym_user_stat us ON ul.user_id = us.user_id';
431 $query .= ' WHERE ul.list_id in ('.$listIds.') AND us.mail_id = '.$mailSelected;
432 $query .= ' GROUP BY ul.list_id;';
433
434 $data['userPerList'] = acym_loadObjectList($query, 'list_id');
435 }
436
437 foreach ($data['listsStats'] as $listId => $item) {
438 $data['emailsSent'][$listId] = [
439 'label' => $data['lists'][$listId]->name,
440 'value' => $item->nbSent,
441 'color' => $data['lists'][$listId]->color,
442 ];
443 $data['emailsOpen'][$listId] = [
444 'label' => $data['lists'][$listId]->name,
445 'value' => round(($item->nbOpen * 100) / $item->nbSent),
446 'color' => $data['lists'][$listId]->color,
447 ];
448 $data['bounces'][$listId] = [
449 'label' => $data['lists'][$listId]->name,
450 'value' => round(($item->nbBounce * 100) / $item->nbSent),
451 'color' => $data['lists'][$listId]->color,
452 ];
453 $data['unsubscribed'][$listId] = [
454 'label' => $data['lists'][$listId]->name,
455 'value' => round(($item->nbUnsub * 100) / $item->nbSent),
456 'color' => $data['lists'][$listId]->color,
457 ];
458 }
459
460 foreach ($data['userPerList'] as $listId => $item) {
461 $nbUser = $item->nbUser;
462 $data['click'][$listId] = ['label' => $data['lists'][$listId]->name, 'value' => 0, 'color' => $data['lists'][$listId]->color];
463
464 if ($nbUser > 0 && !empty($data['nbClick'][$listId]->nbClick)) {
465 $data['click'][$listId]['value'] = round(($data['nbClick'][$listId]->nbClick * 100) / $nbUser);
466 }
467 }
468 }
469
470 private function prepareAbTestMails(array &$data): void
471 {
472 if (empty($this->selectedMailIds)) return;
473
474 $mailClass = new MailClass();
475
476 $mailVersions = [];
477
478 if (empty($data['mailInformation']->parent_id)) {
479 $mailVersions = $mailClass->getParentAndChildMails($data['mailInformation']->id);
480 } elseif (!empty($data['mailInformation']->parent_id)) {
481 $parentEmail = $mailClass->getOneById($data['mailInformation']->parent_id);
482 if (empty($parentEmail)) return;
483 $mailVersions = $mailClass->getParentAndChildMails($parentEmail->id);
484 }
485
486 $data['emailVersions'] = [];
487
488 foreach ($mailVersions as $email) {
489 $data['emailVersions'][$email->id] = $email->name.' - '.$email->subject;
490 }
491 }
492
493 private function prepareMultilingualMails(array &$data): void
494 {
495 if (empty($this->selectedMailIds)) return;
496
497 $mailClass = new MailClass();
498
499 $translatedEmails = [];
500
501 if (empty($data['mailInformation']->parent_id)) {
502 $translatedEmails = $mailClass->getTranslationsById($data['mailInformation']->id, true, true);
503 } elseif (!empty($data['mailInformation']->parent_id)) {
504 $parentEmail = $mailClass->getOneById($data['mailInformation']->parent_id);
505 if (empty($parentEmail)) return;
506 $translatedEmails = $mailClass->getTranslationsById($parentEmail->id, true, true);
507 }
508
509 $data['emailTranslations'] = [];
510 $allLanguages = acym_getLanguages();
511
512 foreach ($translatedEmails as $email) {
513 if (!empty($email->language)) {
514 $data['emailTranslations'][$email->id] = empty($allLanguages[$email->language]) ? $email->language
515 : $allLanguages[$email->language]->name;
516 }
517 }
518 }
519
520 private function prepareDevicesStats(array &$data): void
521 {
522 $campaignClass = new CampaignClass();
523 $devicesCampaign = $campaignClass->getDevicesWithCountByMailId($this->selectedMailIds);
524
525 $data['devices'] = [
526 'ACYM_MOBILE' => 0,
527 'ACYM_DESKTOP' => 0,
528 'ACYM_OTHER' => 0,
529 'ACYM_UNKNOWN' => 0,
530 ];
531
532 foreach ($devicesCampaign as $oneDevice) {
533 if (empty($oneDevice->number)) {
534 continue;
535 }
536
537 if (empty($oneDevice->device)) {
538 $device = 'ACYM_UNKNOWN';
539 } elseif (in_array($oneDevice->device, array_merge(BrowserDetection::PLATFORMS_MOBILE, BrowserDetection::LEGACY_PLATFORMS_MOBILE))) {
540 $device = 'ACYM_MOBILE';
541 } elseif (in_array($oneDevice->device, array_merge(BrowserDetection::PLATFORMS_DESKTOP, BrowserDetection::LEGACY_PLATFORMS_DESKTOP))) {
542 $device = 'ACYM_DESKTOP';
543 } else {
544 $device = 'ACYM_OTHER';
545 }
546
547 $data['devices'][$device] += $oneDevice->number;
548 }
549 }
550
551 private function prepareOpenSourcesStats(array &$data): void
552 {
553 $userStatClass = new UserStatClass();
554 $openedFromStats = $userStatClass->getOpenSourcesStats($this->selectedMailIds);
555
556 $data['openedWith'] = [];
557 foreach ($openedFromStats as $oneSource) {
558 if (empty($oneSource->number)) {
559 continue;
560 }
561
562 if (!empty($oneSource->opened_with) && isset(BrowserDetection::LEGACY_OPENED_WITH_MAP[$oneSource->opened_with])) {
563 $oneSource->opened_with = BrowserDetection::LEGACY_OPENED_WITH_MAP[$oneSource->opened_with];
564 }
565
566 if (empty($oneSource->opened_with)) {
567 $oneSource->opened_with = 'ACYM_UNKNOWN';
568 }
569
570 $data['openedWith'][$oneSource->opened_with] = $oneSource->number;
571 }
572 }
573
574 public function preparecharts(array &$data): void
575 {
576 $mailStatClass = new MailStatClass();
577
578 $data['mail'] = $mailStatClass->getSentFailByMailIds($this->selectedMailIds);
579 if (empty($data['mail'])) return;
580
581 $campaignClass = new CampaignClass();
582 $urlClickClass = new UrlClickClass();
583
584 $data['mail']->totalMail = $data['mail']->sent + $data['mail']->fail;
585 $data['mail']->percentageSent = empty($data['mail']->totalMail) ? 0 : number_format(($data['mail']->sent * 100) / $data['mail']->totalMail, 2);
586 $data['mail']->allSent = empty($data['mail']->totalMail)
587 ? acym_translationSprintf('ACYM_X_MAIL_SUCCESSFULLY_SENT_OF_X', 0, 0)
588 : acym_translationSprintf(
589 'ACYM_X_MAIL_SUCCESSFULLY_SENT_OF_X',
590 $data['mail']->sent,
591 $data['mail']->totalMail
592 );
593
594 $openRateCampaign = empty($this->selectedMailIds) ? $campaignClass->getOpenRateAllCampaign() : $campaignClass->getOpenRateCampaigns($this->selectedMailIds);
595 $data['mail']->percentageOpen = empty($openRateCampaign->sent) ? 0 : number_format(($openRateCampaign->open_unique * 100) / $openRateCampaign->sent, 2);
596 $data['mail']->allOpen = empty($openRateCampaign->sent)
597 ? acym_translationSprintf('ACYM_X_MAIL_OPENED_OF_X', 0, 0)
598 : acym_translationSprintf(
599 'ACYM_X_MAIL_OPENED_OF_X',
600 $openRateCampaign->open_unique,
601 $openRateCampaign->sent
602 );
603
604 $clickRateCampaign = $urlClickClass->getNumberUsersClicked($this->selectedMailIds);
605 $data['mail']->percentageClick = empty($data['mail']->sent) ? 0 : number_format(($clickRateCampaign * 100) / $data['mail']->sent, 2);
606 $data['mail']->allClick = empty($data['mail']->sent)
607 ? acym_translationSprintf('ACYM_X_MAIL_CLICKED_OF_X', 0, 0)
608 : acym_translationSprintf(
609 'ACYM_X_MAIL_CLICKED_OF_X',
610 $clickRateCampaign,
611 $data['mail']->sent
612 );
613
614 $bounceRateCampaign = empty($this->selectedMailIds) ? $campaignClass->getBounceRateAllCampaign() : $campaignClass->getBounceRateCampaigns($this->selectedMailIds);
615 $data['mail']->percentageBounce = empty($data['mail']->sent) ? 0 : number_format(($bounceRateCampaign->bounce_unique * 100) / $data['mail']->sent, 2);
616 $data['mail']->allBounce = empty($data['mail']->sent)
617 ? acym_translationSprintf('ACYM_X_BOUNCE_OF_X', 0, 0)
618 : acym_translationSprintf(
619 'ACYM_X_BOUNCE_OF_X',
620 $bounceRateCampaign->bounce_unique,
621 $data['mail']->sent
622 );
623
624 if (!empty($this->selectedMailIds)) {
625 $mailStat = $mailStatClass->getByMailIds($this->selectedMailIds);
626 $data['mail']->percentageUnsub = empty($data['mail']->sent) ? 0 : number_format(($mailStat->unsubscribe_total * 100) / $data['mail']->sent, 2);
627 $data['mail']->allUnsub = empty($data['mail']->sent)
628 ? acym_translationSprintf('ACYM_X_USERS_UNSUBSCRIBED_OF_X', 0, 0)
629 : acym_translationSprintf(
630 'ACYM_X_USERS_UNSUBSCRIBED_OF_X',
631 $mailStat->unsubscribe_total,
632 $data['mail']->sent
633 );
634 }
635
636 $this->prepareDevicesStats($data);
637 $this->prepareOpenSourcesStats($data);
638 $this->prepareLineChart($data['mail'], $this->selectedMailIds);
639 }
640
641 private function decode(array &$detailedStats, array $columnsToDecode = ['mail_subject', 'mail_name']): void
642 {
643 foreach ($detailedStats as $oneDetailedStat) {
644 foreach ($columnsToDecode as $column) {
645 if (!empty($oneDetailedStat->$column)) {
646 $oneDetailedStat->$column = acym_utf8Decode($oneDetailedStat->$column);
647 }
648 }
649 }
650 }
651
652 private function prepareLinksDetailsListing(array &$data): void
653 {
654 $data['search'] = $this->getVarFiltersListing('string', 'links_details_search', '');
655 $data['ordering'] = $this->getVarFiltersListing('string', 'links_details_ordering', 'id');
656 $data['orderingSortOrder'] = $this->getVarFiltersListing('string', 'links_details_ordering_sort_order', 'desc');
657
658 if (empty($this->selectedMailIds)) return;
659
660 $pagination = new PaginationHelper();
661 $urlClickClass = new UrlClickClass();
662
663 $detailedStatsPerPage = $pagination->getListLimit();
664 $page = $this->getVarFiltersListing('int', 'links_details_pagination_page', 1);
665
666 $urlClicks = $urlClickClass->getUrlsFromMailsWithDetails(
667 [
668 'ordering' => $data['ordering'],
669 'search' => $data['search'],
670 'detailedStatsPerPage' => $detailedStatsPerPage,
671 'offset' => ($page - 1) * $detailedStatsPerPage,
672 'ordering_sort_order' => $data['orderingSortOrder'],
673 'mail_ids' => $this->selectedMailIds,
674 ]
675 );
676
677 $this->decode($urlClicks['links_details']);
678
679 $pagination->setStatus((int)$urlClicks['total']->total, $page, $detailedStatsPerPage);
680
681 $data['pagination'] = $pagination;
682 $data['links_details'] = $urlClicks['links_details'];
683 $data['query'] = $urlClicks['query'];
684 }
685
686 private function prepareListReceivers(array &$data): void
687 {
688 if (empty($this->selectedMailIds)) return;
689
690 $mailStatClass = new MailStatClass();
691 $mailClass = new MailClass();
692
693 $data['mailStat'] = $mailStatClass->getByMailIds($this->selectedMailIds);
694 $data['lists'] = $mailClass->getAllListsByMailId($this->selectedMailIds);
695 }
696
697 private function exportGlobalFormatted(): void
698 {
699 $exportHelper = new ExportHelper();
700 $data = [];
701 $this->prepareDefaultPageInfo($data);
702 $data['show_date_filters'] = true;
703 $data['page_title'] = false;
704 $timeLinechart = acym_getVar('string', 'time_linechart', 'month');
705
706
707 $this->prepareMailFilter($data);
708 $this->prepareClickStats($data);
709 $this->preparecharts($data);
710 $this->prepareDefaultRoundCharts($data);
711 $this->prepareDefaultLineChart($data);
712 $this->prepareDefaultDevicesChart($data);
713 $this->prepareDefaultBrowsersChart($data);
714
715 $globalDonut = [
716 $data['mail']->percentageSent,
717 $data['mail']->percentageOpen,
718 $data['mail']->percentageClick,
719 $data['mail']->percentageBounce,
720 $data['mail']->percentageUnsub,
721 ];
722 $mailName = empty($this->selectedMailIds) ? acym_translation('ACYM_ALL_MAILS') : $data['mailInformation']->name;
723 $globalLine = $data['mail']->$timeLinechart;
724
725 $exportHelper->exportStatsFormattedCSV($mailName, $globalDonut, $globalLine, $timeLinechart);
726 exit;
727 }
728
729 private function exportGlobalFull(): void
730 {
731 $exportHelper = new ExportHelper();
732 $data = [];
733 $this->prepareDefaultPageInfo($data);
734
735 $where = '';
736 if (!empty($this->selectedMailIds)) {
737 $where = 'WHERE mail_id IN ('.implode(',', $this->selectedMailIds).')';
738 }
739
740 $columnsMailStat = acym_getColumns('mail_stat');
741 $columnsToExport = [];
742
743 $columnsToExport['mail.subject'] = acym_translation('ACYM_EMAIL_SUBJECT');
744 foreach ($columnsMailStat as $column) {
745 if ($column === 'mail_id') {
746 continue;
747 }
748
749 $translation = acym_translation('ACYM_'.strtoupper($column).'_COLUMN_STAT');
750 if ($column === 'send_date') {
751 $translation = acym_translation('ACYM_SEND_DATE');
752 } elseif ($column === 'click_total') {
753 $translation = acym_translation('ACYM_TOTAL_CLICKS');
754 } elseif ($column === 'click_unique') {
755 $translation = acym_translation('ACYM_UNIQUE_CLICKS');
756 }
757
758 $columnsToExport['mailstat.'.$column] = $translation;
759 }
760
761 $query = 'SELECT '.implode(', ', array_keys($columnsToExport)).' FROM #__acym_mail_stat AS mailstat LEFT JOIN #__acym_mail AS mail ON mail.id = mailstat.mail_id '.$where;
762 $exportHelper->exportStatsFullCSV($query, $columnsToExport);
763 exit;
764 }
765 }
766