public function send($data) { global $cot_import_filters; if (empty($data['fromName'])) { $data['fromName'] = cot::$cfg['maintitle']; } if (empty($data['fromEmail'])) { $data['fromEmail'] = cot::$cfg['adminemail']; } $queue = new subscribe_model_Queue(); // Отключим html-фильтры $tmp = $cot_import_filters['HTM'] = array(); $queue->from_email = $data['fromEmail']; $queue->from_name = $data['fromName']; $queue->to_email = $data['toEmail']; $queue->to_name = $data['toName']; $queue->subject = $data['subject']; $queue->body = $data['body']; $queue->subscribe = intval($data['subscribe']); $queue->subscriber = intval($data['subscriber']); $queue->save(); unset($queue); $cot_import_filters['HTM'] = $tmp; return true; }
public function deleteAction() { $id = cot_import('id', 'G', 'INT'); $d = cot_import('d', 'G', 'INT'); $backUrlParams = array('m' => 'subscribe', 'n' => 'queue'); if (!empty($d)) { $backUrlParams['d'] = $d; } // Фильтры из списка $f = cot_import('f', 'G', 'ARR'); if (!empty($f)) { foreach ($f as $key => $val) { if ($key == 'id') { continue; } $backUrlParams["f[{$key}]"] = $val; } } if (!$id) { cot_error(cot::$L['nf']); cot_redirect(cot_url('admin', $backUrlParams)); } $item = subscribe_model_Queue::getById($id); if (!$item) { cot_error(cot::$L['nf']); cot_redirect(cot_url('admin', $backUrlParams)); } $item->delete(); cot_message(cot::$L['Deleted']); cot_redirect(cot_url('admin', $backUrlParams, '', true)); }
/** * @var Som_Model_Mapper_Abstract */ protected static $_db = null; protected static $_tbname = ''; protected static $_primary_key = 'id'; public static $fetchColumns = array(); public static $fetchJoins = array(); /** * Static constructor */ public static function __init($db = 'db') { static::$_tbname = cot::$db->subscribe_queue; parent::__init($db); } protected function beforeInsert() { if (empty($this->_data['created'])) { $this->_data['created'] = date('Y-m-d H:i:s', cot::$sys['now']); } return parent::beforeInsert(); } public static function fieldList() { $fields = array('id' => array('type' => 'int', 'description' => 'id', 'primary' => true), 'subscribe' => array('type' => 'link', 'default' => 0, 'description' => cot::$L['subscribe_subscribe'], 'link' => array('model' => 'subscribe_model_Subscribe', 'relation' => SOM::TO_ONE, 'label' => 'title')), 'subscriber' => array('type' => 'link', 'default' => 0, 'description' => cot::$L['subscribe_subscribe'], 'link' => array('model' => 'subscribe_model_Subscriber', 'relation' => SOM::TO_ONE, 'label' => 'email')), 'to_email' => array('type' => 'varchar', 'length' => '255', 'default' => '', 'nullable' => false, 'description' => cot::$L['Email']), 'to_name' => array('type' => 'varchar', 'length' => '255', 'default' => '', 'description' => cot::$L['Name']), 'from_email' => array('type' => 'varchar', 'length' => '255', 'default' => '', 'nullable' => false, 'description' => cot::$L['subscribe_from_mail']), 'from_name' => array('type' => 'varchar', 'length' => '255', 'default' => '', 'description' => cot::$L['subscribe_from_title']), 'subject' => array('type' => 'varchar', 'length' => '255', 'default' => '', 'description' => cot::$L['subscribe_subject']), 'body' => array('type' => 'text', 'default' => '', 'description' => cot::$L['Text']), 'created' => array('type' => 'datetime', 'default' => date('Y-m-d H:i:s', cot::$sys['now']), 'description' => cot::$L['subscribe_created'])); return $fields; } } subscribe_model_Queue::__init();
/** * Запуск обработки очереди * php cli.php --a subscribe.main.runQueue > subscribeQueue.log * php /path/to/your/site/cli.php --a subscribe.main.runQueue > /path/to/your/site/log/subscribeQueue.log */ public function runQueueAction() { echo "---------------------------------------------------------------------------\n"; // Проверка процессов, выполнение которых могло завершиться ошибкой $pidFile = cot::$cfg['modules_dir'] . '/subscribe/inc/queue.txt'; if (!file_exists($pidFile)) { file_put_contents($pidFile, '0'); } if (!is_writeable($pidFile)) { echo "[ERROR] Can't set blocking. File '{$pidFile}' is not writable\n"; ob_flush(); exit; } $pingTime = intval(file_get_contents($pidFile)); if ($pingTime > 0 && cot::$sys['now'] - $pingTime < 300) { // 5 минут // Выполняется другой процесс echo "Other sending process is running\n"; ob_flush(); exit; } // Получаем список писем: $condition = array(); $limit = (int) cot::$cfg['subscribe']['queueCount']; // $items = subscribe_model_Queue::find($condition, $limit, 0, array(array('id', 'asc'))); // Сэкономим память. Ощутимо на большом количестве подписчиков if ($limit > 0) { $limit = "LIMIT {$limit}"; } $stmtItems = cot::$db->query("SELECT * FROM " . subscribe_model_Queue::tableName() . " ORDER BY `id` ASC {$limit}"); $count = $stmtItems->rowCount(); if (!$count) { echo "There are no emails to send at this time\n"; ob_flush(); exit; } echo "Emails count: " . $count . "\n"; // Реальная отправка писем $sender = new subscribe_sender_Cotmail(); /* === Hook === */ foreach (cot_getextplugins('subscribe.queue.run.main') as $pl) { include $pl; } /* ===== */ /* === Hook - Part1 : Set === */ $extp = cot_getextplugins('subscribe.queue.run.loop'); /* ===== */ $errors = 0; $i = 0; while ($item = $stmtItems->fetch()) { echo " - Processing: " . trim($item['name'] . ' ' . $item['email']) . " ..."; ob_flush(); $execute = true; /* === Hook - Part2 : Include === */ foreach ($extp as $pl) { include $pl; } /* ===== */ // Блокировка // Текущее системное время, а не то что было на момент старта скрипта file_put_contents($pidFile, time()); if ($execute) { $data = array('subscribe' => $item['subscribe'], 'subscriber' => $item['subscriber'], 'subject' => $item['subject'], 'fromName' => $item['from_name'], 'fromEmail' => $item['from_email'], 'toEmail' => $item['to_email'], 'toName' => $item['to_name'], 'body' => $item['body']); $isError = false; try { $sender->send($data); } catch (Exception $e) { $isError = true; $errors++; $errCode = $e->getCode(); $errMsg = $e->getMessage(); echo "\n[ERROR] {$errCode}: {$errMsg}! While sending to: {$item['to_email']}\n"; ob_flush(); // Зафиксировать в базе ошибку отправки сообщения if ($item['subscriber'] > 0) { $tmpData = array('last_error' => mb_substr("{$errCode}: {$errMsg}", 0, 253)); cot::$db->update(subscribe_model_Subscriber::tableName(), $tmpData, "id={$item['subscriber']}"); } echo "\n------------\n"; ob_flush(); } // Убираем обработанный элемент из очереди cot::$db->delete(subscribe_model_Queue::tableName(), "id={$item['id']}"); if (!$isError) { echo " done\n"; $i++; } unset($item); if ($i % 100 == 0) { gc_collect_cycles(); } } } $stmtItems->closeCursor(); // Освободим блокировку file_put_contents($pidFile, '0'); echo "{$i} letters send\n"; return ''; }