From c4ddb38d18a390ce41f4675e4b9a8f88dbb4eb2c Mon Sep 17 00:00:00 2001 From: Jonathan Labreuille Date: Fri, 20 May 2016 16:58:02 +0200 Subject: [PATCH] Prevent WP users from being trashed/deleted - return actual rowCount of affected rows for bulk actions (based on PDO last statement) - prevent removal of WP Users segment relationship with subscribers. --- lib/Models/Model.php | 3 +- lib/Models/Subscriber.php | 95 +++++++++++++++++++++----------- lib/Models/SubscriberSegment.php | 20 +++++-- 3 files changed, 82 insertions(+), 36 deletions(-) diff --git a/lib/Models/Model.php b/lib/Models/Model.php index a89e6a27a9..9d484277e7 100644 --- a/lib/Models/Model.php +++ b/lib/Models/Model.php @@ -124,7 +124,8 @@ class Model extends \Sudzy\ValidModel { } } - return $total; + $last_statement = $orm->get_last_statement(); + return $last_statement->rowCount(); } function duplicate($data = array()) { diff --git a/lib/Models/Subscriber.php b/lib/Models/Subscriber.php index 9aad226a5a..80551eb0ab 100644 --- a/lib/Models/Subscriber.php +++ b/lib/Models/Subscriber.php @@ -42,10 +42,24 @@ class Subscriber extends Model { } function delete() { - // delete all relations to segments - SubscriberSegment::where('subscriber_id', $this->id)->deleteMany(); + // WP Users cannot be deleted + if($this->wp_user_id !== null) { + return false; + } else { + // delete all relations to segments + SubscriberSegment::where('subscriber_id', $this->id)->deleteMany(); - return parent::delete(); + return parent::delete(); + } + } + + function trash() { + // WP Users cannot be trashed + if($this->wp_user_id !== null) { + return false; + } else { + return parent::trash(); + } } function sendConfirmationEmail() { @@ -203,7 +217,7 @@ class Subscriber extends Model { ); $segment_list[] = array( - 'label' => str_replace(' (0)', '', $subscribers_without_segment_label), + 'label' => $subscribers_without_segment_label, 'value' => 'none' ); @@ -212,9 +226,14 @@ class Subscriber extends Model { ->filter('groupBy', $group) ->count(); - $label = sprintf('%s (%s)', $segment->name, number_format($subscribers_count)); + $label = sprintf( + '%s (%s)', + $segment->name, + number_format($subscribers_count) + ); + $segment_list[] = array( - 'label' => str_replace(' (0)', '', $label), + 'label' => $label, 'value' => $segment->id() ); } @@ -520,23 +539,18 @@ class Subscriber extends Model { } static function bulkRemoveFromAllLists($orm) { - $segments = Segment::findMany(); - $segment_ids = array_map(function($segment) { - return $segment->id(); - }, $segments); - - if(!empty($segment_ids)) { - // delete relations with segment - $subscribers = $orm->findResultSet(); - foreach($subscribers as $subscriber) { - SubscriberSegment::where('subscriber_id', $subscriber->id) - ->whereIn('segment_id', $segment_ids) - ->deleteMany(); + $subscribers = $orm->findResultSet(); + $subscribers_count = 0; + foreach($subscribers as $subscriber) { + try { + SubscriberSegment::removeSubscriptions($subscriber); + $subscribers_count++; + } catch(Exception $e) { + continue; } - - return $subscribers->count(); } - return false; + + return $subscribers_count; } static function bulkSendConfirmationEmail($orm) { @@ -564,12 +578,11 @@ class Subscriber extends Model { $subscribers_count = 0; $subscribers = $orm->findMany(); foreach($subscribers as $subscriber) { - // create relation with segment - $association = \MailPoet\Models\SubscriberSegment::create(); - $association->subscriber_id = $subscriber->id; - $association->segment_id = $segment->id; - if($association->save()) { + try { + SubscriberSegment::addSubscriptions($subscriber, array($segment->id)); $subscribers_count++; + } catch(Exception $e) { + continue; } } return array( @@ -580,12 +593,32 @@ class Subscriber extends Model { return false; } - static function bulkDelete($orm) { + static function bulkTrash($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(); + parent::rawExecute(join(' ', array( + 'UPDATE `'.self::$_table.'`', + 'SET `deleted_at`=NOW()', + 'WHERE `id` IN ('.rtrim(str_repeat('?,', count($ids)), ',').')', + 'AND `wp_user_id` IS NULL' + )), + $ids + ); + }); + } + + static function bulkDelete($orm) { + $wp_users_segment = Segment::getWPUsers(); + + return parent::bulkAction($orm, function($ids) use ($wp_users_segment) { + // delete subscribers' relations to segments (except WP Users' segment) + SubscriberSegment::whereIn('subscriber_id', $ids) + ->whereNotEqual('segment_id', $wp_users_segment->id) + ->deleteMany(); + + // delete subscribers (except WP Users) + Subscriber::whereIn('id', $ids) + ->whereNull('wp_user_id') + ->deleteMany(); }); } diff --git a/lib/Models/SubscriberSegment.php b/lib/Models/SubscriberSegment.php index 35653339f9..342e6702b4 100644 --- a/lib/Models/SubscriberSegment.php +++ b/lib/Models/SubscriberSegment.php @@ -17,10 +17,18 @@ class SubscriberSegment extends Model { } static function removeSubscriptions($subscriber, $segment_ids = array()) { + $wp_users_segment = Segment::getWPUsers(); + if($subscriber->id > 0) { if(!empty($segment_ids)) { - // subscribe to segments + // unsubscribe from segments foreach($segment_ids as $segment_id) { + + // do not remove subscriptions to the WP Users segment + if($wp_users_segment->id === (int)$segment_id) { + continue; + } + if((int)$segment_id > 0) { self::createOrUpdate(array( 'subscriber_id' => $subscriber->id, @@ -29,9 +37,11 @@ class SubscriberSegment extends Model { )); } } + return true; } else { - // unsubscribe from all segments - SubscriberSegment::where('subscriber_id', $subscriber->id) + // unsubscribe from all segments (except the WP users segment) + return SubscriberSegment::where('subscriber_id', $subscriber->id) + ->whereNotEqual('segment_id', $wp_users_segment->id) ->findResultSet() ->set('status', Subscriber::STATUS_UNSUBSCRIBED) ->save(); @@ -52,9 +62,11 @@ class SubscriberSegment extends Model { )); } } + + return true; } else { // subscribe to all segments - SubscriberSegment::where('subscriber_id', $subscriber->id) + return SubscriberSegment::where('subscriber_id', $subscriber->id) ->findResultSet() ->set('status', Subscriber::STATUS_SUBSCRIBED) ->save();