PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 10.11.1
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v10.11.1
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 / Helpers / CronHelper.php

CronHelper.php in AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress 10.11.1, at back/Helpers/CronHelper.php

742 lines 25.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace AcyMailing\Helpers;
4
5 use AcyMailing\Classes\AutomationClass;
6 use AcyMailing\Classes\CampaignClass;
7 use AcyMailing\Classes\FollowupClass;
8 use AcyMailing\Classes\MailArchiveClass;
9 use AcyMailing\Classes\MailboxClass;
10 use AcyMailing\Classes\MailClass;
11 use AcyMailing\Classes\QueueClass;
12 use AcyMailing\Classes\UserClass;
13 use AcyMailing\Classes\UserStatClass;
14 use AcyMailing\Core\AcymObject;
15
16 class CronHelper extends AcymObject
17 {
18 const STEP_SCHEDULE = 'schedule';
19 const STEP_CLEAN_QUEUE = 'cleanqueue';
20 const STEP_SEND = 'send';
21 const STEP_BOUNCE = 'bounce';
22 const STEP_AUTOMATION = 'automation';
23 const STEP_CAMPAIGN = 'campaign';
24 const STEP_SPECIFIC = 'specific';
25 const STEP_FOLLOWUP = 'followup';
26 const STEP_DELETE_HISTORY = 'delete_history';
27 const STEP_CLEAN_DATA_EXTERNAL_SENDING_METHOD = 'clean_data_external_sending_method';
28 const STEP_CLEAN_EXPORT_CHANGES = 'clean_export_changes';
29 const STEP_MAILBOX_ACTION = 'mailbox_action';
30 const STEP_ABTEST = 'abtest';
31 const STEP_SCENARIO = 'scenario';
32
33 const ALL_STEPS = [
34 self::STEP_SCHEDULE,
35 self::STEP_CLEAN_QUEUE,
36 self::STEP_SEND,
37 self::STEP_BOUNCE,
38 self::STEP_AUTOMATION,
39 self::STEP_CAMPAIGN,
40 self::STEP_SPECIFIC,
41 self::STEP_FOLLOWUP,
42 self::STEP_DELETE_HISTORY,
43 self::STEP_CLEAN_DATA_EXTERNAL_SENDING_METHOD,
44 self::STEP_CLEAN_EXPORT_CHANGES,
45 self::STEP_MAILBOX_ACTION,
46 self::STEP_ABTEST,
47 self::STEP_SCENARIO,
48 ];
49
50 const SEND_REPORT_NO = 0;
51 const SEND_REPORT_EACH_TIME = 1;
52 const SEND_REPORT_ONLY_ON_ACTION = 2;
53 const SEND_REPORT_ONLY_ON_ERROR = 3;
54
55 private array $messages = [];
56 private array $detailMessages = [];
57 private array $emailTypes = [];
58 private array $skip = [];
59
60 private int $cronTimeLimit = 0;
61 private bool $cronTimeLimitReached = false;
62 private int $startQueue;
63
64 private string $mainMessage = '';
65
66 private bool $processed = false;
67
68 private bool $errorDetected = false;
69
70 private bool $externalSendingActivated = false;
71 private bool $externalSendingRepeat;
72 private bool $externalSendingNotFinished = false;
73 private bool $isSendingCall = false;
74
75 public function __construct()
76 {
77 parent::__construct();
78
79 acym_trigger('onAcymProcessQueueExternalSendingCampaign', [&$this->externalSendingActivated]);
80
81 $callType = acym_getVar('string', 'type', '');
82 $this->startQueue = acym_getVar('int', 'startqueue', 0);
83 $this->externalSendingRepeat = !empty(acym_getVar('int', 'external_sending_repeat', 0));
84
85 if ($callType === 'sending' || !empty($this->startQueue) || !empty($this->externalSendingRepeat)) {
86 $this->skip = array_diff(self::ALL_STEPS, [self::STEP_SEND]);
87 $this->isSendingCall = true;
88 }
89 }
90
91 public function addSkipFromString(string $skipVar): void
92 {
93 if (empty($skipVar)) {
94 return;
95 }
96
97 $skipVar = explode(',', $skipVar);
98
99 if (empty($skipVar)) {
100 return;
101 }
102
103 $this->skip = array_unique(array_merge($this->skip, $skipVar));
104 }
105
106 public function cron(): void
107 {
108
109 $this->handleUnlinkLicenseCalls();
110 $this->triggeredMessage();
111 if (!$this->checkCronFrequency()) {
112 return;
113 }
114
115 $this->queueScheduledCampaigns();
116 $this->cleanQueue();
117 $this->handleQueue();
118 $this->handleBounceMessages();
119 $this->handleAutomations();
120 $this->handleAutomaticCampaigns();
121 $this->handleSpecificEmails();
122 $this->handleFollowups();
123 $this->handleMailboxActions();
124 $this->cleanData();
125 $this->handleABTestCampaigns();
126 $this->handleScenario();
127 $this->continueCronCall();
128 $this->handleCronReport();
129 }
130
131 public function saveReport(array $messages = [], array $detailMessages = []): void
132 {
133 $saveReport = $this->config->get('cron_savereport');
134 $reportPath = $this->config->get('cron_savepath');
135
136 if (empty($saveReport) || empty($reportPath)) {
137 return;
138 }
139
140 if (!(($saveReport == 2 && $this->processed) || $saveReport == 1 || ($saveReport == 3 && $this->errorDetected))) {
141 return;
142 }
143
144 if (!empty($messages)) {
145 $this->messages = $messages;
146 }
147
148 if (!empty($detailMessages)) {
149 $this->detailMessages = $detailMessages;
150 }
151
152 $reportPath = str_replace(['{year}', '{month}'], [date('Y'), date('m')], $reportPath);
153 $reportPath = acym_cleanPath(ACYM_ROOT.trim(html_entity_decode($reportPath)));
154 acym_createDir(dirname($reportPath), true, true);
155
156 $lr = "\r\n";
157 ob_start();
158 file_put_contents(
159 $reportPath,
160 $lr.$lr.'******************** '.acym_getDate(time()).' UTC ********************'.$lr.implode($lr, $this->messages),
161 FILE_APPEND
162 );
163
164 if ($saveReport == 2 && !empty($this->detailMessages)) {
165 file_put_contents(
166 $reportPath,
167 $lr.'---- Details ----'.$lr.implode($lr, $this->detailMessages),
168 FILE_APPEND
169 );
170 }
171 $potentialWarnings = ob_get_clean();
172
173 if (!empty($potentialWarnings)) {
174 $this->messages[] = $potentialWarnings;
175 }
176 }
177
178 public function setEmailTypes(array $emailTypes): void
179 {
180 $this->emailTypes = $emailTypes;
181 }
182
183 public function addMessage(string $message): void
184 {
185 $this->messages[] = $message;
186 }
187
188 public function handleCronReport(): void
189 {
190 $sendReport = (int)$this->config->get('cron_sendreport');
191
192 if (
193 ($sendReport === self::SEND_REPORT_ONLY_ON_ACTION && $this->processed)
194 || $sendReport === self::SEND_REPORT_EACH_TIME
195 || ($sendReport === self::SEND_REPORT_ONLY_ON_ERROR && $this->errorDetected)
196 ) {
197 $mailerHelper = new MailerHelper();
198 $mailerHelper->report = false;
199 $mailerHelper->autoAddUser = true;
200 $mailerHelper->addParam('report', implode('<br />', $this->messages));
201 $mailerHelper->addParam('mainreport', $this->mainMessage);
202 $mailerHelper->addParam('detailreport', implode('<br />', $this->detailMessages));
203
204 $receiverString = $this->config->get('cron_sendto');
205 $receivers = [];
206 if (substr_count($receiverString, '@') > 1) {
207 $receivers = explode(' ', trim(preg_replace('# +#', ' ', str_replace([';', ','], ' ', $receiverString))));
208 } else {
209 $receivers[] = trim($receiverString);
210 }
211
212 if (!empty($receivers)) {
213 $mailClass = new MailClass();
214 foreach ($receivers as $oneReceiver) {
215 if (empty($oneReceiver)) {
216 continue;
217 }
218
219 try {
220 $reportEmail = $mailClass->getOneByName('acy_report');
221 if (!empty($reportEmail)) {
222 $mailerHelper->sendOne($reportEmail->id, $oneReceiver);
223 }
224 } catch (\Exception $e) {
225 acym_logError('Error while sending the cron report to '.$oneReceiver.' : '.$e->getMessage());
226 }
227 }
228 }
229 }
230
231 $this->saveReport();
232
233 $newConfig = [
234 'cron_report' => implode("\n", $this->messages),
235 ];
236
237 if (strlen($newConfig['cron_report']) > 800) {
238 $newConfig['cron_report'] = substr($newConfig['cron_report'], 0, 795).'...';
239 }
240
241 $this->config->saveConfig($newConfig);
242 }
243
244 private function handleUnlinkLicenseCalls(): void
245 {
246 if (acym_getVar('int', 'unlink', 0) !== 1) {
247 return;
248 }
249
250 $callLicenseKey = acym_getVar('string', 'licenseKey');
251 $configLicenseKey = $this->config->get('license_key');
252
253 if (!empty($configLicenseKey) && $configLicenseKey === $callLicenseKey) {
254 $this->config->saveConfig(['license_key' => '', 'active_cron' => 0]);
255 }
256
257 exit;
258 }
259
260 private function triggeredMessage(): void
261 {
262 $firstMessage = acym_translationSprintf('ACYM_CRON_TRIGGERED', acym_date('now', 'd F Y H:i'));
263 $this->messages[] = $firstMessage;
264 acym_display($firstMessage, 'info');
265 }
266
267 private function checkCronFrequency(): bool
268 {
269 if ($this->isSendingCall) {
270 return true;
271 }
272
273 $time = time();
274 $nextCronTime = $this->config->get('cron_next', 0);
275 $cronFrequency = $this->config->get('cron_frequency', 900);
276
277 if ($nextCronTime > $time) {
278 if ($nextCronTime > ($time + $cronFrequency)) {
279 $this->config->saveConfig(['cron_next' => $time + $cronFrequency]);
280 }
281
282 $notTimeMessage = acym_translationSprintf('ACYM_CRON_NEXT', acym_date($this->config->get('cron_next'), 'd F Y H:i'));
283 $this->messages[] = $notTimeMessage;
284 acym_display($notTimeMessage, 'info');
285
286 return false;
287 }
288
289 $newConfig = [
290 'cron_last' => $time,
291 'cron_fromip' => acym_getIP(true),
292 'cron_next' => $nextCronTime + $cronFrequency,
293 ];
294
295 if ($newConfig['cron_next'] <= $time || $newConfig['cron_next'] > $time + $cronFrequency) {
296 $newConfig['cron_next'] = $time + $cronFrequency;
297 }
298
299 $this->config->saveConfig($newConfig);
300
301 return true;
302 }
303
304 private function queueScheduledCampaigns(): void
305 {
306 if (in_array(self::STEP_SCHEDULE, $this->skip)) {
307 return;
308 }
309
310 $queueClass = new QueueClass();
311 $nbScheduled = $queueClass->scheduleReady();
312 if (!empty($nbScheduled)) {
313 $this->messages[] = acym_translationSprintf('ACYM_NB_SCHEDULED', $nbScheduled);
314 $this->detailMessages = array_merge($this->detailMessages, $queueClass->messages);
315 $this->processed = true;
316 }
317 }
318
319 private function cleanQueue(): void
320 {
321 if (in_array(self::STEP_CLEAN_QUEUE, $this->skip)) {
322 return;
323 }
324
325 $queueClass = new QueueClass();
326 $deletedNb = $queueClass->cleanQueue();
327
328 if (!empty($deletedNb)) {
329 $this->messages[] = acym_translationSprintf('ACYM_EMAILS_REMOVED_QUEUE_CLEAN', $deletedNb);
330 $this->processed = true;
331 }
332 }
333
334 private function handleQueue(): void
335 {
336 if (in_array(self::STEP_SEND, $this->skip) || !$this->canSendQueuedEmails()) {
337 return;
338 }
339
340 if (!$this->isSendingCall && acym_level(ACYM_ENTERPRISE) && function_exists('curl_multi_exec')) {
341 $this->handleMultiCron();
342 }
343
344 if ($this->isSendingCall || $this->config->get('dedicated_send_process', 0) != 1) {
345 $this->sendQueuedEmails();
346 }
347 }
348
349 private function checkTimeRemaining(): void
350 {
351 $time = time();
352 if (empty($this->cronTimeLimit) || $time < $this->cronTimeLimit) {
353 return;
354 }
355
356 $this->messages[] = acym_translation('ACYM_CRON_TIME_LIMIT_REACHED');
357
358 $this->cronTimeLimitReached = true;
359 }
360
361 private function handleMultiCron(): void
362 {
363 $emailsPerBatches = $this->config->get('queue_nbmail_auto', 70);
364 if (empty($emailsPerBatches)) {
365 return;
366 }
367
368 $nbBatches = $this->config->get('queue_batch_auto', 1);
369 $nbBatches = intval($nbBatches);
370
371 if ($this->config->get('dedicated_send_process', 0) == 1) {
372 $startCron = 0;
373 } else {
374 if ($nbBatches < 2) {
375 return;
376 }
377
378 $startCron = 1;
379 }
380
381 $cronParams = '&t='.time();
382 if (!empty($this->config->get('cron_security', 0)) && !empty($this->config->get('cron_key'))) {
383 $cronParams .= '&cronKey='.$this->config->get('cron_key');
384 }
385
386 $urls = [];
387 for ($i = $startCron; $i < $nbBatches; $i++) {
388 $urls[] = acym_frontendLink('cron&task=cron&type=sending&startqueue='.($emailsPerBatches * $i).$cronParams);
389 }
390
391 acym_asyncUrlCalls($urls);
392 }
393
394 private function handleBounceMessages(): void
395 {
396 $this->checkTimeRemaining();
397 $time = time();
398 $autoBounceHandlingActive = (int)$this->config->get('auto_bounce', 0) === 1;
399 $autoBounceHandlingNextTime = (int)$this->config->get('auto_bounce_next', 0);
400 $autoBounceHandlingFrequency = (int)$this->config->get('auto_bounce_frequency', 0);
401 $isEnterprise = acym_level(ACYM_ENTERPRISE);
402
403 if (in_array(self::STEP_BOUNCE, $this->skip) || $this->cronTimeLimitReached || !$isEnterprise || !$autoBounceHandlingActive || $time < $autoBounceHandlingNextTime) {
404 return;
405 }
406
407 $this->config->saveConfig(
408 [
409 'auto_bounce_last' => $time,
410 'auto_bounce_next' => $time + $autoBounceHandlingFrequency,
411 ]
412 );
413
414 $bounceHelper = new BounceHelper();
415 $bounceHelper->report = false;
416 $bounceHelper->stoptime = $this->cronTimeLimit;
417
418 $newConfig = [];
419 if ($bounceHelper->init() && $bounceHelper->connect()) {
420 $nbMessages = $bounceHelper->getNBMessages();
421 $nbMessagesReport = acym_translationSprintf('ACYM_NB_MAIL_MAILBOX', $nbMessages);
422 $this->messages[] = $nbMessagesReport;
423 $newConfig['auto_bounce_report'] = $nbMessagesReport;
424 $this->detailMessages[] = $nbMessagesReport;
425 if (!empty($nbMessages)) {
426 $bounceHelper->handleMessages();
427 $this->processed = true;
428 }
429 $this->detailMessages = array_merge($this->detailMessages, $bounceHelper->messages);
430 } else {
431 $bounceErrors = $bounceHelper->getErrors();
432 $newConfig['auto_bounce_report'] = implode('<br />', $bounceErrors);
433 if (!empty($bounceErrors[0])) {
434 $bounceErrors[0] = acym_translation('ACYM_BOUNCE_HANDLING').' : '.$bounceErrors[0];
435 }
436 $this->messages = array_merge($this->messages, $bounceErrors);
437 $this->processed = true;
438 $this->errorDetected = true;
439 }
440
441 $this->config->saveConfig($newConfig);
442 }
443
444 private function handleAutomations(): void
445 {
446 $this->checkTimeRemaining();
447 if (in_array(self::STEP_AUTOMATION, $this->skip) || $this->cronTimeLimitReached || !acym_level(ACYM_ENTERPRISE)) {
448 return;
449 }
450
451 $automationClass = new AutomationClass();
452 $automationClass->trigger('classic');
453
454 $userStatusCheckTriggers = [];
455 acym_trigger('onAcymDefineUserStatusCheckTriggers', [&$userStatusCheckTriggers]);
456 $automationClass->trigger($userStatusCheckTriggers);
457
458 if (!empty($automationClass->report)) {
459 if ($automationClass->didAnAction) {
460 $this->processed = true;
461 }
462 $this->messages = array_merge($this->messages, $automationClass->report);
463 }
464 }
465
466 private function handleAutomaticCampaigns(): void
467 {
468 $this->checkTimeRemaining();
469 if (in_array(self::STEP_CAMPAIGN, $this->skip) || $this->cronTimeLimitReached || !acym_level(ACYM_ENTERPRISE)) {
470 return;
471 }
472
473 $campaignClass = new CampaignClass();
474 $campaignClass->triggerAutoCampaign();
475
476 if (!empty($campaignClass->messages)) {
477 $this->messages = array_merge($this->messages, $campaignClass->messages);
478 $this->processed = true;
479 }
480 }
481
482 private function handleSpecificEmails(): void
483 {
484 $this->checkTimeRemaining();
485 if (in_array(self::STEP_SPECIFIC, $this->skip) || $this->cronTimeLimitReached) {
486 return;
487 }
488
489 $campaignClass = new CampaignClass();
490 $specialTypes = [];
491
492 acym_trigger('getCampaignTypes', [&$specialTypes]);
493
494 $specialMail = $campaignClass->getCampaignsByTypes($specialTypes, true);
495 $time = time();
496
497 acym_trigger('filterSpecificMailsToSend', [&$specialMail, $time]);
498
499 foreach ($specialMail as $onespecialMail) {
500 $campaignClass->send($onespecialMail->id);
501 }
502 }
503
504 private function handleFollowups(): void
505 {
506 $this->checkTimeRemaining();
507 if (in_array(self::STEP_FOLLOWUP, $this->skip) || $this->cronTimeLimitReached) {
508 return;
509 }
510
511 $followupClass = new FollowupClass();
512 $followups = $followupClass->getFollowupDailyBases();
513
514 $dailyHour = $this->config->get('daily_hour', '12');
515 $dailyMinute = $this->config->get('daily_minute', '00');
516 $dayBasedOnCMSTimezone = acym_date('now', 'Y-m-d');
517 $dayBasedOnCMSTimezoneAtSpecifiedHour = acym_getTimeFromCMSDate($dayBasedOnCMSTimezone.' '.$dailyHour.':'.$dailyMinute);
518 $time = time();
519
520 foreach ($followups as $followup) {
521 $lastTrigger = empty($followup->last_trigger) ? '' : acym_date($followup->last_trigger, 'Y-m-d');
522 if ($time >= $dayBasedOnCMSTimezoneAtSpecifiedHour && $lastTrigger != $dayBasedOnCMSTimezone) {
523 if (!empty($followup->condition)) {
524 $followup->condition = json_decode($followup->condition, true);
525 }
526
527 acym_trigger('onAcymFollowupDailyBasesNeedToBeTriggered', [$followup]);
528 }
529 }
530 }
531
532 private function handleMailboxActions(): void
533 {
534 $this->checkTimeRemaining();
535 if (in_array(self::STEP_MAILBOX_ACTION, $this->skip) || $this->cronTimeLimitReached || !acym_level(ACYM_ENTERPRISE)) {
536 return;
537 }
538
539 $mailboxActionClass = new MailboxClass();
540 $mailboxes = $mailboxActionClass->getAllActiveReadyWithActions();
541
542 if (empty($mailboxes)) {
543 return;
544 }
545
546 $mailboxHelper = new MailboxHelper();
547 $mailboxHelper->report = false;
548 foreach ($mailboxes as $oneMailboxAction) {
549 $this->processed = true;
550
551 if (!$mailboxHelper->isConnectionValid($oneMailboxAction, false)) {
552 $this->messages[] = acym_translationSprintf('ACYM_CONNECTION_FAILED_MAILBOX_X', $oneMailboxAction->id.'-'.$oneMailboxAction->name);
553 $this->errorDetected = true;
554 continue;
555 }
556
557 $nbMessages = $mailboxHelper->getNBMessages();
558 if (!$nbMessages) {
559 $this->messages[] = acym_translationSprintf('ACYM_NO_MESSAGE_IN_MAILBOX_X', $oneMailboxAction->id.'-'.$oneMailboxAction->name);
560 $mailboxHelper->close();
561 continue;
562 }
563
564 $mailboxHelper->handleAction();
565 $mailboxHelper->close();
566
567
568 $oneMailboxAction->nextdate = time() + $oneMailboxAction->frequency;
569 unset($oneMailboxAction->conditions);
570 unset($oneMailboxAction->actions);
571 $mailboxActionClass->save($oneMailboxAction);
572 }
573 }
574
575 private function cleanData(): void
576 {
577 if (!in_array(self::STEP_DELETE_HISTORY, $this->skip) && $this->isDailyCron()) {
578 $userStatClass = new UserStatClass();
579 $userDetailedStatsDeleted = $userStatClass->deleteDetailedStatsPeriod();
580 if (!empty($userDetailedStatsDeleted['message'])) {
581 $this->messages[] = $userDetailedStatsDeleted['message'];
582 $this->processed = true;
583 }
584
585 $userClass = new UserClass();
586 $userHistoryDeleted = $userClass->deleteHistoryPeriod();
587 if (!empty($userHistoryDeleted['message'])) {
588 $this->messages[] = $userHistoryDeleted['message'];
589 $this->processed = true;
590 }
591
592 $mailArchiveClass = new MailArchiveClass();
593 $archiveDeleted = $mailArchiveClass->deleteArchivePeriod();
594 if (!empty($archiveDeleted['message'])) {
595 $this->messages[] = $archiveDeleted['message'];
596 $this->processed = true;
597 }
598 }
599
600 if (!in_array(self::STEP_CLEAN_DATA_EXTERNAL_SENDING_METHOD, $this->skip) && $this->isDailyCron()) {
601 acym_trigger('onAcymCleanDataExternalSendingMethod');
602 }
603
604 if (!in_array(self::STEP_CLEAN_EXPORT_CHANGES, $this->skip) && $this->isDailyCron()) {
605 $exportHelper = new ExportHelper();
606 $exportHelper->cleanExportChangesFile();
607 }
608
609 if ($this->isDailyCron()) {
610 $time = time();
611 $this->config->saveConfig(['cron_last_daily' => $time]);
612 }
613 }
614
615 private function isDailyCron(): bool
616 {
617 $dailyHour = $this->config->get('daily_hour', '12');
618 $dailyMinute = $this->config->get('daily_minute', '00');
619 $dayBasedOnCMSTimezone = acym_date('now', 'Y-m-d');
620 $dayBasedOnCMSTimezoneAtSpecifiedHour = acym_getTimeFromCMSDate($dayBasedOnCMSTimezone.' '.$dailyHour.':'.$dailyMinute);
621
622 $time = time();
623
624 $lastCronDayBasedOnCMSTimezone = acym_date($this->config->get('cron_last_daily', $time - 86400), 'Y-m-d');
625
626 return $time >= $dayBasedOnCMSTimezoneAtSpecifiedHour && $lastCronDayBasedOnCMSTimezone != $dayBasedOnCMSTimezone;
627 }
628
629 private function handleABTestCampaigns(): void
630 {
631 $this->checkTimeRemaining();
632 if (in_array(self::STEP_ABTEST, $this->skip) || $this->cronTimeLimitReached) {
633 return;
634 }
635
636 $campaignClass = new CampaignClass();
637 $abTestCampaigns = $campaignClass->getAllAbTestCampaignsToFinishSending();
638 foreach ($abTestCampaigns as $campaign) {
639 if ($campaignClass->finishAbTestCampaign($campaign)) {
640 $this->messages[] = acym_translationSprintf('ACYM_ABTEST_CAMPAIGN_X_FINAL_VERSION_SENT', $campaign->id);
641 $this->processed = true;
642 }
643 }
644 }
645
646 private function handleScenario(): void
647 {
648 $this->checkTimeRemaining();
649 if (in_array(self::STEP_SCENARIO, $this->skip) || $this->cronTimeLimitReached) {
650 return;
651 }
652
653 $scenarioHelper = new ScenarioHelper();
654 $scenarioHelper->executeAvailableSteps();
655 $scenarioHelper->triggerTimeScenarios();
656 }
657
658 private function continueCronCall(): void
659 {
660 if ($this->externalSendingNotFinished) {
661 $cronKey = '';
662 if (!empty($this->config->get('cron_security', 0)) && !empty($this->config->get('cron_key'))) {
663 $cronKey = '&cronKey='.$this->config->get('cron_key');
664 }
665 acym_makeCurlCall(acym_frontendLink('cron&task=cron&external_sending_repeat=1&t='.time().$cronKey), ['verifySsl' => false]);
666 }
667 }
668
669 private function canSendQueuedEmails(): bool
670 {
671 if ($this->config->get('queue_type') === 'manual') {
672 return false;
673 }
674
675 $dayOfWeek = acym_date('now', 'N');
676 if ($this->config->get('queue_stop_weekend', 0) && $dayOfWeek >= 6) {
677 return false;
678 }
679
680 $fromHour = $this->config->get('queue_send_from_hour', '00');
681 $fromMinute = $this->config->get('queue_send_from_minute', '00');
682 $toHour = $this->config->get('queue_send_to_hour', '23');
683 $toMinute = $this->config->get('queue_send_to_minute', '59');
684 $time = time();
685
686 if ($fromHour != '00' || $fromMinute != '00' || $toHour != '23' || $toMinute != '59') {
687 $dayBasedOnCMSTimezone = acym_date('now', 'Y-m-d');
688 $fromBasedOnCMSTimezoneAtSpecifiedHour = acym_getTimeFromCMSDate($dayBasedOnCMSTimezone.' '.$fromHour.':'.$fromMinute);
689 $toBasedOnCMSTimezoneAtSpecifiedHour = acym_getTimeFromCMSDate($dayBasedOnCMSTimezone.' '.$toHour.':'.$toMinute);
690 if ($fromBasedOnCMSTimezoneAtSpecifiedHour > $toBasedOnCMSTimezoneAtSpecifiedHour) {
691 if ($time > $fromBasedOnCMSTimezoneAtSpecifiedHour) {
692 $toBasedOnCMSTimezoneAtSpecifiedHour = acym_getTimeFromCMSDate(acym_date('tomorrow', 'Y-m-d').' '.$toHour.':'.$toMinute);
693 } elseif ($time < $toBasedOnCMSTimezoneAtSpecifiedHour) {
694 $fromBasedOnCMSTimezoneAtSpecifiedHour = acym_getTimeFromCMSDate(acym_date('yesterday', 'Y-m-d').' '.$fromHour.':'.$fromMinute);
695 }
696 }
697
698 if ($time < $fromBasedOnCMSTimezoneAtSpecifiedHour || $time > $toBasedOnCMSTimezoneAtSpecifiedHour) {
699 return false;
700 }
701 }
702
703 return true;
704 }
705
706 private function sendQueuedEmails(): void
707 {
708 $queueHelper = new QueueHelper();
709 $queueHelper->send_limit = (int)$this->config->get('queue_nbmail_auto');
710 $queueHelper->report = false;
711 $queueHelper->emailTypes = $this->emailTypes;
712 $queueHelper->startSendingFrom = $this->startQueue;
713 $queueHelper->process();
714
715 if (!empty($queueHelper->messages)) {
716 $this->detailMessages = array_merge($this->detailMessages, $queueHelper->messages);
717 }
718
719 if (!empty($queueHelper->nbprocess)) {
720 $this->processed = true;
721
722 if (!$queueHelper->finish && $this->externalSendingActivated) {
723 $this->externalSendingNotFinished = true;
724 }
725 }
726
727 $this->mainMessage = acym_translationSprintf(
728 'ACYM_CRON_PROCESS',
729 $queueHelper->nbprocess,
730 $queueHelper->successSend,
731 $queueHelper->errorSend
732 );
733 $this->messages[] = $this->mainMessage;
734
735 if (!empty($queueHelper->errorSend)) {
736 $this->errorDetected = true;
737 }
738
739 $this->cronTimeLimit = $queueHelper->stoptime;
740 }
741 }
742