diff --git a/assets/js/src/subscribers/list.jsx b/assets/js/src/subscribers/list.jsx index 2c2a1dfbd3..9993b4fd0c 100644 --- a/assets/js/src/subscribers/list.jsx +++ b/assets/js/src/subscribers/list.jsx @@ -313,6 +313,7 @@ const SubscriberList = React.createClass({ 'SET NAMES utf8', \PDO::MYSQL_ATTR_INIT_COMMAND => 'SET TIME_ZONE = "+00:00"' diff --git a/lib/Config/Menu.php b/lib/Config/Menu.php index 79c6c1c0d5..642fdc20c4 100644 --- a/lib/Config/Menu.php +++ b/lib/Config/Menu.php @@ -67,7 +67,7 @@ class Menu { 'forms' ) ); - add_submenu_page( + $hook_subscribers_page = add_submenu_page( 'mailpoet', __('Subscribers'), __('Subscribers'), @@ -182,6 +182,17 @@ class Menu { 'cron' ) ); + + add_action('load-'.$hook_subscribers_page, function() { + add_screen_option('per_page', array( + 'label' => _x( + 'Number of subscribers per page', + 'subscribers per page (screen options)' + ), + 'default' => 10, + 'option' => 'mailpoet_subscribers_per_page' + )); + }); } function home() { @@ -305,6 +316,13 @@ class Menu { function subscribers() { $data = array(); + // listing: limit per page + $data['per_page'] = get_user_meta( + get_current_user_id(), + 'mailpoet_subscribers_per_page', + true + ); + $data['segments'] = Segment::findArray(); $data['custom_fields'] = array_map(function($field) { diff --git a/lib/Models/Model.php b/lib/Models/Model.php index a18f14f273..4116532158 100644 --- a/lib/Models/Model.php +++ b/lib/Models/Model.php @@ -5,6 +5,7 @@ if(!defined('ABSPATH')) exit; class Model extends \Sudzy\ValidModel { protected $_errors; + const BULK_ACTION_BATCH_SIZE = 1000; function __construct() { $this->_errors = array(); @@ -70,19 +71,23 @@ class Model extends \Sudzy\ValidModel { } static function bulkTrash($orm) { - $models = $orm->findResultSet(); - $models->set_expr('deleted_at', 'NOW()')->save(); - return $models->count(); + $model = get_called_class(); + return self::bulkAction($orm, function($ids) use($model) { + self::rawExecute(join(' ', array( + 'UPDATE `'.$model::$_table.'`', + 'SET `deleted_at`=NOW()', + 'WHERE `id` IN ('.rtrim(str_repeat('?,', count($ids)), ',').')' + )), + $ids + ); + }); } static function bulkDelete($orm) { - $models = $orm->findMany(); - $count = 0; - foreach($models as $model) { - $model->delete(); - $count++; - } - return $count; + $model = get_called_class(); + return self::bulkAction($orm, function($ids) use($model) { + $model::whereIn('id', $ids)->deleteMany(); + }); } function restore() { @@ -90,9 +95,35 @@ class Model extends \Sudzy\ValidModel { } static function bulkRestore($orm) { - $models = $orm->findResultSet(); - $models->set_expr('deleted_at', 'NULL')->save(); - return $models->count(); + $model = get_called_class(); + return self::bulkAction($orm, function($ids) use($model) { + self::rawExecute(join(' ', array( + 'UPDATE `'.$model::$_table.'`', + 'SET `deleted_at`=NULL', + 'WHERE `id` IN ('.rtrim(str_repeat('?,', count($ids)), ',').')' + )), + $ids + ); + }); + } + + static function bulkAction($orm, $callback = false) { + $total = $orm->count(); + + $models = $orm->select('id') + ->offset(null) + ->limit(null) + ->findArray(); + + $ids = array_map(function($model) { + return (int)$model['id']; + }, $models); + + if(is_callable($callback)) { + $callback($ids); + } + + return $total; } function duplicate($data = array()) { diff --git a/lib/Models/Subscriber.php b/lib/Models/Subscriber.php index 722b0d3a24..cc70fd4199 100644 --- a/lib/Models/Subscriber.php +++ b/lib/Models/Subscriber.php @@ -411,7 +411,6 @@ class Subscriber extends Model { } static function bulkAddToList($orm, $data = array()) { - $segment_id = (isset($data['segment_id']) ? (int)$data['segment_id'] : 0); $segment = Segment::findOne($segment_id); @@ -435,6 +434,15 @@ class Subscriber extends Model { return false; } + static function bulkDelete($orm) { + return parent::bulkAction($orm, function($ids) { + // delete subscribers + Subscriber::whereIn('id', $ids)->deleteMany(); + // delete subscribers' relations to segments + SubscriberSegment::whereIn('subscriber_id', $ids)->deleteMany(); + }); + } + static function subscribed($orm) { return $orm ->whereNull('deleted_at') diff --git a/views/forms.html b/views/forms.html index 9cf6f2b4f2..840fa75ba0 100644 --- a/views/forms.html +++ b/views/forms.html @@ -8,12 +8,15 @@ 'searchLabel': __('Search'), 'loadingItems': __('Loading forms...'), 'noItemsFound': __('No forms found.'), + 'selectAllLabel': __('All forms on this page are selected.'), + 'selectedAllLabel': __('All %d forms are selected.'), + 'selectAllLink': __('Select all forms on all pages.'), + 'clearSelection': __('Clear selection.'), 'permanentlyDeleted': __('%d forms permanently deleted.') }) %> diff --git a/views/newsletters.html b/views/newsletters.html index 7959edc042..65cae54eec 100644 --- a/views/newsletters.html +++ b/views/newsletters.html @@ -10,7 +10,7 @@ 'noItemsFound': __('No newsletters found.'), 'selectAllLabel': __('All newsletters on this page are selected.'), 'selectedAllLabel': __('All %d newsletters are selected.'), - 'selectAllLink': __('Select all pages.'), + 'selectAllLink': __('Select all newsletters on all pages.'), 'clearSelection': __('Clear selection.'), 'permanentlyDeleted': __('%d newsletters permanently deleted.') }) %> diff --git a/views/subscribers/subscribers.html b/views/subscribers/subscribers.html index f2ccbc72be..143ddbf2ad 100644 --- a/views/subscribers/subscribers.html +++ b/views/subscribers/subscribers.html @@ -10,12 +10,13 @@ 'noItemsFound': __('No subscribers found.'), 'selectAllLabel': __('All subscribers on this page are selected.'), 'selectedAllLabel': __('All %d subscribers are selected.'), - 'selectAllLink': __('Select all pages.'), + 'selectAllLink': __('Select all subscribers on all pages.'), 'clearSelection': __('Clear selection.'), 'permanentlyDeleted': __('%d subscribers permanently deleted.') }) %>