Наверх

Подписка на новости для вашего сайта

Сделал я себе блог и решил, что каждый день на него никто заходить все равно не будет, но почитать новые статьи многие бы не отказались. И решил я сделать подписку на новые статьи для любого посетителя.

Так как на начальном этапе подписчиков будет немного, то отправку писем я реализовал с помощью простого плагина на событие OnDocFormSave:
<?php
switch ($modx->event->name) {
  case "OnDocFormSave":
    if ($mode != 'new' || $resource->template != 2) {
        return; break;
    } else {
      $salt = 'Соль для md5 при генерации ссылок на отписку';
      // Используем механизм отправки писем из Tickets
        $Tickets = $modx->getService('tickets','Tickets',
         $modx->getOption('tickets.core_path',null,
                     $modx->getOption('core_path')
                     .'components/tickets/')
         .'model/tickets/',$scriptProperties);
      /* Получаем список подписчиков
        (если пользователь подписан, zip = 1) */
        $subscribers = $modx->getCollection('modUserProfile',
                  array('zip' => 1, 'email:!=' => ''));
        foreach ($subscribers as $subscriber) {
            $sendTo = $subscriber->get('email');
            $mail = array("to" => $sendTo
             , "subject" => "Новая статья: ".$resource->pagetitle
            , "message" => "<b>В блоге Ильи Уткина новая статья.</b><h2>"
               .$resource->pagetitle."</h2>
                <table width=\"710\"><tbody><tr><td>".$resource->introtext
               ."</td></tr></tbody></table><a href=\""
               .$modx->makeUrl($resource->id,'','','full')
               .'\">Читать далее »</a><p>Чтобы отписаться от рассылки
               перейдите по ссылке:</p><p>
	       <a href=\"http://ilyaut.ru/profile/?email='
               .$sendTo.'&hash='.md5($sendTo.$salt).'\">
               http://ilyaut.ru/profile/?email='
               .$sendTo.'&hash='.md5($sendTo.$salt).'</a></p>');
            $Tickets->sendMail($mail);
        }
    }
}
Этот код отправляет письма всем пользователям, у которых параметр zip равен 1.

Теперь надо дать пользователям возможность подписаться на новости. Для пользователей есть форма, в которую они вписывают свой электронный адрес. Вот обработчик формы:
<?php
$email = $hook->getValue('email');
$success = false;
// Если пользователь неавторизован, то
if (!$modx->user->get('id')) {
    // Если уже есть пользователь с таким e-mail'ом, ошибка
    if ($users = $modx->getCollection('modUserProfile',
	    array('email' => $email))) {
        $hook->addError('email','На сайте уже есть
	    пользователь с таким электронным
            адресом. Если это вы, то для
	    управления рассылкой придется авторизоваться');
        return false;
    } else {
	// Если нет, создаем пользователя и подписываем
        $user = $modx->newObject('modUser');
        $user->fromArray(array('username' => $email
	                     , 'password' => $email));
        $Profile = $modx->newObject('modUserProfile');
        $Profile->set('email', $email);
        $Profile->set('fullname', 'Подписчик');
        $Profile->set('zip', 1); // подписан на новости
        $Profile->save();
        $user->addOne($Profile);
        $user->save();
        $success = true;
    }
} else {
    // Если пользователь авторизован, просто вносим изменения
    $profile = $modx->user->getOne('Profile');
    $profile->set('zip',1);
    $profile->set('email',$email);
    $profile->save();
    $success = true;
}

if ($success) {
    // Отправляем письмо, с помощью которого можно отписаться
    $Tickets = $modx->getService('tickets','Tickets' ...;
    $Tickets->sendMail(array('to' => $email,
	 'subject' => 'Подписка на новые статьи успешно оформлена',
	 'message' => '</h3>Вы подписались на новые статьи.</h3>
	   <p>Если это были не вы, просто перейдите по ссылке
	   и подписка аннулируется:</p>
	   <p><a href="http://ilyaut.ru/profile/?email='
	   .$email.'&hash='.md5($email.$salt).'">
	   http://ilyaut.ru/profile/?email='.$email.'&hash='
	   .md5($email.$salt).'</a></p>'));
    return true;
} else {
    $hook->addError('email','Что-то не так');
    return false;
}
Соль везде одинаковая, только я вам не скажу, какая))))

И теперь делаем отписку от рассылки. На старнице /profile/ сниппет:
// Если в ссылке нет email или hash ничего не делаем
if (!$_GET['email'] || !$_GET['hash']) return;

// Если хеш неправильный, показываем ошибку
if ($_GET['hash'] != md5($_GET['email'].$salt)) {
    return '<h1 style="color: #c00;">Ошибка.
	    Вы не отписаны от рассылки.</h1>';
}
// Если все верно, находим пользователя по email
$Profile = $modx->getCollection('modUserProfile',
	    array('email' => $_GET['email']));
if (!$Profile) return '<h1 style="color: #c00;">Ошибка.
		       Вы не отписаны от рассылки.</h1>';

foreach ($Profile as $prof) {
    $user = $prof->getOne('User');
    // Если это не просто подписчик, а именно пользователь
    if ($prof->get('fullname') != 'Подписчик') {
        // то просто отписываем его от рассылки
        $prof->set('zip',2); // отписан
        $prof->save();
    } else {
        // А если это просто подписчик, удаляем его
        $user->remove();
    }
}

return '<h1 style="color: #0c0;">Вы отписаны от рассылки.</h1>';

Можно было сделать хеш похитрее, но так как он защищает только от несанкционированной отписки от рассылки, то и так пойдет =) G+

12 комментариев

  1. Юлия Подковко 05 ноября 2013, 17:43(Комментарий был изменён) # 0
    Илья, а как это в итоге работает?
    Вы добавляете новость в дереве документов на сайте, она автоматически разлетается подписчикам?
    1. Илья Уткин 05 ноября 2013, 17:47(Комментарий был изменён) # 0
      Да, но у меня стоит ограничение по шаблону — если ресурс не новый и шаблон не второй, ничего не делаем:
      if ($mode != 'new' || $resource->template != 2) {
              return; break;
          }
      Если вы собрались делать рассылку, лучше подождите, Василий Наумкин скоро обещает рассказать, как сделать рассылку и подарить сообществу готовый компонент по рассылке.
      1. Юлия Подковко 06 ноября 2013, 11:08(Комментарий был изменён) # 0
        Спасибо! Интересная идея в сообществе, буду следить
        Только что сообразила, что везде решения для Revo, эх, не мой вариант в данном проекте
    2. Katehiz 27 апреля 2015, 08:10 # 0
      Доброго времени суток. Задача рассылать уведомления неавторизованным подписчикам о новых записях в новостях. Использую компонент Tickets Создал плагин с приведенным выше кодом. Создал файл обработчик subscribeNews.php. Как использовать обработчик? У меня есть форма на сайте:
      <form action="[[++base_url]]core/components/tsender/subscribeNews.php" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate form form-inline" target="_blank" novalidate>
          <div class="mc-field-group">
              <input type="email" value="" placeholder="Введите e-mail адрес" name="email" class="required email" id="mce-EMAIL">
              <input type="submit" value="Подписаться" name="subscribe" id="mc-embedded-subscribe" class="btn btn-primary">
          </div>                          
      </form>
      
      Ввожу emai в Input, нажимаю отправить, открывается пустая страница "[адрес сайта]/core/components/tsender/subscribeNews.php". Письма не приходят, когда создаешь новый тикет. Подскажите, что не так сделал?
      1. Илья Уткин 27 апреля 2015, 08:33 # 0
        Статья старенькая уже. Сейчас в MODX есть дополнение Sendex. Используйте его.
      2. Katehiz 27 апреля 2015, 13:20 # 0
        Я так понял, что в шаблоне письма Sendex нужно прописать вызов
        [[!getTickets? &limit=`1` tpl=`шаблон превью новости`]]
        или
        [[!TicketLatest?]]
        для того чтобы получить последние/юю новости?
        1. Илья Уткин 27 апреля 2015, 13:26 # 0
          1. Илья Уткин 27 апреля 2015, 13:29 # 0
            1. Katehiz 27 апреля 2015, 17:35 # 0
              Благодарю разобрался. Все работает!
          2. Katehiz 27 апреля 2015, 17:34 # 0
            Благодарю разобрался. Все работает!
            1. Jassie 18 января 2016, 08:59 # 0
              Скажите, Ваше решение для Revo? Нет ли для Evo чего-то подобного?
              1. Илья Уткин 18 января 2016, 09:01 # 0
                Для Evo это решение не подойдет. Ничего не видел такого, к сожалению…

              Авторизация

              через сервис Loginza:

              Подписка или RSS

              Буду присылать новые статьи — никакого спама



              Шаблоны MODX

              1 2 Дальше »

              Объектная
              модель
              MODX