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_default — Да
И эта опция оказывается включена, в чанках отрабатывается, а в шаблонах и на страницах нет.
Стандартные теги будут работать, но возможны сюрпризы. Да и зачем.
Все сделал по инструкции, все работает при подписке, все красиво. Спасибо.
Но. когда отписываюсь из письма, переходит на страницу и все. Ничего не пишет, что я отписался, и из админки не отписывается. В чем может быть проблема? Спасибо!
п.с. mngatoff допиши в статью, что бы другие как я не задавали вопросов.
п.с.с. спасибо за статью!