Sendex и AjaxForm - подписка на рассылку ч/з ajax
Sendex, как учебный компонент, особо не развивается, но он довольно удобен и приятен в обращении изнутри сайта. В связи с чем регулярно его использую. Но вот «снаружи», на фронте, он не очень удобен. Очередная просьба от клиента «чтобы окошко появлялось, а страничка не перезагружалась», побудила переписать для себя сниппет так, чтобы потом пользовать его через ajaxform. Получилось три чанка, один сниппет и немного джаваскрипта.
Итак.
Сниппет Sendex_custom принимает четыре действия (action):
Модифицированные чанки выглядят вот так:
sendex.subscribe:
sendex.unsubscribe:
Добавляем к этому небольшую js-обвязочку:
Теперь пользователь будет видеть стандартные красные jGrowl-всплывашки с ошибками, если что-то сделает не так, и зеленые с сообщением «все отлично, пройди по ссылке». А форма в случае успешной отправки будет заменяться нужным нам текстом.
Итак, пользователю пришла ссылка, он по ней перешел. Надо бы его встретить. В дело вступает confirm.
Вставляем перед формами подписки (я вставил в самое начало шаблона, еще до head) следующий код:
И в любом месте шаблона вызываем плейсхолдер с сообщением об успехе.
Чанк sendex.confirm у меня выглядит вот так:
Здесь у нас невидимый блок с сообщением и кусок скрипта, который его покажет во всплывающем окне.
Я использую для всплывающих окон MagnificPopup. Этот код рассчитан на него. Если вы используете другой скрипт для поп-апов, легко переделаете код под себя.
Ну и теперь, собственно, сам сниппет.
Итак.
Сниппет Sendex_custom принимает четыре действия (action):
- check — проверка, подписан ли текущий пользователь. Если да — возвращает его код, если нет — false
- confirm — подтверждение подписки при переходе по ссылке из письма. Если ты перешел по ссылке и подписка подтвердилась, выставляется плейсхолдер sendex.confirm с содержимым чанка из параметра 'tpl'
- subscribe
- unsubscribe
{set $subscribed = '!sendex_custom' | snippet : ['id' => 1, 'action' => 'check']}
<div id="sendexForm">
{if $subscribed}
{'!ajaxform' | snippet : [
'snippet' => 'sendex_custom',
'form' => 'sendex.unsubscribe',
'id' => 1,
'action' => 'unsubscribe',
'code' => $subscribed,
]}
{else}
{'!ajaxform' | snippet : [
'snippet' => 'sendex_custom',
'form' => 'sendex.subscribe',
'id' => 1,
'action' => 'subscribe',
'tplActivate' => 'sendex.activate',
]}
{/if}
</div>
Модифицированные чанки выглядят вот так:
sendex.subscribe:
<form id="sendexForm_form_subscribe">
<div class="hidden"><input type="text" name="address"></div><!-- это только ради антиспама -->
<input type="email" name="email" value="{$_modx->user.email}" placeholder="Ваш e-mail">
<button type="submit">Подписаться</button>
</form>
sendex.unsubscribe:
<form id="sendexForm_form_unsubscribe">
<div class="hidden"><input type="text" name="address"></div>
<input type="hidden" name="code" value="[[+code]]">
<button type="submit">Отписаться</button>
</form>
Добавляем к этому небольшую js-обвязочку:
$(document).on('af_complete', function(e, response) {
if (response.success) {
switch (response.form.attr('id')) {
case 'sendexForm_form_subscribe':
$('#sendexForm').html('Вы подписались на рассылку!');
break;
case 'sendexForm_form_unsubscribe':
$('#sendexForm').html('Вы отписались от рассылки');
break;
}
}
});
Теперь пользователь будет видеть стандартные красные jGrowl-всплывашки с ошибками, если что-то сделает не так, и зеленые с сообщением «все отлично, пройди по ссылке». А форма в случае успешной отправки будет заменяться нужным нам текстом.
Итак, пользователю пришла ссылка, он по ней перешел. Надо бы его встретить. В дело вступает confirm.
Вставляем перед формами подписки (я вставил в самое начало шаблона, еще до head) следующий код:
{$_modx->runSnippet('!sendex_custom', [
'id' => 1,
'action' => 'confirm',
'tpl' => 'sendex.confirm'
])}
И в любом месте шаблона вызываем плейсхолдер с сообщением об успехе.
{'sendex.confirm' | placeholder}
Чанк sendex.confirm у меня выглядит вот так:
<div id="sendexConfirm" class="mfp-hide">
<h4>Поздравляем!</h4>
<p>Вы только что успешно
подписались на нашу рассылку.</p>
<p>Отписаться вы можете в любой момент, перейдя по ссылке "Отписаться" из очередного письма.</p>
<button onclick="$.magnificPopup.close()">ОК</button>
</div>
{set $script}
<script>
$(document).on('ready', function() {
$.magnificPopup.open({
type: 'inline',
items: {
src: '#sendexConfirm',
}
});
});
</script>
{/set}
{$_modx->regClientScript($script, true)}
Здесь у нас невидимый блок с сообщением и кусок скрипта, который его покажет во всплывающем окне.
Я использую для всплывающих окон MagnificPopup. Этот код рассчитан на него. Если вы используете другой скрипт для поп-апов, легко переделаете код под себя.
Ну и теперь, собственно, сам сниппет.
<?php
if (!empty($_POST['address']) or empty($scriptProperties['action']) or !in_array($scriptProperties['action'], array('subscribe', 'confirm', 'check', 'unsubscribe'))) {
return $AjaxForm->error('Неверный запрос');
}
if (!$modx->loadClass('pdofetch', MODX_CORE_PATH . 'components/pdotools/model/pdotools/', false, true)) {
return false;
}
$pdoFetch = new pdoFetch($modx, $scriptProperties);
$Sendex = $modx->getService('sendex','Sendex',$modx->getOption('sendex_core_path',null,$modx->getOption('core_path').'components/sendex/').'model/sendex/',$scriptProperties);
if (!($Sendex instanceof Sendex)) {
return false;
}
if (empty($scriptProperties['id']) or !($newsletter = $modx->getObject('sxNewsletter', $scriptProperties['id'])) or !$newsletter->active) {
return false;
}
if (empty($scriptProperties['linkTTL'])) {
$linkTTL = 1800;
}
$placeholders = $newsletter->toArray();
$placeholders['message'] = '';
$placeholders['error'] = 0;
if ($modx->user->isAuthenticated($modx->context->key)) {
$placeholders = array_merge(
$modx->user->toArray(),
$modx->user->Profile->toArray(),
$placeholders
);
}
$isAuthenticated = $modx->user->isAuthenticated($modx->context->key);
switch ($scriptProperties['action']) {
case 'confirm':
if (!empty($_GET['hash']) && $_GET['sx_action'] == $scriptProperties['action']) {
if ($response = $newsletter->confirmEmail($_GET['hash'])) {
return $modx->setPlaceholder('sendex.confirm', $pdoFetch->getChunk($tpl));
} else {
return false;
}
}
break;
case 'check':
if ($isAuthenticated and $subs_id = $newsletter->isSubscribed(0, $modx->user->Profile->email) and $subscriber = $modx->getObject('sxSubscriber', $subs_id)) {
return $subscriber->code;
}
return false;
break;
case 'subscribe':
$error = '';
$params = array();
if (empty($_POST['email'])) {
$error = $modx->lexicon('sendex_subscribe_err_email_ns');
} else {
$email = strip_tags(trim(preg_replace('/\s{2,}/', ' ', $_POST['email'])));
if (!empty($email) && filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
$error = 'Некорректный email';
} else {
$response = $newsletter->checkEmail($email, 0, $linkTTL);
if ($response === true) {
$error = $modx->lexicon('sendex_subscribe_err_already');
} elseif ($response === false) {
$error = $modx->lexicon('sendex_subscribe_err_email_wrong');
} else {
$params['hash'] = $response;
$params['sx_action'] = 'confirm';
$placeholders['link'] = $modx->makeUrl($modx->resource->id, $modx->context->key, $params, 'full');
$placeholders['email_body'] = $modx->getChunk($tplActivate, $placeholders);
$response = $Sendex->sendEmail($email, $placeholders);
if ($response !== true) {
$error = $modx->lexicon('sendex_subscribe_err_email_send');
} else {
return $AjaxForm->success('Мы отправили Вам письмо со ссылкой - перейдите по ней, и Ваша подписка будет активирована.');
}
}
}
}
if (!empty($error)) {
return $AjaxForm->error($error);
}
break;
case 'unsubscribe':
if (!empty($_REQUEST['code']) and $response = $newsletter->unSubscribe($_REQUEST['code'])) {
return $AjaxForm->success('Вы отписались от рассылки');
}
return $AjaxForm->error('Ошибка');
break;
}
Комментарии: 17
Подскажите, пожалуйста. У меня вот такие конструкции {} не отрабатываются, pdoTools стоит последний, т.е. Fenom там по идее должен быть. Что-то ещё нужно установить?
Системные настройки
pdotools_fenom_default — Да
pdotools_fenom_default — Да
Спасибо! А после этого стандартные конструкции MODX будут работать?
И эта опция оказывается включена, в чанках отрабатывается, а в шаблонах и на страницах нет.
И эта опция оказывается включена, в чанках отрабатывается, а в шаблонах и на страницах нет.
«использовать fenom на страницах» тоже надо включить. И следить потом, чтобы все что с фигурными скобками и при этом не феном (какая-нибудь гугл-аналитика, к примеру) либо было в теге {ignore}{/ignore}, либо имело пробел после скобки.
Стандартные теги будут работать, но возможны сюрпризы. Да и зачем.
Стандартные теги будут работать, но возможны сюрпризы. Да и зачем.
пользователь это зарегистрированный юзер или гости тоже могут использовать
гости тоже
Здравствуйте!
Все сделал по инструкции, все работает при подписке, все красиво. Спасибо.
Но. когда отписываюсь из письма, переходит на страницу и все. Ничего не пишет, что я отписался, и из админки не отписывается. В чем может быть проблема? Спасибо!
Все сделал по инструкции, все работает при подписке, все красиво. Спасибо.
Но. когда отписываюсь из письма, переходит на страницу и все. Ничего не пишет, что я отписался, и из админки не отписывается. В чем может быть проблема? Спасибо!
приветствую. В данном примере отписки по ссылке нет, ее надо дописать — по аналогии, сниппет принимающий парметры из ссылки и отписывающий человека, а затем показывающий сообщение
Подскажите, я так понимаю что Sendex не поддерживает синтаксис fenom в чанках?? Например чанк tpl.Sendex.activate и плейсхолдер [[+link]] не преобразется в fenom, ни {$link}, ни {$_pls['link']}
Кто дописывал возможность отписаться?
Судя по коду, тут эта возможность уже есть.
Так не смог разобраться в чём дело. Выдаёт ошибку.
Ошибка
Не могу отправить email.
Вот что выдаёт в консоле:
{"success":false,"message":"\u041d\u0435 \u043c\u043e\u0433\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c email.","data":[]}
Решился вопрос? Та же проблема
Попробовал на другом сайте, та же история.
А у вас в базу записываются email'ы после перехода из письма? Попробовал сегодня с утра, письма приходят, а данные в базу не записываются. Думаю это уже на стороне Sendex проблема. Будем разбираттся)
В статье не указан чанк: sendex.activate создай его, можно копирнуть и переименовать из tpl.Sendex.activate
п.с. mngatoff допиши в статью, что бы другие как я не задавали вопросов.
п.с.с. спасибо за статью!
п.с. mngatoff допиши в статью, что бы другие как я не задавали вопросов.
п.с.с. спасибо за статью!
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.