Send confirmation email + page

This commit is contained in:
Jonathan Labreuille
2016-02-24 10:56:47 +01:00
parent cf6466197a
commit 14fe333678
5 changed files with 225 additions and 30 deletions

View File

@ -208,6 +208,16 @@ const bulk_actions = [
); );
} }
}, },
{
name: 'sendConfirmationEmail',
label: 'Resend confirmation email',
onSuccess: function(response) {
MailPoet.Notice.success(
'%$1d confirmation emails have been sent.'
.replace('%$1d', ~~response)
);
}
},
{ {
name: 'trash', name: 'trash',
label: 'Trash', label: 'Trash',
@ -272,13 +282,13 @@ const SubscriberList = React.createClass({
subscriber.subscriptions.map((subscription) => { subscriber.subscriptions.map((subscription) => {
const segment = this.getSegmentFromId(subscription.segment_id); const segment = this.getSegmentFromId(subscription.segment_id);
if(segment === false) return;
if (subscription.status === 'subscribed') { if (subscription.status === 'subscribed') {
subscribed_segments.push(segment.name); subscribed_segments.push(segment.name);
} else { } else if (subscription.status === 'unsubscribed') {
unsubscribed_segments.push(segment.name); unsubscribed_segments.push(segment.name);
} }
}); });
segments = ( segments = (
<span> <span>
<span className="mailpoet_segments_subscribed"> <span className="mailpoet_segments_subscribed">

View File

@ -1,12 +1,17 @@
<?php <?php
namespace MailPoet\Models; namespace MailPoet\Models;
use MailPoet\Mailer\Mailer;
use MailPoet\Util\Helpers; use MailPoet\Util\Helpers;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
class Subscriber extends Model { class Subscriber extends Model {
public static $_table = MP_SUBSCRIBERS_TABLE; public static $_table = MP_SUBSCRIBERS_TABLE;
const STATUS_SUBSCRIBED = 'subscribed';
const STATUS_UNSUBSCRIBED = 'unsubscribed';
const STATUS_UNCONFIRMED = 'unconfirmed';
function __construct() { function __construct() {
parent::__construct(); parent::__construct();
@ -16,13 +21,22 @@ class Subscriber extends Model {
)); ));
} }
static function findOne($id = null) {
if(is_int($id) || (string)(int)$id === $id) {
return parent::findOne($id);
} else {
return parent::where('email', $id)->findOne();
}
}
function segments() { function segments() {
return $this->has_many_through( return $this->has_many_through(
__NAMESPACE__.'\Segment', __NAMESPACE__.'\Segment',
__NAMESPACE__.'\SubscriberSegment', __NAMESPACE__.'\SubscriberSegment',
'subscriber_id', 'subscriber_id',
'segment_id' 'segment_id'
)->where(MP_SUBSCRIBER_SEGMENT_TABLE.'.status', 'subscribed'); )
->where(MP_SUBSCRIBER_SEGMENT_TABLE.'.status', self::STATUS_SUBSCRIBED);
} }
function delete() { function delete() {
@ -56,10 +70,99 @@ class Subscriber extends Model {
} }
} }
function sendConfirmationEmail() { function getConfirmationUrl() {
$this->set('status', 'unconfirmed'); $post = get_post(Setting::getValue('signup_confirmation.page'));
// TODO if($post === null) {
// create page
return '';
} else {
$url = get_permalink($post);
$params = array(
'mailpoet_action=confirm',
'mailpoet_token='.md5(AUTH_KEY.$this->email),
'mailpoet_email='.$this->email
);
// add parameters
$url .= (parse_url($url, PHP_URL_QUERY) ? '&' : '?').join('&', $params);
$url_params = parse_url($url);
if(empty($url_params['scheme'])) {
$url = get_bloginfo('url').$url;
}
return $url;
}
}
function sendConfirmationEmail() {
if($this->status === self::STATUS_UNCONFIRMED) {
$signup_confirmation = Setting::getValue('signup_confirmation');
$segments = $this->segments()->findMany();
$segment_names = array_map(function($segment) {
return $segment->name;
}, $segments);
$body = nl2br($signup_confirmation['body']);
// replace list of segments shortcode
$body = str_replace(
'[lists_to_confirm]',
'<strong>'.join(', ', $segment_names).'</strong>',
$body
);
// replace activation link
$body = str_replace(
array(
'[activation_link]',
'[/activation_link]'
),
array(
'<a href="'.htmlentities($this->getConfirmationUrl()).'">',
'</a>'
),
$body
);
// build email data
$email = array(
'subject' => $signup_confirmation['subject'],
'body' => array(
'html' => $body,
'text' => $body
)
);
// convert subsdriber to array
$subscriber = $this->asArray();
// set from
$from = (!empty($signup_confirmation['from'])
? $signup_confirmation['from']
: false
);
// set reply to
$reply_to = (!empty($signup_confirmation['reply_to'])
? $signup_confirmation['reply_to']
: false
);
// send email
$mailer = new Mailer(
false,
$from,
$reply_to
);
print '<pre>';
print_r($mailer);
print '</pre>';
exit();
return $mailer->send($email, $subscriber);
}
return false;
} }
static function subscribe($subscriber_data = array(), $segment_ids = array()) { static function subscribe($subscriber_data = array(), $segment_ids = array()) {
@ -76,11 +179,11 @@ class Subscriber extends Model {
} }
if((bool)Setting::getValue('signup_confirmation.enabled')) { if((bool)Setting::getValue('signup_confirmation.enabled')) {
if($subscriber->status !== 'subscribed') { if($subscriber->status !== self::STATUS_SUBSCRIBED) {
$subscriber->sendConfirmationEmail(); $subscriber->sendConfirmationEmail();
} }
} else { } else {
$subscriber->set('status', 'subscribed'); $subscriber->set('status', self::STATUS_SUBSCRIBED);
} }
if($subscriber->save()) { if($subscriber->save()) {
@ -162,19 +265,19 @@ class Subscriber extends Model {
'count' => self::getPublished()->count() 'count' => self::getPublished()->count()
), ),
array( array(
'name' => 'subscribed', 'name' => self::STATUS_SUBSCRIBED,
'label' => __('Subscribed'), 'label' => __('Subscribed'),
'count' => self::filter('subscribed')->count() 'count' => self::filter(self::STATUS_SUBSCRIBED)->count()
), ),
array( array(
'name' => 'unconfirmed', 'name' => self::STATUS_UNCONFIRMED,
'label' => __('Unconfirmed'), 'label' => __('Unconfirmed'),
'count' => self::filter('unconfirmed')->count() 'count' => self::filter(self::STATUS_UNCONFIRMED)->count()
), ),
array( array(
'name' => 'unsubscribed', 'name' => self::STATUS_UNSUBSCRIBED,
'label' => __('Unsubscribed'), 'label' => __('Unsubscribed'),
'count' => self::filter('unsubscribed')->count() 'count' => self::filter(self::STATUS_UNSUBSCRIBED)->count()
), ),
array( array(
'name' => 'trash', 'name' => 'trash',
@ -413,21 +516,23 @@ class Subscriber extends Model {
static function bulkConfirmUnconfirmed($orm) { static function bulkConfirmUnconfirmed($orm) {
$subscribers = $orm->findResultSet(); $subscribers = $orm->findResultSet();
$subscribers->set('status', 'subscribed')->save(); $subscribers->set('status', self::STATUS_SUBSCRIBED)->save();
return $subscribers->count(); return $subscribers->count();
} }
static function bulkResendConfirmationEmail($orm) { static function bulkSendConfirmationEmail($orm) {
$subscribers = $orm $subscribers = $orm
->where('status', 'unconfirmed') ->where('status', self::STATUS_UNCONFIRMED)
->findResultSet(); ->findMany();
$emails_sent = 0;
if(!empty($subscribers)) { if(!empty($subscribers)) {
foreach($subscribers as $subscriber) { foreach($subscribers as $subscriber) {
$subscriber->sendConfirmationEmail(); if($subscriber->sendConfirmationEmail()) {
$emails_sent++;
} }
}
return $subscribers->count(); return $emails_sent;
} }
return false; return false;
} }
@ -468,19 +573,19 @@ class Subscriber extends Model {
static function subscribed($orm) { static function subscribed($orm) {
return $orm return $orm
->whereNull('deleted_at') ->whereNull('deleted_at')
->where('status', 'subscribed'); ->where('status', self::STATUS_SUBSCRIBED);
} }
static function unsubscribed($orm) { static function unsubscribed($orm) {
return $orm return $orm
->whereNull('deleted_at') ->whereNull('deleted_at')
->where('status', 'unsubscribed'); ->where('status', self::STATUS_UNSUBSCRIBED);
} }
static function unconfirmed($orm) { static function unconfirmed($orm) {
return $orm return $orm
->whereNull('deleted_at') ->whereNull('deleted_at')
->where('status', 'unconfirmed'); ->where('status', self::STATUS_UNCONFIRMED);
} }
static function withoutSegments($orm) { static function withoutSegments($orm) {

View File

@ -1,6 +1,7 @@
<?php <?php
namespace MailPoet\Router; namespace MailPoet\Router;
use \MailPoet\Util\Security; use \MailPoet\Util\Security;
use \MailPoet\Models\Subscriber;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
@ -17,6 +18,7 @@ class Router {
'wp_ajax_mailpoet', 'wp_ajax_mailpoet',
array($this, 'setup') array($this, 'setup')
); );
$this->setupPublic();
} }
function setup() { function setup() {
@ -36,6 +38,84 @@ class Router {
} }
} }
function setupPublic() {
if(isset($_GET['mailpoet_page'])) {
$mailpoet_page = $_GET['mailpoet_page'];
add_filter('wp_title', array($this,'setWindowTitle'));
add_filter('the_title', array($this,'setPageTitle'));
add_filter('the_content', array($this,'setPageContent'));
}
}
function setWindowTitle() {
}
function setPageTitle($title) {
$action = (isset($_GET['mailpoet_action']))
? $_GET['mailpoet_action']
: null;
switch($action) {
case 'confirm':
$token = (isset($_GET['mailpoet_token']))
? $_GET['mailpoet_token']
: null;
$email = (isset($_GET['mailpoet_email']))
? $_GET['mailpoet_email']
: null;
if(empty($token) || empty($token)) {
$title = sprintf(
__("You've subscribed to: %s"),
'demo'
);
} else {
// check token validity
if(md5(AUTH_KEY.$email) !== $token) {
$title = __('Your confirmation link expired, please subscribe again.');
} else {
$subscriber = Subscriber::findOne($email);
if($subscriber !== false) {
if($subscriber->status !== Subscriber::STATUS_SUBSCRIBED) {
$subscriber->status = Subscriber::STATUS_SUBSCRIBED;
$subscriber->save();
}
$segments = $subscriber->segments()->findMany();
$segment_names = array_map(function($segment) {
return $segment->name;
}, $segments);
$title = sprintf(
__("You've subscribed to: %s"),
join(', ', $segment_names)
);
}
}
}
break;
case 'manage':
// TODO
break;
case 'unsubscribe':
// TODO
break;
}
return $title;
}
function setPageContent($content) {
return __(
"Yup, we've added you to our list. ".
"You'll hear from us shortly."
);
}
function setToken() { function setToken() {
$global = '<script type="text/javascript">'; $global = '<script type="text/javascript">';
$global .= 'var mailpoet_token = "'.Security::generateToken().'";'; $global .= 'var mailpoet_token = "'.Security::generateToken().'";';

View File

@ -16,10 +16,10 @@ class Pages {
'show_ui' => true, 'show_ui' => true,
'show_in_menu' => false, 'show_in_menu' => false,
'rewrite' => false, 'rewrite' => false,
'show_in_nav_menus'=>false, 'show_in_nav_menus' => false,
'can_export'=>false, 'can_export' => false,
'publicly_queryable'=>true, 'publicly_queryable' => true,
'exclude_from_search'=>true 'exclude_from_search' => true
)); ));
} }

View File

@ -163,7 +163,7 @@
<% for page in pages %> <% for page in pages %>
<option <option
value="<%= page.id %>" value="<%= page.id %>"
data-preview-url="<%= page.preview_url|raw %>" data-preview-url="<%= page.preview_url|raw %>&amp;mailpoet_action=confirm"
data-edit-url="<%= page.edit_url|raw %>" data-edit-url="<%= page.edit_url|raw %>"
<% if(page.id == settings.signup_confirmation.page) %> <% if(page.id == settings.signup_confirmation.page) %>
selected="selected" selected="selected"