From 1af242c2ddb5b358eb30888625e9f46a3f21f87b Mon Sep 17 00:00:00 2001 From: Amine Ben hammou Date: Thu, 15 Mar 2018 17:56:10 +0100 Subject: [PATCH] adding subscribers getter from dynamic segments --- .../Export/DefaultSubscribersGetter.php | 70 ++++-------------- .../Export/DynamicSubscribersGetter.php | 65 ++++++++++++++++ .../ImportExport/Export/Export.php | 9 +++ .../ImportExport/Export/SubscribersGetter.php | 74 +++++++++++++++++++ .../ImportExport/ImportExportFactory.php | 16 ++-- 5 files changed, 170 insertions(+), 64 deletions(-) create mode 100644 lib/Subscribers/ImportExport/Export/DynamicSubscribersGetter.php create mode 100644 lib/Subscribers/ImportExport/Export/SubscribersGetter.php diff --git a/lib/Subscribers/ImportExport/Export/DefaultSubscribersGetter.php b/lib/Subscribers/ImportExport/Export/DefaultSubscribersGetter.php index f1ced0f08c..2a455d781f 100644 --- a/lib/Subscribers/ImportExport/Export/DefaultSubscribersGetter.php +++ b/lib/Subscribers/ImportExport/Export/DefaultSubscribersGetter.php @@ -9,63 +9,25 @@ use MailPoet\Models\SubscriberSegment; /** * Gets batches of subscribers from default segments. */ -class DefaultSubscribersGetter { +class DefaultSubscribersGetter extends SubscribersGetter { - protected $segments_ids; - protected $batch_size; - protected $offset; - protected $finished; + /** + * @var bool + */ protected $get_subscribers_without_segment; public function __construct($segments_ids, $batch_size) { + parent::__construct($segments_ids, $batch_size); $this->get_subscribers_without_segment = (array_search(0, $segments_ids) !== false); - $this->segments_ids = $this->filterSegmentIds($segments_ids); - $this->batch_size = $batch_size; - $this->reset(); } - protected function filterSegmentIds($ids) { - $ids = array_map(function($data) { - return $data['id']; - }, Segment::select('id') - ->whereIn('id', $ids) - ->where('type', Segment::TYPE_DEFAULT) - ->findArray() - ); - if($this->get_subscribers_without_segment) { - $ids[] = 0; - } - return $ids; - } - - public function reset() { - $this->offset = 0; - $this->finished = false; - } - - /** - * Gets the next batch of subscribers or `false` if no more! - */ - public function get() { - if($this->finished) { - return false; - } - // define returned columns - $subscribers = Subscriber::selectMany( - 'first_name', - 'last_name', - 'email', - 'subscribed_ip', - array( - 'global_status' => Subscriber::$_table . '.status' - ), - array( - 'list_status' => SubscriberSegment::$_table . '.status' + protected function filter($subscribers) { + $subscribers = $subscribers + ->selectMany( + array( + 'list_status' => SubscriberSegment::$_table . '.status' + ) ) - ); - - // JOIN subscribers on segment and subscriber_segment tables - $subscribers = $subscribers ->left_outer_join( SubscriberSegment::$_table, array( @@ -82,7 +44,6 @@ class DefaultSubscribersGetter { SubscriberSegment::$_table . '.segment_id' ) ) - ->filter('filterWithCustomFieldsForExport') ->groupBy(Subscriber::$_table . '.id') ->groupBy(Segment::$_table . '.id'); @@ -107,18 +68,13 @@ class DefaultSubscribersGetter { ->selectExpr('MAX(' . Segment::$_table . '.name) as segment_name') ->whereIn(SubscriberSegment::$_table . '.segment_id', $this->segments_ids); } + $subscribers = $subscribers - ->whereNull(Subscriber::$_table . '.deleted_at') ->offset($this->offset) ->limit($this->batch_size) ->findArray(); - $this->offset += $this->batch_size; - - if(count($subscribers) < $this->batch_size) { - $this->finished = true; - } - return $subscribers; } + } \ No newline at end of file diff --git a/lib/Subscribers/ImportExport/Export/DynamicSubscribersGetter.php b/lib/Subscribers/ImportExport/Export/DynamicSubscribersGetter.php new file mode 100644 index 0000000000..0f8d479d1b --- /dev/null +++ b/lib/Subscribers/ImportExport/Export/DynamicSubscribersGetter.php @@ -0,0 +1,65 @@ +segment_index = 0; + } + + protected function filter($subscribers) { + $segment_id = $this->segments_ids[$this->segment_index]; + + $filters = Hooks::applyFilters( + 'mailpoet_add_segment_filters', + $segment_id + ); + + if(!is_array($filters) || empty($filters)) { + return array(); + } + + $name = Segment::findOne($segment_id)->name; + + foreach($filters as $filter) { + $subscribers = $filter->toSql($subscribers); + } + + return $subscribers + ->selectMany(array( + 'list_status' => Subscriber::$_table . '.status' + )) + ->selectExpr("'{$name}' AS segment_name") + ->offset($this->offset) + ->limit($this->batch_size) + ->findArray(); + } + + public function get() { + if($this->segment_index >= count($this->segments_ids)) { + $this->finished = true; + } + + $subscribers = parent::get(); + + if($subscribers !== false && count($subscribers) < $this->batch_size) { + $this->segment_index ++; + $this->offset = 0; + $this->finished = false; + } + + return $subscribers; + } + +} \ No newline at end of file diff --git a/lib/Subscribers/ImportExport/Export/Export.php b/lib/Subscribers/ImportExport/Export/Export.php index 3aed895498..86416bd1b9 100644 --- a/lib/Subscribers/ImportExport/Export/Export.php +++ b/lib/Subscribers/ImportExport/Export/Export.php @@ -23,6 +23,7 @@ class Export { public $export_file; public $export_file_URL; public $default_subscribers_getter; + public $dynamic_subscribers_getter; public function __construct($data) { if(strpos(@ini_get('disable_functions'), 'set_time_limit') === false) { @@ -34,6 +35,11 @@ class Export { self::SUBSCRIBER_BATCH_SIZE ); + $this->dynamic_subscribers_getter = new DynamicSubscribersGetter( + $data['segments'], + self::SUBSCRIBER_BATCH_SIZE + ); + $this->export_format_option = $data['export_format_option']; $this->subscriber_fields = $data['subscriber_fields']; $this->subscriber_custom_fields = $this->getSubscriberCustomFields(); @@ -162,6 +168,9 @@ class Export { function getSubscribers() { $subscribers = $this->default_subscribers_getter->get(); + if($subscribers === false) { + $subscribers = $this->dynamic_subscribers_getter->get(); + } return $subscribers; } diff --git a/lib/Subscribers/ImportExport/Export/SubscribersGetter.php b/lib/Subscribers/ImportExport/Export/SubscribersGetter.php new file mode 100644 index 0000000000..d49274d1a2 --- /dev/null +++ b/lib/Subscribers/ImportExport/Export/SubscribersGetter.php @@ -0,0 +1,74 @@ +segments_ids = $segments_ids; + $this->batch_size = $batch_size; + $this->reset(); + } + + public function reset() { + $this->offset = 0; + $this->finished = false; + } + + /** + * Initialize the query by selecting fields and ignoring trashed subscribers. + * + * @return \ORM + */ + protected function select() { + return Subscriber::selectMany( + 'first_name', + 'last_name', + 'email', + 'subscribed_ip', + array( + 'global_status' => Subscriber::$_table . '.status' + ) + ) + ->filter('filterWithCustomFieldsForExport') + ->whereNull(Subscriber::$_table . '.deleted_at'); + } + + /** + * Filters the subscribers query based on the segments, offset and batch size. + * + * @param \ORM $subscribers + * @return array + */ + abstract protected function filter($subscribers); + + /** + * Gets the next batch of subscribers or `false` if no more! + */ + public function get() { + if($this->finished) { + return false; + } + + $subscribers = $this->select(); + $subscribers = $this->filter($subscribers); + + $this->offset += $this->batch_size; + + if(count($subscribers) < $this->batch_size) { + $this->finished = true; + } + + return $subscribers; + } +} \ No newline at end of file diff --git a/lib/Subscribers/ImportExport/ImportExportFactory.php b/lib/Subscribers/ImportExport/ImportExportFactory.php index 143a4f82a0..9fc51d565f 100644 --- a/lib/Subscribers/ImportExport/ImportExportFactory.php +++ b/lib/Subscribers/ImportExport/ImportExportFactory.php @@ -18,13 +18,15 @@ class ImportExportFactory { } function getSegments($with_confirmed_subscribers = false) { - $segments = ($this->action === self::IMPORT_ACTION) ? - Segment::getSegmentsForImport() : - Segment::getSegmentsForExport($with_confirmed_subscribers); - $segments = Hooks::applyFilters('mailpoet_segments_with_subscriber_count', $segments); - $segments = array_values(array_filter($segments, function($segment) { - return $segment['subscribers'] > 0; - })); + if($this->action === self::IMPORT_ACTION) { + $segments = Segment::getSegmentsForImport(); + } else { + $segments = Segment::getSegmentsForExport($with_confirmed_subscribers); + $segments = Hooks::applyFilters('mailpoet_segments_with_subscriber_count', $segments); + $segments = array_values(array_filter($segments, function($segment) { + return $segment['subscribers'] > 0; + })); + } return array_map(function($segment) { if(!$segment['name']) $segment['name'] = __('Not In List', 'mailpoet');