- Adds subsription tracking option to Settings->Advanced

- Updates sending queue worker to not replace links if tracking is
  disabled
Closes #417
This commit is contained in:
Vlad
2016-04-13 22:00:13 -04:00
parent a3e6eb5bba
commit 84294b7ee6
5 changed files with 112 additions and 29 deletions

View File

@@ -76,14 +76,19 @@ class SendingQueue {
if($queue->newsletter_rendered_body === null) { if($queue->newsletter_rendered_body === null) {
// render newsletter // render newsletter
$rendered_newsletter = $this->renderNewsletter($newsletter); $rendered_newsletter = $this->renderNewsletter($newsletter);
// extract and replace links if((int) Setting::getValue('tracking.enabled') === 1) {
$processed_newsletter = $this->processLinks( // extract and replace links
$this->joinObject($rendered_newsletter), $processed_newsletter = $this->processLinks(
$newsletter['id'], $this->joinObject($rendered_newsletter),
$queue->id $newsletter['id'],
); $queue->id
list($newsletter['body']['html'], $newsletter['body']['text']) = );
$this->splitObject($processed_newsletter); list($newsletter['body']['html'], $newsletter['body']['text']) =
$this->splitObject($processed_newsletter);
}
else {
$newsletter['body'] = $rendered_newsletter;
}
$queue->newsletter_rendered_body = json_encode($newsletter['body']); $queue->newsletter_rendered_body = json_encode($newsletter['body']);
$queue->newsletter_rendered_body_hash = md5($newsletter['body']['text']); $queue->newsletter_rendered_body_hash = md5($newsletter['body']['text']);
$queue->save(); $queue->save();
@@ -200,12 +205,14 @@ class SendingQueue {
$subscriber, $subscriber,
$this->joinObject($data_for_shortcodes) $this->joinObject($data_for_shortcodes)
); );
$processed_newsletter = $this->replaceLinks( if((int) Setting::getValue('tracking.enabled') === 1) {
$newsletter['id'], $processed_newsletter = $this->replaceLinks(
$subscriber['id'], $newsletter['id'],
$queue->id, $subscriber['id'],
$processed_newsletter $queue->id,
); $processed_newsletter
);
}
list($newsletter['subject'], list($newsletter['subject'],
$newsletter['body']['html'], $newsletter['body']['html'],
$newsletter['body']['text'] $newsletter['body']['text']

View File

@@ -1,5 +1,6 @@
<?php <?php
namespace MailPoet\Newsletter\Shortcodes\Categories; namespace MailPoet\Newsletter\Shortcodes\Categories;
use MailPoet\Models\Setting;
use MailPoet\Subscription\Url as SubscriptionUrl; use MailPoet\Subscription\Url as SubscriptionUrl;
class Subscription { class Subscription {
@@ -21,23 +22,35 @@ class Subscription {
) { ) {
switch($action) { switch($action) {
case 'unsubscribe': case 'unsubscribe':
return '<a target="_blank" href="'. return '<a target="_blank" href="['.
esc_attr(SubscriptionUrl::getUnsubscribeUrl($subscriber)) self::processUrl(
$action,
esc_attr(SubscriptionUrl::getUnsubscribeUrl($subscriber))
)
.'">'.__('Unsubscribe').'</a>'; .'">'.__('Unsubscribe').'</a>';
break; break;
case 'unsubscribe_url': case 'unsubscribe_url':
return SubscriptionUrl::getUnsubscribeUrl($subscriber); return self::processUrl(
$action,
SubscriptionUrl::getUnsubscribeUrl($subscriber)
);
break; break;
case 'manage': case 'manage':
return '<a target="_blank" href="'. return '<a target="_blank" href="'.
esc_attr(SubscriptionUrl::getManageUrl($subscriber)) self::processUrl(
$action,
esc_attr(SubscriptionUrl::getManageUrl($subscriber))
)
.'">'.__('Manage subscription').'</a>'; .'">'.__('Manage subscription').'</a>';
break; break;
case 'manage_url': case 'manage_url':
return SubscriptionUrl::getManageUrl($subscriber); return self::processUrl(
$action,
SubscriptionUrl::getManageUrl($subscriber)
);
break; break;
default: default:
@@ -45,4 +58,11 @@ class Subscription {
break; break;
} }
} }
static function processUrl($action, $url) {
if((int) Setting::getValue('tracking.enabled') === 1) {
return sprintf('[subscription:%s]', $action);
}
return $url;
}
} }

View File

@@ -18,18 +18,21 @@ class Shortcodes {
return array_unique($shortcodes[0]); return array_unique($shortcodes[0]);
} }
function match($shortcode) {
preg_match(
'/\[(?P<type>\w+):(?P<action>\w+)(?:.*?default:(?P<default>.*?))?\]/',
$shortcode,
$match
);
return $match;
}
function process($shortcodes, $text) { function process($shortcodes, $text) {
$processed_shortcodes = array_map( $processed_shortcodes = array_map(
function($shortcode) use($text) { function($shortcode) use($text) {
preg_match( $shortcode_details = $this->match($shortcode);
'/\[(?P<type>\w+):(?P<action>\w+)(?:.*?default:(?P<default>.*?))?\]/',
$shortcode,
$shortcode_details
);
$shortcode_type = ucfirst($shortcode_details['type']); $shortcode_type = ucfirst($shortcode_details['type']);
$shortcode_action = $shortcode_details['action']; $shortcode_action = $shortcode_details['action'];
// do not process subscription management links
if ($shortcode_type === 'Subscription') return $shortcode;
$shortcode_class = $shortcode_class =
__NAMESPACE__ . '\\Categories\\' . $shortcode_type; __NAMESPACE__ . '\\Categories\\' . $shortcode_type;
$shortcode_default_value = isset($shortcode_details['default']) $shortcode_default_value = isset($shortcode_details['default'])

View File

@@ -3,6 +3,8 @@ namespace MailPoet\Statistics\Track;
use MailPoet\Models\NewsletterLink; use MailPoet\Models\NewsletterLink;
use MailPoet\Models\StatisticsClicks; use MailPoet\Models\StatisticsClicks;
use MailPoet\Models\Subscriber;
use MailPoet\Subscription\Url as SubscriptionUrl;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
@@ -17,8 +19,10 @@ class Clicks {
$url = ($url) ? $url : $this->url; $url = ($url) ? $url : $this->url;
if(!preg_match('/\d+-\d+-\d+-[a-zA-Z0-9]/', $url)) $this->abort(); if(!preg_match('/\d+-\d+-\d+-[a-zA-Z0-9]/', $url)) $this->abort();
list ($newsletter_id, $subscriber_id, $queue_id, $hash) = explode('-', $url); list ($newsletter_id, $subscriber_id, $queue_id, $hash) = explode('-', $url);
$link = NewsletterLink::where('hash', $hash)->findOne(); $subscriber = Subscriber::findOne($subscriber_id);
if(!$link) $this->abort(); $link = NewsletterLink::where('hash', $hash)
->findOne();
if(!$link || !$subscriber) $this->abort();
$statistics = StatisticsClicks::where('link_id', $link->id) $statistics = StatisticsClicks::where('link_id', $link->id)
->where('subscriber_id', $subscriber_id) ->where('subscriber_id', $subscriber_id)
->where('newsletter_id', $newsletter_id) ->where('newsletter_id', $newsletter_id)
@@ -36,7 +40,23 @@ class Clicks {
$statistics->count = (int) $statistics->count++; $statistics->count = (int) $statistics->count++;
$statistics->save(); $statistics->save();
} }
header('Location: ' . $link->url, true, 301); $url = (preg_match('/\[subscription:.*?\]/', $link->url)) ?
$this->processSubscriptionUrl($link->url, $subscriber) :
$link->url;
header('Location: ' . $url, true, 302);
}
function processSubscriptionUrl($url, $subscriber) {
preg_match('/\[subscription:(.*?)\]/', $url, $match);
$action = $match[1];
if(preg_match('/unsubscribe/', $action)) {
$url = SubscriptionUrl::getUnsubscribeUrl($subscriber);
}
if(preg_match('/manage/', $action)) {
$url = SubscriptionUrl::getManageUrl($subscriber);
}
!ddd($url);
return $url;
} }
private function abort() { private function abort() {

View File

@@ -61,6 +61,39 @@
</p> </p>
</td> </td>
</tr> </tr>
<!-- link tracking -->
<tr>
<th scope="row">
<label>
<%= __('Open and click tracking') %>
<p class="description"><%= __('Some users prefer not to track their subscribers.') %></p>
</th>
<td>
<p>
<label>
<input
type="radio"
name="tracking[enabled]"
value="1"
<% if(settings.tracking.enabled) %>
checked="checked"
<% endif %>
/><%= __('Yes') %>
</label>
&nbsp;
<label>
<input
type="radio"
name="tracking[enabled]"
value=""
<% if not(settings.tracking.enabled) %>
checked="checked"
<% endif %>
/><%= __('No') %>
</label>
</p>
</td>
</tr>
<!-- share anonymous data? --> <!-- share anonymous data? -->
<tr> <tr>
<th scope="row"> <th scope="row">