diff --git a/assets/js/src/segments/list.jsx b/assets/js/src/segments/list.jsx
index bb3f39ad97..65a9ea5a12 100644
--- a/assets/js/src/segments/list.jsx
+++ b/assets/js/src/segments/list.jsx
@@ -28,6 +28,10 @@ var columns = [
name: 'unsubscribed',
label: MailPoet.I18n.t('unsubscribed')
},
+ {
+ name: 'bounced',
+ label: MailPoet.I18n.t('bounced')
+ },
{
name: 'created_at',
label: MailPoet.I18n.t('createdOn'),
@@ -192,6 +196,7 @@ const SegmentList = React.createClass({
const subscribed = ~~(segment.subscribers_count.subscribed || 0);
const unconfirmed = ~~(segment.subscribers_count.unconfirmed || 0);
const unsubscribed = ~~(segment.subscribers_count.unsubscribed || 0);
+ const bounced = ~~(segment.subscribers_count.bounced || 0);
let segment_name;
@@ -229,6 +234,9 @@ const SegmentList = React.createClass({
{ unsubscribed.toLocaleString() }
|
+
+ { bounced.toLocaleString() }
+ |
{ MailPoet.Date.format(segment.created_at) }
|
diff --git a/assets/js/src/subscribers/form.jsx b/assets/js/src/subscribers/form.jsx
index 78d504ccc8..cdccd7e310 100644
--- a/assets/js/src/subscribers/form.jsx
+++ b/assets/js/src/subscribers/form.jsx
@@ -45,7 +45,8 @@ define(
values: {
'subscribed': MailPoet.I18n.t('subscribed'),
'unconfirmed': MailPoet.I18n.t('unconfirmed'),
- 'unsubscribed': MailPoet.I18n.t('unsubscribed')
+ 'unsubscribed': MailPoet.I18n.t('unsubscribed'),
+ 'bounced': MailPoet.I18n.t('bounced')
},
filter: function(subscriber, value) {
if (~~(subscriber.wp_user_id) > 0 && value === 'unconfirmed') {
diff --git a/assets/js/src/subscribers/list.jsx b/assets/js/src/subscribers/list.jsx
index 4dc09ca7d8..11f756b8b6 100644
--- a/assets/js/src/subscribers/list.jsx
+++ b/assets/js/src/subscribers/list.jsx
@@ -255,6 +255,10 @@ const SubscriberList = React.createClass({
case 'unsubscribed':
status = MailPoet.I18n.t('unsubscribed');
break;
+
+ case 'bounced':
+ status = MailPoet.I18n.t('bounced');
+ break;
}
let segments = false;
diff --git a/lib/Models/Segment.php b/lib/Models/Segment.php
index 6f3752746c..a336d68279 100644
--- a/lib/Models/Segment.php
+++ b/lib/Models/Segment.php
@@ -87,6 +87,10 @@ class Segment extends Model {
'SUM(CASE subscribers.status WHEN "' . Subscriber::STATUS_UNCONFIRMED . '" THEN 1 ELSE 0 END)',
Subscriber::STATUS_UNCONFIRMED
)
+ ->select_expr(
+ 'SUM(CASE subscribers.status WHEN "' . Subscriber::STATUS_BOUNCED . '" THEN 1 ELSE 0 END)',
+ Subscriber::STATUS_BOUNCED
+ )
->findOne()
->asArray();
diff --git a/lib/Models/Subscriber.php b/lib/Models/Subscriber.php
index 82b2311422..cc5e076619 100644
--- a/lib/Models/Subscriber.php
+++ b/lib/Models/Subscriber.php
@@ -13,6 +13,7 @@ class Subscriber extends Model {
const STATUS_SUBSCRIBED = 'subscribed';
const STATUS_UNSUBSCRIBED = 'unsubscribed';
const STATUS_UNCONFIRMED = 'unconfirmed';
+ const STATUS_BOUNCED = 'bounced';
const SUBSCRIPTION_LIMIT_COOLDOWN = 60;
@@ -335,6 +336,11 @@ class Subscriber extends Model {
'label' => __('Unsubscribed', 'mailpoet'),
'count' => self::filter(self::STATUS_UNSUBSCRIBED)->count()
),
+ array(
+ 'name' => self::STATUS_BOUNCED,
+ 'label' => __('Bounced', 'mailpoet'),
+ 'count' => self::filter(self::STATUS_BOUNCED)->count()
+ ),
array(
'name' => 'trash',
'label' => __('Trash', 'mailpoet'),
@@ -720,6 +726,12 @@ class Subscriber extends Model {
->where('status', self::STATUS_UNCONFIRMED);
}
+ static function bounced($orm) {
+ return $orm
+ ->whereNull('deleted_at')
+ ->where('status', self::STATUS_BOUNCED);
+ }
+
static function withoutSegments($orm) {
return $orm->select(MP_SUBSCRIBERS_TABLE.'.*')
->leftOuterJoin(
diff --git a/lib/Subscribers/ImportExport/Import/Import.php b/lib/Subscribers/ImportExport/Import/Import.php
index 459b1d4868..0d1fe00314 100644
--- a/lib/Subscribers/ImportExport/Import/Import.php
+++ b/lib/Subscribers/ImportExport/Import/Import.php
@@ -302,18 +302,24 @@ class Import {
-1,
'-1',
'false'
+ ),
+ 'bounced' => array(
+ 'bounced'
)
);
$subscribers_data['status'] = array_map(function($state) use ($statuses) {
- if(in_array(strtolower($state), $statuses['subscribed'])) {
+ if(in_array(strtolower($state), $statuses['subscribed'], true)) {
return 'subscribed';
}
- if(in_array(strtolower($state), $statuses['unsubscribed'])) {
+ if(in_array(strtolower($state), $statuses['unsubscribed'], true)) {
return 'unsubscribed';
}
- if(in_array(strtolower($state), $statuses['unconfirmed'])) {
+ if(in_array(strtolower($state), $statuses['unconfirmed'], true)) {
return 'unconfirmed';
}
+ if(in_array(strtolower($state), $statuses['bounced'], true)) {
+ return 'bounced';
+ }
return 'subscribed'; // make "subscribed" a default status
}, $subscribers_data['status']);
return array(
diff --git a/lib/Subscription/Pages.php b/lib/Subscription/Pages.php
index 6497e0f720..f5c4072b45 100644
--- a/lib/Subscription/Pages.php
+++ b/lib/Subscription/Pages.php
@@ -290,6 +290,14 @@ class Pages {
'is_checked' => (
$subscriber->status === Subscriber::STATUS_UNSUBSCRIBED
)
+ ),
+ array(
+ 'value' => array(
+ Subscriber::STATUS_BOUNCED => __('Bounced', 'mailpoet')
+ ),
+ 'is_checked' => (
+ $subscriber->status === Subscriber::STATUS_BOUNCED
+ )
)
)
)
diff --git a/testItHasGroupFilter b/testItHasGroupFilter
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/unit/Helpscout/BeaconTest.php b/tests/unit/Helpscout/BeaconTest.php
index e57c815749..4663856bb7 100644
--- a/tests/unit/Helpscout/BeaconTest.php
+++ b/tests/unit/Helpscout/BeaconTest.php
@@ -5,7 +5,7 @@ use \MailPoet\Models\Subscriber;
class BeaconTest extends MailPoetTest {
function _before() {
- // create 3 users (1 confirmed, 1 subscribed, 1 unsubscribed)
+ // create 4 users (1 confirmed, 1 subscribed, 1 unsubscribed, 1 bounced)
Subscriber::createOrUpdate(array(
'email' => 'user1@mailpoet.com',
'status' => Subscriber::STATUS_SUBSCRIBED
@@ -18,6 +18,10 @@ class BeaconTest extends MailPoetTest {
'email' => 'user3@mailpoet.com',
'status' => Subscriber::STATUS_UNSUBSCRIBED
));
+ Subscriber::createOrUpdate(array(
+ 'email' => 'user4@mailpoet.com',
+ 'status' => Subscriber::STATUS_BOUNCED
+ ));
$this->beacon_data = Beacon::getData();
}
diff --git a/tests/unit/Models/SubscriberTest.php b/tests/unit/Models/SubscriberTest.php
index 84437e8f19..a8dd944aef 100644
--- a/tests/unit/Models/SubscriberTest.php
+++ b/tests/unit/Models/SubscriberTest.php
@@ -114,16 +114,30 @@ class SubscriberTest extends MailPoetTest {
foreach($subscribers as $subscriber) {
expect($subscriber->status)->equals(Subscriber::STATUS_UNCONFIRMED);
}
+
+ $this->subscriber->status = Subscriber::STATUS_SUBSCRIBED;
+ $this->subscriber->save();
$subscribers = Subscriber::filter('groupBy', Subscriber::STATUS_SUBSCRIBED)
->findMany();
foreach($subscribers as $subscriber) {
expect($subscriber->status)->equals(Subscriber::STATUS_SUBSCRIBED);
}
+
+ $this->subscriber->status = Subscriber::STATUS_UNSUBSCRIBED;
+ $this->subscriber->save();
$subscribers = Subscriber::filter('groupBy', Subscriber::STATUS_UNSUBSCRIBED)
->findMany();
foreach($subscribers as $subscriber) {
expect($subscriber->status)->equals(Subscriber::STATUS_UNSUBSCRIBED);
}
+
+ $this->subscriber->status = Subscriber::STATUS_BOUNCED;
+ $this->subscriber->save();
+ $subscribers = Subscriber::filter('groupBy', Subscriber::STATUS_BOUNCED)
+ ->findMany();
+ foreach($subscribers as $subscriber) {
+ expect($subscriber->status)->equals(Subscriber::STATUS_BOUNCED);
+ }
}
function testItCanHaveSegment() {
@@ -507,6 +521,11 @@ class SubscriberTest extends MailPoetTest {
'deleted_at' => Carbon::now()->toDateTimeString()
));
+ $subscriber_5 = Subscriber::createOrUpdate(array(
+ 'email' => 'subscriber_5@mailpoet.com',
+ 'status' => Subscriber::STATUS_BOUNCED
+ ));
+
// counts only subscribed & unconfirmed users
$total = Subscriber::getTotalSubscribers();
expect($total)->equals(2);
diff --git a/tests/unit/Newsletter/ShortcodesTest.php b/tests/unit/Newsletter/ShortcodesTest.php
index 4b19a42881..4590d1479f 100644
--- a/tests/unit/Newsletter/ShortcodesTest.php
+++ b/tests/unit/Newsletter/ShortcodesTest.php
@@ -153,7 +153,12 @@ class ShortcodesTest extends MailPoetTest {
$this->subscriber->save();
$result =
$shortcodes_object->process(array('[subscriber:count]'));
- expect($result[0])->equals(--$subscriber_count);
+ expect($result[0])->equals($subscriber_count - 1);
+ $this->subscriber->status = 'bounced';
+ $this->subscriber->save();
+ $result =
+ $shortcodes_object->process(array('[subscriber:count]'));
+ expect($result[0])->equals($subscriber_count - 1);
}
function testItCanProcessSubscriberCustomFieldShortcodes() {
diff --git a/tests/unit/Subscribers/ImportExport/Import/ImportTest.php b/tests/unit/Subscribers/ImportExport/Import/ImportTest.php
index adf783c92c..f73f360304 100644
--- a/tests/unit/Subscribers/ImportExport/Import/ImportTest.php
+++ b/tests/unit/Subscribers/ImportExport/Import/ImportTest.php
@@ -186,7 +186,12 @@ class ImportTest extends MailPoetTest {
'unsubscribed',
-1,
'-1',
- 'false'
+ 'false',
+ #bounced
+ 'bounced',
+ #unexpected
+ 'qwerty',
+ null
),
);
list($subscribers_data, $subsciber_fields) =
@@ -205,7 +210,10 @@ class ImportTest extends MailPoetTest {
'unsubscribed',
'unsubscribed',
'unsubscribed',
- 'unsubscribed'
+ 'unsubscribed',
+ 'bounced',
+ 'subscribed',
+ 'subscribed'
)
)
);
diff --git a/views/segments.html b/views/segments.html
index 585e216c3d..f36fca4dc8 100644
--- a/views/segments.html
+++ b/views/segments.html
@@ -30,6 +30,7 @@
'subscribed': __('Subscribed'),
'unconfirmed': __('Unconfirmed'),
'unsubscribed': __('Unsubscribed'),
+ 'bounced': __('Bounced'),
'createdOn': __('Created on'),
'oneSegmentTrashed': __('1 list was moved to the trash'),
'multipleSegmentsTrashed': __('%$1d lists were moved to the trash'),
diff --git a/views/subscribers/subscribers.html b/views/subscribers/subscribers.html
index 9f570a5202..f85b22c523 100644
--- a/views/subscribers/subscribers.html
+++ b/views/subscribers/subscribers.html
@@ -50,6 +50,7 @@
'unconfirmed': __('Unconfirmed'),
'subscribed': __('Subscribed'),
'unsubscribed': __('Unsubscribed'),
+ 'bounced': __('Bounced'),
'selectList': __('Select a list'),
'unsubscribedOn': __('Unsubscribed on %$1s'),
'subscriberUpdated': __('Subscriber was updated successfully!'),