604800, 'month' => 2419200, ]; const LIMIT_EMAIL_BATCH = 5000; private $acymailingUserClass; private $cmsUserClass; private $apiKey; private $cmsOffset; private $acymailingOffset; private $numberOfEmailsSent; private $remainingCreditsBatch; private $blockedForNoCredits; public function __construct() { parent::__construct(); $this->apiKey = $this->config->get('license_key'); $this->acymailingUserClass = new AcymailingUserClass(); $this->cmsUserClass = new CmsUserClass(); $this->cmsOffset = 0; $this->acymailingOffset = 0; $this->numberOfEmailsSent = 0; $this->remainingCreditsBatch = intval($this->config->get('remaining_credits_batch', 0)); $this->blockedForNoCredits = false; } public function process() { // If we are on the callback url we dont trigger the cron $controller = Security::getVar('string', 'ctrl', ''); if ($controller == 'callbackController') return; // If the user didn't set any conditions we do not trigger any batch $conditions = $this->config->get('conditions_selected', ''); if (empty($conditions)) return; // If no api key set we don't trigger the cron if (empty($this->apiKey)) return; // If the execution timing is set to now we don't trigger the cron $executionTime = $this->config->get('execution_selected', 'now'); if ($executionTime == 'now' || empty(self::INTERVAL_CRON[$executionTime])) return; $lastCronTrigger = $this->config->get('last_cron_trigger', ''); $time = time(); // We check if we have to trigger the cron if (!empty($lastCronTrigger) && $lastCronTrigger > $time - self::INTERVAL_CRON[$executionTime]) return; $this->config->save(['last_cron_trigger' => $time]); $this->processBatches(); } public function processBatches() { $this->config->load(); // We get the config for which users to test (cms/acymailing) $tablesSelected = $this->config->get('tables_selected', []); if (empty($tablesSelected)) return; $tablesSelected = explode(',', $tablesSelected); // for the CMS users if (in_array('cms', $tablesSelected)) { do { $batchCms = $this->batchCmsUsers(true); } while ($batchCms); } // for AcyMailing users if (in_array('acymailing', $tablesSelected)) { do { $batchAcymailing = $this->batchAcymailingUsers(true); } while ($batchAcymailing); } $apiService = new ApiService(); $apiService->refreshCreditsUsed(); if (empty($this->numberOfEmailsSent)) { if ($this->blockedForNoCredits) { Message::enqueueMessage(__('Not enough credits to run this test', 'acychecker'), 'warning'); } else { Message::enqueueMessage(__('There isn\'t any email address to test', 'acychecker'), 'info'); } } else { $message = sprintf(__('%s email addresses have been sent to be tested, you can check the results here:', 'acychecker'), $this->numberOfEmailsSent); $message .= ' '.__('Results', 'acychecker').''; Message::enqueueMessage($message, 'info'); } } private function batchAcymailingUsers($onlyNew) { //We get the lists filter $listsFilter = $this->config->get('table_filter_acymailing', []); if (!empty($listsFilter)) $listsFilter = explode(',', $listsFilter); // Get users for a batch if ($onlyNew) { $emails = $this->acymailingUserClass->getUsersEmail(0, self::LIMIT_EMAIL_BATCH, true, $onlyNew, $listsFilter); } else { $emails = $this->acymailingUserClass->getUsersEmail($this->acymailingOffset, self::LIMIT_EMAIL_BATCH, true, $onlyNew, $listsFilter); $this->acymailingOffset += count($emails); } // If no user we don't do anything if (empty($emails)) return false; if ($this->remainingCreditsBatch === 0) { $this->blockedForNoCredits = true; return false; } return $this->newBatch($emails); } private function batchCmsUsers($onlyNew) { //We get the lists filter $groupsFilter = $this->config->get('table_filter_cms', []); if (!empty($groupsFilter)) $groupsFilter = explode(',', $groupsFilter); // Get users for a batch if ($onlyNew) { $emails = $this->cmsUserClass->getUsersEmail(0, self::LIMIT_EMAIL_BATCH, true, $onlyNew, $groupsFilter); } else { $emails = $this->cmsUserClass->getUsersEmail($this->cmsOffset, self::LIMIT_EMAIL_BATCH, true, $onlyNew, $groupsFilter); $this->cmsOffset += count($emails); } // If no user we don't do anything if (empty($emails)) return false; if ($this->remainingCreditsBatch === 0) { $this->blockedForNoCredits = true; return false; } return $this->newBatch($emails); } private function newBatch($emails) { // Prepare the query to insert the test $insertQuery = 'INSERT IGNORE INTO #__acyc_test (`email`, `date`, `status`) VALUES '; $allTests = []; // Prepare the date to set on each test $dateTimeNow = new \DateTime('NOW'); $dateTimeNow->setTimezone(new \DateTimeZone('UTC')); $dateNow = $dateTimeNow->format('Y-m-d H:i:s'); if (!empty($this->remainingCreditsBatch) && $this->remainingCreditsBatch < count($emails)) { Message::enqueueMessage(sprintf(__('There weren\'t enough credits to test all email addresses, the first %s have been taken.', 'acychecker'), $this->remainingCreditsBatch, Url::completeLink('tests')), 'warning'); $emails = array_slice($emails, 0, $this->remainingCreditsBatch); $this->remainingCreditsBatch = 0; } // We fill the all the test values foreach ($emails as $email) { $oneTest = [ Database::escapeDB($email), Database::escapeDB($dateNow), 0, ]; $allTests[] = implode(',', $oneTest); } $insertQuery .= '('.implode('),(', $allTests).')'; // We call the api $apiService = new ApiService(); $result = $apiService->dispatchBatch($emails); if (!$result['success']) { DebugService::logMessage('cron_service.log', 'Error while creating batch - '.$result['message']); Message::enqueueMessage($result['message'], 'warning'); return false; } $this->numberOfEmailsSent += count($emails); // We execute the query to store the email tested Database::query($insertQuery); // We store the new batch batch ID in the configuration $urlsBatch = $this->config->get('urls_results_batch', []); if (!empty($urlsBatch)) $urlsBatch = json_decode($urlsBatch, true); $urlsBatch[$result['data']['test_id']] = $result['data']['url_result']; $this->config->save(['urls_results_batch' => json_encode($urlsBatch)]); return true; } }