-
-
- { subscriber.email }
-
-
+
+ { subscriber.email }
+
{ actions }
|
@@ -195,7 +300,9 @@ define(
endpoint="subscribers"
onRenderItem={ this.renderItem }
columns={ columns }
- bulk_actions={ bulk_actions } />
+ bulk_actions={ bulk_actions }
+ messages={ messages }
+ />
);
}
diff --git a/composer.json b/composer.json
index 7091ac4db1..17d7aa0c89 100644
--- a/composer.json
+++ b/composer.json
@@ -16,7 +16,7 @@
"vlucas/phpdotenv": "*",
"umpirsky/twig-gettext-extractor": "1.1.*",
"raveren/kint": "^1.0"
- },
+ },
"autoload": {
"psr-4": {
"MailPoet\\": "lib/",
diff --git a/lib/Config/Migrator.php b/lib/Config/Migrator.php
index d115967702..5d1800a044 100644
--- a/lib/Config/Migrator.php
+++ b/lib/Config/Migrator.php
@@ -54,6 +54,7 @@ class Migrator {
'email varchar(150) NOT NULL,',
'status varchar(12) NOT NULL DEFAULT "unconfirmed",',
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
+ 'deleted_at TIMESTAMP NULL DEFAULT NULL,',
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
'PRIMARY KEY (id),',
'UNIQUE KEY email (email)'
@@ -82,6 +83,7 @@ class Migrator {
'preheader varchar(250) NOT NULL,',
'body longtext,',
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
+ 'deleted_at TIMESTAMP NULL DEFAULT NULL,',
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
'PRIMARY KEY (id)'
);
@@ -106,6 +108,7 @@ class Migrator {
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
'name varchar(90) NOT NULL,',
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
+ 'deleted_at TIMESTAMP NULL DEFAULT NULL,',
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
'PRIMARY KEY (id),',
'UNIQUE KEY name (name)'
@@ -170,8 +173,7 @@ class Migrator {
'newsletter_type varchar(90) NOT NULL,',
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
- 'PRIMARY KEY (id),',
- 'UNIQUE KEY name_newsletter_type (newsletter_type, name)'
+ 'PRIMARY KEY (id)'
);
return $this->sqlify(__FUNCTION__, $attributes);
}
diff --git a/lib/Listing/Handler.php b/lib/Listing/Handler.php
index 3ddc97b835..dd56636b38 100644
--- a/lib/Listing/Handler.php
+++ b/lib/Listing/Handler.php
@@ -71,10 +71,17 @@ class Handler {
return $this->model;
}
+ function count() {
+ return (int)$this->model->count();
+ }
+
function getSelectionIds() {
- $models = $this->getSelection()->select('id')->findMany();
+ $models = $this->getSelection()
+ ->select('id')
+ ->findArray();
+
return array_map(function($model) {
- return (int)$model->id;
+ return (int)$model['id'];
}, $models);
}
diff --git a/lib/Models/Subscriber.php b/lib/Models/Subscriber.php
index fc986ddfe4..a498148438 100644
--- a/lib/Models/Subscriber.php
+++ b/lib/Models/Subscriber.php
@@ -69,18 +69,8 @@ class Subscriber extends Model {
foreach($filters as $filter) {
if($filter['name'] === 'segment') {
-
$segment = Segment::findOne($filter['value']);
if($segment !== false) {
- /*$orm = $orm
- ->select(MP_SUBSCRIBERS_TABLE.'.*')
- ->select('subscriber_segment.id', 'subscriber_segment_id')
- ->join(
- MP_SUBSCRIBER_SEGMENT_TABLE,
- MP_SUBSCRIBERS_TABLE.'.id = subscriber_segment.subscriber_id',
- 'subscriber_segment'
- )
- ->where('subscriber_segment.segment_id', (int)$filter['value']);*/
$orm = $segment->subscribers();
}
}
@@ -93,35 +83,47 @@ class Subscriber extends Model {
array(
'name' => 'all',
'label' => __('All'),
- 'count' => Subscriber::count()
+ 'count' => Subscriber::whereNull('deleted_at')->count()
),
array(
'name' => 'subscribed',
'label' => __('Subscribed'),
- 'count' => Subscriber::where('status', 'subscribed')->count()
+ 'count' => Subscriber::whereNull('deleted_at')
+ ->where('status', 'subscribed')
+ ->count()
),
array(
'name' => 'unconfirmed',
'label' => __('Unconfirmed'),
- 'count' => Subscriber::where('status', 'unconfirmed')->count()
+ 'count' => Subscriber::whereNull('deleted_at')
+ ->where('status', 'unconfirmed')
+ ->count()
),
array(
'name' => 'unsubscribed',
'label' => __('Unsubscribed'),
- 'count' => Subscriber::where('status', 'unsubscribed')->count()
+ 'count' => Subscriber::whereNull('deleted_at')
+ ->where('status', 'unsubscribed')
+ ->count()
+ ),
+ array(
+ 'name' => 'trash',
+ 'label' => __('Trash'),
+ 'count' => Subscriber::whereNotNull('deleted_at')->count()
)
);
}
static function groupBy($orm, $group = null) {
- if($group === null or !in_array(
- $group,
- array('subscribed', 'unconfirmed', 'unsubscribed')
- )) {
- return $orm;
- }
+ if($group === 'trash') {
+ return $orm->whereNotNull('deleted_at');
+ } else {
+ $orm = $orm->whereNull('deleted_at');
- return $orm->where('status', $group);
+ if(in_array($group, array('subscribed', 'unsubscribed', 'unconfirmed'))) {
+ return $orm->where('status', $group);
+ }
+ }
}
static function filterWithCustomFields($orm) {
@@ -197,6 +199,7 @@ class Subscriber extends Model {
$segment = Segment::findOne($segment_id);
if($segment !== false) {
+ $subscribers_count = 0;
$subscribers = $listing->getSelection()->findMany();
foreach($subscribers as $subscriber) {
// remove subscriber from all segments
@@ -207,8 +210,13 @@ class Subscriber extends Model {
$association->subscriber_id = $subscriber->id;
$association->segment_id = $segment->id;
$association->save();
+
+ $subscribers_count++;
}
- return true;
+ return array(
+ 'subscribers' => $subscribers_count,
+ 'segment' => $segment->name
+ );
}
return false;
}
@@ -223,6 +231,67 @@ class Subscriber extends Model {
SubscriberSegment::whereIn('subscriber_id', $subscriber_ids)
->where('segment_id', $segment->id)
->deleteMany();
+
+ return array(
+ 'subscribers' => count($subscriber_ids),
+ 'segment' => $segment->name
+ );
+ }
+ return false;
+ }
+
+ static function removeFromAllLists($listing) {
+ $segments = Segment::findMany();
+ $segment_ids = array_map(function($segment) {
+ return $segment->id();
+ }, $segments);
+
+ if(!empty($segment_ids)) {
+ // delete relations with segment
+ $subscriber_ids = $listing->getSelectionIds();
+ SubscriberSegment::whereIn('subscriber_id', $subscriber_ids)
+ ->whereIn('segment_id', $segment_ids)
+ ->deleteMany();
+
+ return array(
+ 'subscribers' => count($subscriber_ids)
+ );
+ }
+ return false;
+ }
+
+ static function confirmUnconfirmed($listing) {
+ $subscriber_ids = $listing->getSelectionIds();
+ $subscribers = Subscriber::whereIn('id', $subscriber_ids)
+ ->where('status', 'unconfirmed')
+ ->findMany();
+
+ if(!empty($subscribers)) {
+ $subscribers_count = 0;
+ foreach($subscribers as $subscriber) {
+ $subscriber->set('status', 'subscribed');
+ if($subscriber->save() === true) {
+ $subscribers_count++;
+ }
+ }
+
+ return array(
+ 'subscribers' => $subscribers_count
+ );
+ }
+ return false;
+ }
+
+ static function resendConfirmationEmail($listing) {
+ $subscriber_ids = $listing->getSelectionIds();
+ $subscribers = Subscriber::whereIn('id', $subscriber_ids)
+ ->where('status', 'unconfirmed')
+ ->findMany();
+
+ if(!empty($subscribers)) {
+ foreach($subscribers as $subscriber) {
+ // TODO: resend confirmation email
+ }
return true;
}
return false;
@@ -233,24 +302,64 @@ class Subscriber extends Model {
$segment = Segment::findOne($segment_id);
if($segment !== false) {
+ $subscribers_count = 0;
$subscribers = $listing->getSelection()->findMany();
foreach($subscribers as $subscriber) {
// create relation with segment
$association = \MailPoet\Models\SubscriberSegment::create();
$association->subscriber_id = $subscriber->id;
$association->segment_id = $segment->id;
- $association->save();
+ if($association->save()) {
+ $subscribers_count++;
+ }
}
- return true;
+ return array(
+ 'subscribers' => $subscribers_count,
+ 'segment' => $segment->name
+ );
}
return false;
}
- static function trash($listing) {
- // delete relations with all segments
- $subscriber_ids = $listing->getSelectionIds();
- \MailPoet\Models\SubscriberSegment::whereIn('subscriber_id', $subscriber_ids)->deleteMany();
+ static function trash($listing, $data = array()) {
+ $confirm_delete = filter_var($data['confirm'], FILTER_VALIDATE_BOOLEAN);
+ if($confirm_delete) {
+ // delete relations with all segments
+ $subscribers = $listing->getSelection()->findResultSet();
- return $listing->getSelection()->deleteMany();
+ if(!empty($subscribers)) {
+ $subscribers_count = 0;
+ foreach($subscribers as $subscriber) {
+ if($subscriber->delete()) {
+ $subscribers_count++;
+ }
+ }
+ return array(
+ 'subscribers' => $subscribers_count
+ );
+ }
+ return false;
+ } else {
+ // soft delete
+ $subscribers = $listing->getSelection()
+ ->findResultSet()
+ ->set_expr('deleted_at', 'NOW()')
+ ->save();
+
+ return array(
+ 'subscribers' => $subscribers->count()
+ );
+ }
+ }
+
+ static function restore($listing, $data = array()) {
+ $subscribers = $listing->getSelection()
+ ->findResultSet()
+ ->set_expr('deleted_at', 'NULL')
+ ->save();
+
+ return array(
+ 'subscribers' => $subscribers->count()
+ );
}
}
\ No newline at end of file
diff --git a/lib/Router/Subscribers.php b/lib/Router/Subscribers.php
index bce5d3f453..1649e77a61 100644
--- a/lib/Router/Subscribers.php
+++ b/lib/Router/Subscribers.php
@@ -53,10 +53,28 @@ class Subscribers {
wp_send_json($result);
}
- function delete($id) {
+ function restore($id) {
$subscriber = Subscriber::findOne($id);
if($subscriber !== false) {
- $result = $subscriber->delete();
+ $subscriber->set_expr('deleted_at', 'NULL');
+ $result = array('subscribers' => (int)$subscriber->save());
+ } else {
+ $result = false;
+ }
+ wp_send_json($result);
+ }
+
+ function delete($data = array()) {
+ $subscriber = Subscriber::findOne($data['id']);
+ $confirm_delete = filter_var($data['confirm'], FILTER_VALIDATE_BOOLEAN);
+ if($subscriber !== false) {
+ if($confirm_delete) {
+ $subscriber->delete();
+ $result = array('subscribers' => 1);
+ } else {
+ $subscriber->set_expr('deleted_at', 'NOW()');
+ $result = array('subscribers' => (int)$subscriber->save());
+ }
} else {
$result = false;
}
diff --git a/views/layout.html b/views/layout.html
index a4b521a283..ee5d6dde41 100644
--- a/views/layout.html
+++ b/views/layout.html
@@ -1,10 +1,10 @@
-
+
-
-
+
+
<% block title %><% endblock %>
diff --git a/views/settings.html b/views/settings.html
index e937f47724..baa835afdf 100644
--- a/views/settings.html
+++ b/views/settings.html
@@ -47,7 +47,7 @@
<% include 'settings/bounce.html' %>
-
+
|