PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 11.1.0
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v11.1.0
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
← All changes | back/Classes/FollowupClass.php +143 -77 10.1.4 → 11.1.0 View file →
@@ -23,9 +23,9 @@
23 23 $this->table = 'followup';
24 24 $this->pkey = 'id';
25 25 }
26 26
27 - public function getDelayUnits()
27 + public function getDelayUnits(): array
28 28 {
29 29 $return = self::DELAY_UNIT;
30 30 foreach ($return as $key => $value) {
31 31 $return[$key] = acym_translation($value);
@@ -81,9 +81,9 @@
81 81
82 82 return $results;
83 83 }
84 84
85 - public function getNumberSubscribersByListId($listId = 0, $onlySubscribed = false)
85 + public function getNumberSubscribersByListId(int $listId = 0, bool $onlySubscribed = false): int
86 86 {
87 87 if (empty($listId)) return 0;
88 88
89 89 $query = 'SELECT COUNT(*)
@@ -93,12 +93,12 @@
93 93 if ($onlySubscribed) {
94 94 $query .= ' AND `status` = 1';
95 95 }
96 96
97 - return acym_loadResult($query);
97 + return (int)acym_loadResult($query);
98 98 }
99 99
100 - private function getGlobalStats(&$element, $urlClickClass)
100 + private function getGlobalStats(object $element, UrlClickClass $urlClickClass): void
101 101 {
102 102 $mailsStats = acym_loadObjectList(
103 103 'SELECT mail_stat.*
104 104 FROM #__acym_mail_stat AS mail_stat
@@ -113,9 +113,9 @@
113 113 if (empty($mailsStats)) return;
114 114
115 115 foreach ($mailsStats as $key => $mailsStat) {
116 116 $element->open += $mailsStat->open_unique;
117 - $element->click += $urlClickClass->getNumberUsersClicked($mailsStat->mail_id);
117 + $element->click += $urlClickClass->getNumberUsersClicked([$mailsStat->mail_id]);
118 118 $numberMailSent += $mailsStat->sent;
119 119 }
120 120
121 121 if (!empty($numberMailSent)) {
@@ -122,8 +122,9 @@
122 122 $element->open = number_format($element->open / $numberMailSent * 100, 2);
123 123 $element->click = number_format($element->click / $numberMailSent * 100, 2);
124 124 }
125 125
126 + //Tracking sales
126 127 if (!acym_isTrackingSalesActive()) return;
127 128
128 129 $trackingSales = acym_loadObject(
129 130 'SELECT SUM(user_stat.tracking_sale) AS sale, user_stat.currency
@@ -132,15 +133,17 @@
132 133 WHERE fhm.followup_id = '.intval($element->id)
133 134 );
134 135
135 136 $element->sale = $trackingSales->sale;
136 - if (empty($element->currency)) $element->currency = '';
137 + if (empty($element->currency)) {
138 + $element->currency = '';
139 + }
140 +
137 141 acym_trigger('getCurrency', [&$element->currency]);
138 142 }
139 143
140 - public function delete($elements)
144 + public function delete(array $elements): int
141 145 {
142 - if (!is_array($elements)) $elements = [$elements];
143 146 acym_arrayToInteger($elements);
144 147
145 148 if (empty($elements)) return 0;
146 149
@@ -159,14 +162,15 @@
159 162
160 163 return $result;
161 164 }
162 165
163 - public function getEmailsByIds($followupIds)
166 + public function getEmailsByIds(array $followupIds): array
164 167 {
165 - if (!is_array($followupIds)) $followupIds = [$followupIds];
166 168 acym_arrayToInteger($followupIds);
167 169
168 - if (empty($followupIds)) return [];
170 + if (empty($followupIds)) {
171 + return [];
172 + }
169 173
170 174 return acym_loadResultArray(
171 175 'SELECT `mail_id`
172 176 FROM #__acym_followup_has_mail
@@ -174,14 +178,15 @@
174 178 ORDER BY `delay`*`delay_unit` ASC'
175 179 );
176 180 }
177 181
178 - public function getListsByIds($followupIds)
182 + public function getListsByIds(array $followupIds): array
179 183 {
180 - if (!is_array($followupIds)) $followupIds = [$followupIds];
181 184 acym_arrayToInteger($followupIds);
182 185
183 - if (empty($followupIds)) return [];
186 + if (empty($followupIds)) {
187 + return [];
188 + }
184 189
185 190 return acym_loadResultArray(
186 191 'SELECT `list_id`
187 192 FROM #__acym_followup
@@ -188,13 +193,13 @@
188 193 WHERE `id` IN ('.implode(', ', $followupIds).')'
189 194 );
190 195 }
191 196
192 - public function getOneById($id)
197 + public function getOneById(int $id): ?object
193 198 {
194 199 $followup = parent::getOneById($id);
195 200
196 - if (empty($followup)) return false;
201 + if (empty($followup)) return null;
197 202
198 203 if (!empty($followup->condition)) {
199 204 $followup->condition = json_decode($followup->condition, true);
200 205 }
@@ -205,20 +210,24 @@
205 210
206 211 return $followup;
207 212 }
208 213
209 - public function getOneByListId($listId)
214 + public function getOneByListId(int $listId): ?object
210 215 {
211 216 $followup = acym_loadObject('SELECT * FROM `#__acym_followup` WHERE `list_id` = '.intval($listId));
212 217
213 - if (empty($followup)) return null;
218 + if (empty($followup)) {
219 + return null;
220 + }
214 221
215 - if (!empty($followup->condition)) $followup->condition = json_decode($followup->condition, true);
222 + if (!empty($followup->condition)) {
223 + $followup->condition = json_decode($followup->condition, true);
224 + }
216 225
217 226 return $followup;
218 227 }
219 228
220 - public function save($element)
229 + public function save(object $element): ?int
221 230 {
222 231 if (!empty($element->condition) && is_array($element->condition)) {
223 232 $element->condition = json_encode($element->condition);
224 233 }
@@ -231,9 +240,9 @@
231 240
232 241 return parent::save($element);
233 242 }
234 243
235 - private function updateListFollowup(&$element)
244 + private function updateListFollowup(object $element): void
236 245 {
237 246 $listClass = new ListClass();
238 247 if (empty($element->list_id)) {
239 248 $list = new \stdClass();
@@ -238,10 +247,16 @@
238 247 if (empty($element->list_id)) {
239 248 $list = new \stdClass();
240 249 $list->name = $element->display_name;
241 250 $list->description = '';
242 - $randColor = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
243 - $list->color = '#'.$randColor[rand(0, 15)].$randColor[rand(0, 15)].$randColor[rand(0, 15)].$randColor[rand(0, 15)].$randColor[rand(0, 15)].$randColor[rand(0, 15)];
251 + $list->color = '#'.implode('', [
252 + ListClass::COLOR_PARTS[acym_rand(0, 15)],
253 + ListClass::COLOR_PARTS[acym_rand(0, 15)],
254 + ListClass::COLOR_PARTS[acym_rand(0, 15)],
255 + ListClass::COLOR_PARTS[acym_rand(0, 15)],
256 + ListClass::COLOR_PARTS[acym_rand(0, 15)],
257 + ListClass::COLOR_PARTS[acym_rand(0, 15)],
258 + ]);
244 259 $list->access = '';
245 260 $list->type = ListClass::LIST_TYPE_FOLLOWUP;
246 261 } else {
247 262 $list = $listClass->getOneById($element->list_id);
@@ -250,21 +265,11 @@
250 265
251 266 $element->list_id = $listClass->save($list);
252 267 }
253 268
254 - public function getTriggerNiceName($trigger)
269 + public function getConditionSummary(object $followup): array
255 270 {
256 - $triggers = [];
257 - acym_trigger('getFollowupTriggers', [&$triggers]);
258 - if (key_exists($trigger, $triggers)) {
259 - return $triggers[$trigger];
260 - }
261 -
262 - return '';
263 - }
264 -
265 - public function getConditionSummary($condition, $trigger)
266 - {
271 + $condition = $followup->condition;
267 272 $statusArray = [
268 273 'is' => acym_strtolower(acym_translation('ACYM_IS')),
269 274 'is_not' => acym_strtolower(acym_translation('ACYM_IS_NOT')),
270 275 ];
@@ -280,9 +285,9 @@
280 285 foreach ($lists as $list) {
281 286 $listsToDisplay[] = $list->name;
282 287 }
283 288
284 - $translationKey = $trigger === 'user_subscribe' ? 'ACYM_X_SUBSCRIBING_X_LIST' : 'ACYM_X_SUBSCRIBED_X_LIST';
289 + $translationKey = $followup->trigger === 'user_subscribe' ? 'ACYM_X_SUBSCRIBING_X_LIST' : 'ACYM_X_SUBSCRIBED_X_LIST';
285 290 $return[] = acym_translationSprintf($translationKey, acym_strtolower($statusArray[$condition['lists_status']]), implode(',', $listsToDisplay));
286 291 }
287 292
288 293
@@ -296,14 +301,14 @@
296 301 }
297 302 $return[] = acym_translationSprintf('ACYM_X_PART_X_SEGMENT', acym_strtolower($statusArray[$condition['segments_status']]), implode(',', $segmentsToDisplay));
298 303 }
299 304
300 - acym_trigger('getFollowupConditionSummary', [&$return, $condition, $trigger, $statusArray]);
305 + acym_trigger('getFollowupConditionSummary', [&$return, $condition, $followup->trigger, $statusArray]);
301 306
302 307 return $return;
303 308 }
304 309
305 - private function getKeyMailArray($key, $mailsKey)
310 + private function getKeyMailArray(int $key, array $mailsKey): int
306 311 {
307 312 if (!empty($mailsKey) && in_array($key, $mailsKey)) {
308 313 return $this->getKeyMailArray(++$key, $mailsKey);
309 314 }
@@ -310,20 +315,22 @@
310 315
311 316 return $key;
312 317 }
313 318
314 - public function getOneByIdWithMails($id)
319 + public function getOneByIdWithMails(int $id): ?object
315 320 {
316 321 $followup = $this->getOneById($id);
317 322
318 - if (empty($followup)) return false;
323 + if (empty($followup)) {
324 + return null;
325 + }
319 326
320 327 $mailClass = new MailClass();
321 328 $mails = $mailClass->decode(
322 329 acym_loadObjectList(
323 330 'SELECT mail.subject, mail.id, followup_mail.delay, followup_mail.delay_unit
324 - FROM #__acym_mail AS mail
325 - JOIN #__acym_followup_has_mail AS followup_mail ON mail.id = followup_mail.mail_id AND followup_mail.followup_id = '.intval($id),
331 + FROM #__acym_mail AS mail
332 + JOIN #__acym_followup_has_mail AS followup_mail ON mail.id = followup_mail.mail_id AND followup_mail.followup_id = '.intval($id),
326 333 'id'
327 334 )
328 335 );
329 336
@@ -341,9 +348,9 @@
341 348
342 349 return $followup;
343 350 }
344 351
345 - private function getDelayDisplay($delay, $delayUnit)
352 + private function getDelayDisplay(int $delay, int $delayUnit): string
346 353 {
347 354 $delayUnits = $this->getDelayUnits();
348 355
349 356 return acym_translationSprintf('ACYM_X_PLUS_X_FOLLOW_UP', $delayUnits[$delayUnit], $delay);
@@ -348,13 +355,15 @@
348 355
349 356 return acym_translationSprintf('ACYM_X_PLUS_X_FOLLOW_UP', $delayUnits[$delayUnit], $delay);
350 357 }
351 358
352 - public function getDelaySettingToMail(&$mail, $followupId)
359 + public function getDelaySettingToMail(object $mail, int $followupId): bool
353 360 {
354 361 $settings = acym_loadObject('SELECT delay, delay_unit FROM #__acym_followup_has_mail WHERE followup_id = '.intval($followupId).' AND mail_id = '.intval($mail->id));
355 362
356 - if (empty($settings)) return false;
363 + if (empty($settings)) {
364 + return false;
365 + }
357 366
358 367 $mail->delay = $settings->delay;
359 368 $mail->delay_unit = $settings->delay_unit;
360 369
@@ -360,11 +369,13 @@
360 369
361 370 return true;
362 371 }
363 372
364 - public function saveDelaySettings($followupData, $mailId)
373 + public function saveDelaySettings(array $followupData, int $mailId): bool
365 374 {
366 - if (empty($followupData['id']) || empty($followupData['delay_unit']) || empty($mailId)) return false;
375 + if (empty($followupData['id']) || empty($followupData['delay_unit']) || empty($mailId)) {
376 + return false;
377 + }
367 378
368 379 acym_arrayToInteger($followupData);
369 380
370 381 $affectedRow = acym_query(
@@ -375,15 +386,20 @@
375 386
376 387 return $affectedRow !== false;
377 388 }
378 389
379 - public function duplicateMail($mailId, $id)
390 + public function duplicateMail(int $mailId, int $id): bool
380 391 {
381 - if (empty($mailId) || empty($id)) return false;
392 + if (empty($mailId) || empty($id)) {
393 + return false;
394 + }
395 +
382 396 $mailClass = new MailClass();
383 397 $mail = $mailClass->getOneById($mailId);
384 398
385 - if (empty($mail)) return false;
399 + if (empty($mail)) {
400 + return false;
401 + }
386 402
387 403 $delaySettings = new \stdClass();
388 404 $delaySettings->id = $mail->id;
389 405 $this->getDelaySettingToMail($delaySettings, $id);
@@ -388,12 +404,15 @@
388 404 $delaySettings->id = $mail->id;
389 405 $this->getDelaySettingToMail($delaySettings, $id);
390 406
391 407 unset($mail->id);
408 + unset($mail->creator_id);
392 409 $mail->name .= '_copy';
393 410
394 411 $mail->id = $mailClass->save($mail);
395 - if (empty($mail->id)) return false;
412 + if (empty($mail->id)) {
413 + return false;
414 + }
396 415
397 416 $affectedRow = acym_query(
398 417 'INSERT INTO #__acym_followup_has_mail (`mail_id`, `followup_id`, `delay`, `delay_unit`) VALUE ('.intval($mail->id).', '.$id.', '.intval(
399 418 $delaySettings->delay
@@ -402,19 +421,21 @@
402 421
403 422 return !empty($affectedRow);
404 423 }
405 424
406 - public function deleteMail($mailId)
425 + public function deleteMail(int $mailId): bool
407 426 {
408 - if (empty($mailId)) return false;
427 + if (empty($mailId)) {
428 + return false;
429 + }
430 +
409 431 $mailClass = new MailClass();
410 432
411 - return $mailClass->delete($mailId);
433 + return (bool)$mailClass->delete([$mailId]);
412 434 }
413 435
414 - public function getFollowupsWithMailsInfoByIds($followupIds)
436 + public function getFollowupsWithMailsInfoByIds(array $followupIds): array
415 437 {
416 - if (!is_array($followupIds)) $followupIds = [$followupIds];
417 438 acym_arrayToInteger($followupIds);
418 439
419 440 $mailsInfo = acym_loadObjectList(
420 441 'SELECT followup_mail.*, followup.send_once
@@ -421,9 +442,11 @@
421 442 FROM #__acym_followup_has_mail AS followup_mail
422 443 JOIN #__acym_followup AS followup ON followup.id = followup_mail.followup_id AND followup_mail.followup_id IN ('.implode(',', $followupIds).')'
423 444 );
424 445
425 - if (empty($mailsInfo)) return [];
446 + if (empty($mailsInfo)) {
447 + return [];
448 + }
426 449
427 450 $return = [];
428 451
429 452 foreach ($mailsInfo as $mailInfo) {
@@ -450,8 +473,9 @@
450 473 }
451 474
452 475 $followupListIds = [];
453 476 foreach ($followupLists as $listId => $followupList) {
477 + // The user unsubscribed, don't re-subscribe them
454 478 if (in_array($followupList->status, [0, '0'], true)) {
455 479 continue;
456 480 }
457 481
@@ -464,20 +488,24 @@
464 488 return [];
465 489 }
466 490
467 491 $userClass = new UserClass();
468 - $userClass->subscribe($userId, array_keys($followupListIds), false);
492 + $userClass->subscribe([$userId], array_keys($followupListIds), false);
469 493
470 494 return $followupListIds;
471 495 }
472 496
473 - public function addFollowupEmailsQueue($followupTrigger, $userId, $params = [])
497 + public function addFollowupEmailsQueue(string $followupTrigger, int $userId, array $params = []): bool
474 498 {
475 - if (empty($followupTrigger) || empty($userId)) return false;
499 + if (empty($followupTrigger) || empty($userId)) {
500 + return false;
501 + }
476 502
477 503 $followupToTrigger = acym_loadObjectList('SELECT * FROM #__acym_followup WHERE active = 1 AND `trigger` = '.acym_escapeDB($followupTrigger), 'id');
478 504
479 - if (empty($followupToTrigger)) return false;
505 + if (empty($followupToTrigger)) {
506 + return false;
507 + }
480 508
481 509 foreach ($followupToTrigger as $key => $followup) {
482 510 if (!empty($followup->condition)) {
483 511 $followupToTrigger[$key]->condition = json_decode($followup->condition, true);
@@ -485,17 +513,23 @@
485 513 }
486 514
487 515 acym_trigger('matchFollowupsConditions', [&$followupToTrigger, $userId, $params]);
488 516
489 - if (empty($followupToTrigger)) return false;
517 + if (empty($followupToTrigger)) {
518 + return false;
519 + }
490 520
491 521 $followupIds = $this->subscribeUserToFollowupList(array_keys($followupToTrigger), $userId);
492 522
493 - if (empty($followupIds)) return false;
523 + if (empty($followupIds)) {
524 + return false;
525 + }
494 526
495 527 $followups = $this->getFollowupsWithMailsInfoByIds($followupIds);
496 528
497 - if (empty($followups)) return false;
529 + if (empty($followups)) {
530 + return false;
531 + }
498 532
499 533 $priority = $this->config->get('followup_max_priority', 0) == 1 ? 1 : 2;
500 534
501 535 $valuesToInsert = [];
@@ -519,34 +553,42 @@
519 553
520 554 return !empty($affectedRows);
521 555 }
522 556
523 - private function addMailStat($mailId)
557 + private function addMailStat(int $mailId): void
524 558 {
525 559 $mailStatClass = new MailStatClass();
526 560 $mailStat = $mailStatClass->getOneRowByMailId($mailId);
527 - $newMailStat = [
528 - 'mail_id' => intval($mailId),
529 - 'total_subscribers' => 1,
530 - ];
561 + $newMailStat = new \stdClass();
562 + $newMailStat->mail_id = intval($mailId);
563 + $newMailStat->total_subscribers = 1;
564 +
531 565 if (empty($mailStat)) {
532 - $newMailStat['send_date'] = acym_date('now', 'Y-m-d H:i:s', false);
566 + $newMailStat->send_date = acym_date('now', 'Y-m-d H:i:s', false);
533 567 }
534 568
535 569 $mailStatClass->save($newMailStat);
536 570 }
537 571
538 - public function getFollowupDailyBases()
572 + public function getFollowupDailyBases(): array
539 573 {
540 574 $triggers = [];
541 575 acym_trigger('onAcymGetFollowupDailyBases', [&$triggers]);
542 576
543 - return acym_loadObjectList('SELECT * FROM #__acym_followup WHERE `trigger` IN ("'.implode('","', $triggers).'") AND active = 1');
577 + if (empty($triggers)) {
578 + return [];
579 + }
580 +
581 + $safeTriggers = array_map('acym_escapeDB', $triggers);
582 +
583 + return acym_loadObjectList('SELECT * FROM #__acym_followup WHERE `trigger` IN ('.implode(',', $safeTriggers).') AND active = 1');
544 584 }
545 585
546 - public function queueForSubscribers($emailId)
586 + public function queueForSubscribers(int $emailId): ?int
547 587 {
548 - if (empty($emailId)) return false;
588 + if (empty($emailId)) {
589 + return null;
590 + }
549 591
550 592 $mailInfo = acym_loadObject(
551 593 'SELECT map.*, followup.list_id
552 594 FROM #__acym_followup_has_mail AS map
@@ -553,9 +595,9 @@
553 595 JOIN #__acym_followup AS followup
554 596 ON followup.id = map.followup_id
555 597 WHERE map.mail_id = '.intval($emailId)
556 598 );
557 - if (empty($mailInfo)) return false;
599 + if (empty($mailInfo)) return null;
558 600
559 601 $this->addMailStat($mailInfo->mail_id);
560 602
561 603 $delay = intval($mailInfo->delay) * intval($mailInfo->delay_unit);
@@ -564,9 +606,11 @@
564 606 FROM #__acym_user_has_list
565 607 WHERE status = 1
566 608 AND list_id = '.intval($mailInfo->list_id);
567 609
568 - return acym_query($query);
610 + $addedEmails = acym_query($query);
611 +
612 + return $addedEmails === false || $addedEmails === null ? null : intval($addedEmails);
569 613 }
570 614
571 615 public function getXFollowups(array $options): array
572 616 {
@@ -612,8 +656,13 @@
612 656
613 657 return $followUps;
614 658 }
615 659
660 + /**
661 + * @param string $mailId
662 + *
663 + * @return object|null
664 + */
616 665 public function getOneByMailId(int $mailId): ?object
617 666 {
618 667 return acym_loadObject(
619 668 'SELECT followup.*
@@ -623,8 +672,13 @@
623 672 WHERE mail_id = '.intval($mailId)
624 673 );
625 674 }
626 675
676 + /**
677 + * @param $followupId
678 + *
679 + * @return object
680 + */
627 681 public function getLastEmail(int $followupId): object
628 682 {
629 683 return acym_loadObject(
630 684 'SELECT mail_id as id, delay * delay_unit as totalDelay FROM #__acym_followup_has_mail WHERE followup_id = '.intval($followupId).' ORDER BY totalDelay DESC'
@@ -630,8 +684,16 @@
630 684 'SELECT mail_id as id, delay * delay_unit as totalDelay FROM #__acym_followup_has_mail WHERE followup_id = '.intval($followupId).' ORDER BY totalDelay DESC'
631 685 );
632 686 }
633 687
688 + /**
689 + * @param int $followUpId
690 + * @param int $userId
691 + * @param int $additionalDelay
692 + * @param array $mailIdToSkip
693 + *
694 + * @return void
695 + */
634 696 public function triggerFollowUp(int $followUpId, int $userId, int $additionalDelay = 0, array $mailIdToSkip = []): void
635 697 {
636 698 $followUp = $this->getOneById($followUpId);
637 699
@@ -642,9 +704,9 @@
642 704 $values = intval($userId).', '.intval($followUp->list_id).', 1, '.acym_escapeDB(acym_date(time(), 'Y-m-d H:i:s'));
643 705
644 706 acym_query('INSERT IGNORE INTO #__acym_user_has_list (`user_id`, `list_id`, `status`, `subscription_date`) VALUES ('.$values.') ON DUPLICATE KEY UPDATE status = 1');
645 707
646 - $followups = $this->getFollowupsWithMailsInfoByIds($followUpId);
708 + $followups = $this->getFollowupsWithMailsInfoByIds([$followUpId]);
647 709 $allValues = [];
648 710 foreach ($followups as $mails) {
649 711 foreach ($mails as $mail) {
650 712 if (in_array($mail->mail_id, $mailIdToSkip)) {
@@ -653,8 +715,12 @@
653 715 $sendDate = time() + (intval($mail->delay) * intval($mail->delay_unit)) + $additionalDelay;
654 716 $sendDate = acym_escapeDB(acym_date($sendDate, 'Y-m-d H:i:s', false));
655 717 $allValues[] = '('.intval($mail->mail_id).', '.intval($userId).', '.$sendDate.', '.$this->config->get('priority_newsletter', 3).', 0'.')';
656 718 }
719 + }
720 +
721 + if (empty($allValues)) {
722 + return;
657 723 }
658 724
659 725 $queryToProcess = 'INSERT IGNORE INTO #__acym_queue (`mail_id`, `user_id`, `sending_date`, `priority`, `try`) VALUES '.implode(', ', $allValues);
660 726