Example #1
0
 /**
  * Сборщик мусора
  */
 protected function garbageCollect()
 {
     // Удаление старых неподтвержденных подписчиков
     $delDate = new DateTime();
     // 1 неделя
     $delDate->sub(new DateInterval('P1W'));
     $items = subscribe_model_Subscriber::find(array(array('email_valid', 0), array('created', $delDate->format('Y-m-d H:i:s'), '<=')));
     if (!empty($items)) {
         foreach ($items as $itemRow) {
             $itemRow->delete();
         }
     }
 }
Example #2
0
 /**
  * Редактирование рассылки
  * @return string
  * @throws Exception
  */
 public function editAction()
 {
     global $cot_extrafields, $admintitle, $adminpath;
     $id = cot_import('id', 'G', 'INT');
     // id Рассылки
     $act = cot_import('act', 'G', 'ALP');
     if (empty($act)) {
         $act = cot_import('act', 'P', 'ALP');
     }
     $adminpath[] = array(cot_url('admin', array('m' => 'subscribe')), cot::$L['subscribe_subscribes']);
     /* === Hook === */
     foreach (cot_getextplugins('subscribe.admin.edit.first') as $pl) {
         include $pl;
     }
     /* ===== */
     if (!$id) {
         $item = new subscribe_model_Subscribe();
         $admintitle = cot::$L['subscribe_add_new'];
         $adminpath[] = array(cot_url('admin', array('m' => 'subscribe', 'a' => 'edit')), $admintitle);
     } else {
         $item = subscribe_model_Subscribe::getById($id);
         if (!$item) {
             cot_error(cot::$L['subscribe_err_not_found']);
             cot_redirect(cot_url('admin', array('m' => 'subscribe'), '', true));
         }
         if ($act == 'clone') {
             $id = null;
             $item = clone $item;
             $admintitle = cot::$L['subscribe_add_new'];
             $adminpath[] = array(cot_url('admin', array('m' => 'subscribe', 'a' => 'edit')), $admintitle);
         } else {
             $admintitle = $item->title . " [" . cot::$L['Edit'] . "]";
             $adminpath[] = array(cot_url('admin', array('m' => 'subscribe', 'a' => 'edit', 'id' => $item->id)), $admintitle);
         }
     }
     // Сохранение
     if ($act == 'save') {
         unset($_POST['id'], $_POST['user'], $_POST['x'], $_POST['act']);
         /* === Hook === */
         foreach (cot_getextplugins('subscribe.admin.save.first') as $pl) {
             include $pl;
         }
         /* ===== */
         $data = $_POST;
         $data['next_run'] = cot_import_date('next_run');
         if (!empty($data['next_run'])) {
             $data['next_run'] = date('Y-m-d H:i:s', $data['next_run']);
         }
         $item->setData($data);
         /* === Hook === */
         foreach (cot_getextplugins('subscribe.admin.save.validate') as $pl) {
             include $pl;
         }
         /* ===== */
         // There is some errors
         if (!$item->validate() || cot_error_found()) {
             $urlParams = array('m' => 'subscribe', 'a' => 'edit');
             if ($item->id > 0) {
                 $urlParams['id'] = $item->id;
             }
             cot_redirect(cot_url('admin', $urlParams, '', true));
         }
         $isNew = $item->id == 0;
         // Перерасчет времени следующего запуска
         // Делать это в админке при редактировании рассылки и при выполнении рассылки
         // А то могут быть коллизии
         $recalculate = true;
         if (!empty($item->next_run)) {
             $tmp = strtotime($item->next_run);
             if ($tmp > cot::$sys['now']) {
                 $recalculate = false;
             }
         }
         if ($recalculate) {
             $item->next_run = $item->getNextRunDate();
         }
         // Сохранение
         if ($item->save()) {
             cot_message(cot::$L['Saved']);
             $urlParams = array('m' => 'subscribe', 'a' => 'edit', 'id' => $item->id);
             $redirectUrl = cot_url('admin', $urlParams, '', true);
             /* === Hook === */
             foreach (cot_getextplugins('subscribe.admin.save.done') as $pl) {
                 include $pl;
             }
             /* ===== */
             // Редирект на станицу рассылки
             cot_redirect($redirectUrl);
         }
     }
     // 'input_textarea_editor', 'input_textarea_medieditor', 'input_textarea_minieditor', ''
     $editor = 'input_textarea_editor';
     /* === Hook === */
     foreach (cot_getextplugins('subscribe.admin.edit.main') as $pl) {
         include $pl;
     }
     /* ===== */
     $nextRun = 0;
     if (!empty($item->next_run)) {
         $nextRun = strtotime($item->next_run);
     }
     $formElements = array('hidden' => array('element' => cot_inputbox('hidden', 'act', 'save')), 'title' => array('element' => cot_inputbox('text', 'title', $item->rawValue('title')), 'required' => true, 'label' => subscribe_model_Subscribe::fieldLabel('title')), 'alias' => array('element' => cot_inputbox('text', 'alias', $item->rawValue('alias')), 'label' => subscribe_model_Subscribe::fieldLabel('alias')), 'admin_note' => array('element' => cot_textarea('admin_note', $item->rawValue('admin_note'), 5, 120, ''), 'label' => subscribe_model_Subscribe::fieldLabel('admin_note')), 'from_mail' => array('element' => cot_inputbox('text', 'from_mail', $item->rawValue('from_mail')), 'label' => subscribe_model_Subscribe::fieldLabel('from_mail'), 'hint' => cot::$L['subscribe_from_mail_hint']), 'from_title' => array('element' => cot_inputbox('text', 'from_title', $item->rawValue('from_title')), 'label' => subscribe_model_Subscribe::fieldLabel('from_title')), 'subject' => array('element' => cot_inputbox('text', 'subject', $item->rawValue('subject')), 'label' => subscribe_model_Subscribe::fieldLabel('subject')), 'description' => array('element' => cot_textarea('description', $item->rawValue('description'), 5, 120, '', $editor), 'label' => subscribe_model_Subscribe::fieldLabel('description')), 'content_url' => array('element' => cot_inputbox('text', 'content_url', $item->rawValue('content_url')), 'label' => subscribe_model_Subscribe::fieldLabel('content_url'), 'hint' => cot::$L['subscribe_content_url_hint']), 'text' => array('element' => cot_textarea('text', $item->rawValue('text'), 5, 120, '', $editor), 'label' => subscribe_model_Subscribe::fieldLabel('text'), 'hint' => cot::$L['subscribe_text_hint']), 'next_run' => array('element' => cot_selectbox_date($nextRun, 'long', 'next_run'), 'label' => subscribe_model_Subscribe::fieldLabel('next_run'), 'hint' => cot::$L['subscribe_next_run_hint'] . " " . cot::$usr['timetext']), 'sched_mday' => array('element' => cot_inputbox('text', 'sched_mday', $item->rawValue('sched_mday')), 'label' => subscribe_model_Subscribe::fieldLabel('sched_mday'), 'hint' => cot::$L['subscribe_sched_mday_hint']), 'sched_wday' => array('element' => cot_inputbox('text', 'sched_wday', $item->rawValue('sched_wday')), 'label' => subscribe_model_Subscribe::fieldLabel('sched_wday'), 'hint' => cot::$L['subscribe_sched_wday_hint']), 'sched_time' => array('element' => cot_inputbox('text', 'sched_time', $item->rawValue('sched_time')), 'label' => subscribe_model_Subscribe::fieldLabel('sched_time'), 'hint' => cot::$L['subscribe_sched_time_hint']), 'active' => array('element' => cot_checkbox($item->rawValue('active'), 'active', subscribe_model_Subscribe::fieldLabel('active'))), 'periodical' => array('element' => cot_checkbox($item->rawValue('periodical'), 'periodical', subscribe_model_Subscribe::fieldLabel('periodical'))), 'sort' => array('element' => cot_inputbox('text', 'sort', $item->rawValue('sort')), 'label' => subscribe_model_Subscribe::fieldLabel('sort')));
     if (!empty($cot_extrafields[cot::$db->subscribe])) {
         // Extra fields for subscribe
         foreach ($cot_extrafields[cot::$db->subscribe] as $exfld) {
             $fName = $exfld['field_name'];
             $formElements[$fName] = array('element' => cot_build_extrafields($fName, $exfld, $item->rawValue($fName)));
             if ($exfld['field_type'] !== 'checkbox') {
                 isset(cot::$L['subscribe_' . $exfld['field_name'] . '_title']) ? cot::$L['subscribe_' . $exfld['field_name'] . '_title'] : subscribe_model_Subscribe::fieldLabel($fName);
             }
         }
     }
     $subscribers = subscribe_model_Subscriber::count(array(array('subscribe', $item->id)));
     $activeSubscribers = subscribe_model_Subscriber::count(array(array('subscribe', $item->id), array('active', 1)));
     $actionParams = array('m' => 'subscribe', 'a' => 'edit');
     if ($item->id > 0) {
         $actionParams['id'] = $item->id;
     }
     $template = array('subscribe', 'admin', 'edit');
     $view = new View();
     $view->page_title = $admintitle;
     $view->item = $item;
     $view->subscribers = $subscribers;
     $view->activeSubscribers = $activeSubscribers;
     $view->formElements = $formElements;
     $view->formAction = cot_url('admin', $actionParams);
     /* === Hook === */
     foreach (cot_getextplugins('subscribe.admin.edit.view') as $pl) {
         include $pl;
     }
     /* ===== */
     return $view->render($template);
 }
Example #3
0
 protected function beforeDelete()
 {
     // Удалить всех подписчиков
     $items = subscribe_model_Subscriber::find(array(array('subscribe', $this->_data['id'])));
     if (!empty($items)) {
         foreach ($items as $itemRow) {
             $itemRow->delete();
         }
     }
     return parent::beforeDelete();
 }
Example #4
0
 /**
  * Запуск обработки очереди
  * 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 '';
 }
Example #5
0
 /**
  * Отписаться от рассылки
  */
 public function unsubscribeAction()
 {
     $code = cot_import('code', 'G', 'TXT');
     if (!$code) {
         cot_die_message('404');
     }
     $title = cot::$L['subscribe_unsubscribe'];
     $subscriber = subscribe_model_Subscriber::fetchOne(array(array('unsubscr_code', $code)));
     if (!$subscriber) {
         cot_error(cot::$L['subscribe_err_wrong_unsubscribe_code']);
     }
     cot::$sys['sublocation'] = $title;
     cot::$out['subtitle'] = $title;
     if ($subscriber) {
         $title .= ': ' . $subscriber->subscribe->title;
         cot::$sys['sublocation'] = $title;
         cot::$out['subtitle'] = $title;
         $subscriber->active = 0;
         $subscriber->save();
         cot_message(sprintf(cot::$L['subscribe_msg_you_unsubscribed'], $subscriber->subscribe->title));
     }
     $template = array('subscribe', 'unsubscribe');
     $view = new View();
     $view->page_title = $title;
     $view->subscriber = $subscriber;
     /* === Hook === */
     foreach (cot_getextplugins('subscribe.unsubscribe.view') as $pl) {
         include $pl;
     }
     /* ===== */
     return $view->render($template);
 }
Example #6
0
 public function deleteAction()
 {
     $id = cot_import('id', 'G', 'INT');
     $d = cot_import('d', 'G', 'INT');
     $backUrlParams = array('m' => 'subscribe', 'n' => 'user');
     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['subscribe_err_subscriber_not_found']);
         cot_redirect(cot_url('admin', $backUrlParams));
     }
     $item = subscribe_model_Subscriber::getById($id);
     if (!$item) {
         cot_error(cot::$L['subscribe_err_subscriber_not_found']);
         cot_redirect(cot_url('admin', $backUrlParams));
     }
     $email = $item->email;
     $item->delete();
     cot_message(sprintf(cot::$L['subscribe_subscriber_deleted'], $email));
     cot_redirect(cot_url('admin', $backUrlParams, '', true));
 }