Subscribers page review

- added screen option to set number of items per page
- improved bulk actions in order to handle large sets
This commit is contained in:
Jonathan Labreuille
2016-02-12 18:57:17 +01:00
parent 97adfc14c0
commit 8139a7dd0a
9 changed files with 94 additions and 20 deletions

View File

@ -313,6 +313,7 @@ const SubscriberList = React.createClass({
</h2> </h2>
<Listing <Listing
limit={ mailpoet_listing_per_page }
location={ this.props.location } location={ this.props.location }
params={ this.props.params } params={ this.props.params }
endpoint="subscribers" endpoint="subscribers"

View File

@ -7,8 +7,13 @@ class Hooks {
} }
function init() { function init() {
$subscribe = Setting::getValue('subscribe', array());
// Subscribe in comments // Subscribe in comments
if((bool)Setting::getValue('subscribe.on_comment.enabled')) { if(
isset($subscribe['on_comment']['enabled'])
&&
(bool)$subscribe['on_comment']['enabled']
) {
if(is_user_logged_in()) { if(is_user_logged_in()) {
add_action( add_action(
'comment_form_field_comment', 'comment_form_field_comment',
@ -37,7 +42,11 @@ class Hooks {
} }
// Subscribe in registration form // Subscribe in registration form
if((bool)Setting::getValue('subscribe.on_register.enabled')) { if(
isset($subscribe['on_register']['enabled'])
&&
(bool)$subscribe['on_register']['enabled']
) {
if(is_multisite()) { if(is_multisite()) {
add_action( add_action(
'signup_extra_fields', 'signup_extra_fields',

View File

@ -56,6 +56,9 @@ class Initializer {
\ORM::configure('username', Env::$db_username); \ORM::configure('username', Env::$db_username);
\ORM::configure('password', Env::$db_password); \ORM::configure('password', Env::$db_password);
\ORM::configure('logging', WP_DEBUG); \ORM::configure('logging', WP_DEBUG);
\ORM::configure('logger', function($query, $time) {
error_log($query);
});
\ORM::configure('driver_options', array( \ORM::configure('driver_options', array(
\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', \PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET TIME_ZONE = "+00:00"' \PDO::MYSQL_ATTR_INIT_COMMAND => 'SET TIME_ZONE = "+00:00"'

View File

@ -67,7 +67,7 @@ class Menu {
'forms' 'forms'
) )
); );
add_submenu_page( $hook_subscribers_page = add_submenu_page(
'mailpoet', 'mailpoet',
__('Subscribers'), __('Subscribers'),
__('Subscribers'), __('Subscribers'),
@ -182,6 +182,17 @@ class Menu {
'cron' '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() { function home() {
@ -305,6 +316,13 @@ class Menu {
function subscribers() { function subscribers() {
$data = array(); $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['segments'] = Segment::findArray();
$data['custom_fields'] = array_map(function($field) { $data['custom_fields'] = array_map(function($field) {

View File

@ -5,6 +5,7 @@ if(!defined('ABSPATH')) exit;
class Model extends \Sudzy\ValidModel { class Model extends \Sudzy\ValidModel {
protected $_errors; protected $_errors;
const BULK_ACTION_BATCH_SIZE = 1000;
function __construct() { function __construct() {
$this->_errors = array(); $this->_errors = array();
@ -70,19 +71,23 @@ class Model extends \Sudzy\ValidModel {
} }
static function bulkTrash($orm) { static function bulkTrash($orm) {
$models = $orm->findResultSet(); $model = get_called_class();
$models->set_expr('deleted_at', 'NOW()')->save(); return self::bulkAction($orm, function($ids) use($model) {
return $models->count(); self::rawExecute(join(' ', array(
'UPDATE `'.$model::$_table.'`',
'SET `deleted_at`=NOW()',
'WHERE `id` IN ('.rtrim(str_repeat('?,', count($ids)), ',').')'
)),
$ids
);
});
} }
static function bulkDelete($orm) { static function bulkDelete($orm) {
$models = $orm->findMany(); $model = get_called_class();
$count = 0; return self::bulkAction($orm, function($ids) use($model) {
foreach($models as $model) { $model::whereIn('id', $ids)->deleteMany();
$model->delete(); });
$count++;
}
return $count;
} }
function restore() { function restore() {
@ -90,9 +95,35 @@ class Model extends \Sudzy\ValidModel {
} }
static function bulkRestore($orm) { static function bulkRestore($orm) {
$models = $orm->findResultSet(); $model = get_called_class();
$models->set_expr('deleted_at', 'NULL')->save(); return self::bulkAction($orm, function($ids) use($model) {
return $models->count(); 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()) { function duplicate($data = array()) {

View File

@ -411,7 +411,6 @@ class Subscriber extends Model {
} }
static function bulkAddToList($orm, $data = array()) { static function bulkAddToList($orm, $data = array()) {
$segment_id = (isset($data['segment_id']) ? (int)$data['segment_id'] : 0); $segment_id = (isset($data['segment_id']) ? (int)$data['segment_id'] : 0);
$segment = Segment::findOne($segment_id); $segment = Segment::findOne($segment_id);
@ -435,6 +434,15 @@ class Subscriber extends Model {
return false; 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) { static function subscribed($orm) {
return $orm return $orm
->whereNull('deleted_at') ->whereNull('deleted_at')

View File

@ -8,12 +8,15 @@
'searchLabel': __('Search'), 'searchLabel': __('Search'),
'loadingItems': __('Loading forms...'), 'loadingItems': __('Loading forms...'),
'noItemsFound': __('No forms found.'), '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.') 'permanentlyDeleted': __('%d forms permanently deleted.')
}) %> }) %>
<script type="text/javascript"> <script type="text/javascript">
var mailpoet_segments = <%= json_encode(segments) %>; var mailpoet_segments = <%= json_encode(segments) %>;
var mailpoet_form_edit_url = var mailpoet_form_edit_url =
"<%= admin_url('admin.php?page=mailpoet-form-editor&id=') %>"; "<%= admin_url('admin.php?page=mailpoet-form-editor&id=') %>";
</script> </script>

View File

@ -10,7 +10,7 @@
'noItemsFound': __('No newsletters found.'), 'noItemsFound': __('No newsletters found.'),
'selectAllLabel': __('All newsletters on this page are selected.'), 'selectAllLabel': __('All newsletters on this page are selected.'),
'selectedAllLabel': __('All %d newsletters are selected.'), 'selectedAllLabel': __('All %d newsletters are selected.'),
'selectAllLink': __('Select all pages.'), 'selectAllLink': __('Select all newsletters on all pages.'),
'clearSelection': __('Clear selection.'), 'clearSelection': __('Clear selection.'),
'permanentlyDeleted': __('%d newsletters permanently deleted.') 'permanentlyDeleted': __('%d newsletters permanently deleted.')
}) %> }) %>

View File

@ -10,12 +10,13 @@
'noItemsFound': __('No subscribers found.'), 'noItemsFound': __('No subscribers found.'),
'selectAllLabel': __('All subscribers on this page are selected.'), 'selectAllLabel': __('All subscribers on this page are selected.'),
'selectedAllLabel': __('All %d subscribers are selected.'), 'selectedAllLabel': __('All %d subscribers are selected.'),
'selectAllLink': __('Select all pages.'), 'selectAllLink': __('Select all subscribers on all pages.'),
'clearSelection': __('Clear selection.'), 'clearSelection': __('Clear selection.'),
'permanentlyDeleted': __('%d subscribers permanently deleted.') 'permanentlyDeleted': __('%d subscribers permanently deleted.')
}) %> }) %>
<script type="text/javascript"> <script type="text/javascript">
var mailpoet_listing_per_page = <%= per_page %>;
var mailpoet_segments = <%= json_encode(segments) %>; var mailpoet_segments = <%= json_encode(segments) %>;
var mailpoet_custom_fields = <%= json_encode(custom_fields) %>; var mailpoet_custom_fields = <%= json_encode(custom_fields) %>;
var mailpoet_month_names = <%= json_encode(month_names) %>; var mailpoet_month_names = <%= json_encode(month_names) %>;