diff --git a/lib/API/JSON/v1/Subscribers.php b/lib/API/JSON/v1/Subscribers.php index 7fde90d968..70cc04ae7f 100644 --- a/lib/API/JSON/v1/Subscribers.php +++ b/lib/API/JSON/v1/Subscribers.php @@ -12,6 +12,7 @@ use MailPoet\Models\Setting; use MailPoet\Models\StatisticsForms; use MailPoet\Models\Subscriber; use MailPoet\Newsletter\Scheduler\Scheduler; +use MailPoet\Segments\BulkAction; use MailPoet\Segments\SubscribersListings; use MailPoet\Subscription\Throttling as SubscriptionThrottling; use MailPoet\WP\Hooks; @@ -246,12 +247,12 @@ class Subscribers extends APIEndpoint { function bulkAction($data = array()) { try { - $bulk_action = new Listing\BulkAction( - '\MailPoet\Models\Subscriber', - $data - ); - $meta = $bulk_action->apply(); - return $this->successResponse(null, $meta); + if(!isset($data['listing']['filter']['segment'])) { + $bulk_action = new Listing\BulkAction('\MailPoet\Models\Subscriber', $data); + } else { + $bulk_action = new BulkAction($data); + } + return $this->successResponse(null, $bulk_action->apply()); } catch(\Exception $e) { return $this->errorResponse(array( $e->getCode() => $e->getMessage() diff --git a/lib/Models/Model.php b/lib/Models/Model.php index c9082c0bf2..d066307e4b 100644 --- a/lib/Models/Model.php +++ b/lib/Models/Model.php @@ -184,7 +184,7 @@ class Model extends \Sudzy\ValidModel { return (int)$model['id']; }, $rows); - if($callback !== false) { + if(is_callable($callback)) { $callback($ids); } diff --git a/lib/Segments/BulkAction.php b/lib/Segments/BulkAction.php new file mode 100644 index 0000000000..65ecf9927a --- /dev/null +++ b/lib/Segments/BulkAction.php @@ -0,0 +1,57 @@ +data = $data; + } + + /** + * @return array + * @throws \Exception + */ + function apply() { + if(!isset($this->data['listing']['filter']['segment'])) { + throw new \InvalidArgumentException('Missing segment id'); + } + $segment = Segment::findOne($this->data['listing']['filter']['segment']); + if($segment) { + $segment = $segment->asArray(); + } + return $this->applySegment($segment); + } + + /** + * @param array $segment + * + * @return array + * @throws \Exception + */ + private function applySegment($segment) { + if(!$segment || $segment['type'] === Segment::TYPE_DEFAULT || $segment['type'] === Segment::TYPE_WP_USERS) { + $bulk_action = new \MailPoet\Listing\BulkAction( + '\MailPoet\Models\Subscriber', + $this->data + ); + + return $bulk_action->apply(); + } else { + $handlers = Hooks::applyFilters('mailpoet_subscribers_in_segment_apply_bulk_action_handlers', array()); + foreach($handlers as $handler) { + $meta = $handler->apply($segment, $this->data); + if($meta) { + return $meta; + } + } + throw new \InvalidArgumentException('No handler found for segment'); + } + } + +} \ No newline at end of file diff --git a/tests/unit/Segments/BulkActionTest.php b/tests/unit/Segments/BulkActionTest.php new file mode 100644 index 0000000000..2dc570c648 --- /dev/null +++ b/tests/unit/Segments/BulkActionTest.php @@ -0,0 +1,105 @@ +cleanData(); + $this->segment_1 = Segment::createOrUpdate(array('name' => 'Segment 1', 'type' => 'default')); + $this->segment_2 = Segment::createOrUpdate(array('name' => 'Segment 3', 'type' => 'not default')); + $this->subscriber_1 = Subscriber::createOrUpdate(array( + 'email' => 'john@mailpoet.com', + 'first_name' => 'John', + 'last_name' => 'Doe', + 'status' => Subscriber::STATUS_SUBSCRIBED, + 'segments' => array( + $this->segment_1->id, + ), + )); + $this->subscriber_2 = Subscriber::createOrUpdate(array( + 'email' => 'jake@mailpoet.com', + 'first_name' => 'Jake', + 'last_name' => 'Doe', + 'status' => Subscriber::STATUS_SUBSCRIBED, + 'segments' => array( + $this->segment_2->id, + ), + )); + SubscriberSegment::resubscribeToAllSegments($this->subscriber_1); + SubscriberSegment::resubscribeToAllSegments($this->subscriber_2); + } + + function _after() { + $this->cleanData(); + } + + private function cleanData() { + \ORM::raw_execute('TRUNCATE ' . Segment::$_table); + \ORM::raw_execute('TRUNCATE ' . SubscriberSegment::$_table); + \ORM::raw_execute('TRUNCATE ' . Subscriber::$_table); + } + + function testBulkActionWithoutSegment() { + $handler = new BulkAction(array()); + $this->setExpectedException('InvalidArgumentException'); + $handler->apply(); + } + + function testBulkActionForDefaultSegment() { + $handler = new BulkAction(array( + 'listing' => array('filter'=> array('segment' => $this->segment_1->id)), + 'action' => 'trash', + )); + $result = $handler->apply(); + expect($result['count'])->equals(1); + } + + function testBulkActionForUnknownSegment() { + $handler = new BulkAction(array( + 'listing' => array('filter'=> array('segment' => 'this-segment-doesnt-exist')), + 'action' => 'trash', + )); + $result = $handler->apply(); + expect($result)->notEmpty(); + } + + function testForUnknownSegmentTypeWithoutHandler() { + $handler = new BulkAction(array( + 'listing' => array('filter'=> array('segment' => $this->segment_2->id)), + 'action' => 'trash', + )); + $this->setExpectedException('InvalidArgumentException'); + remove_all_filters('mailpoet_subscribers_in_segment_apply_bulk_action_handlers'); + $handler->apply(); + } + + function testBulkActionUsingFilter() { + $mock = Stub::makeEmpty('\MailPoet\Test\Segments\SubscribersBulkActionHandlerMock', array('apply')); + $mock + ->expects($this->once()) + ->method('apply') + ->will($this->returnValue('result')); + + remove_all_filters('mailpoet_subscribers_in_segment_apply_bulk_action_handlers'); + Hooks::addFilter('mailpoet_subscribers_in_segment_apply_bulk_action_handlers', function () use ($mock) { + return array($mock); + }); + + $handler = new BulkAction(array( + 'listing' => array('filter'=> array('segment' => $this->segment_2->id)), + 'action' => 'trash', + )); + $result = $handler->apply(); + expect($result)->equals('result'); + } + +} diff --git a/tests/unit/Segments/SubscribersBulkActionHandlerMock.php b/tests/unit/Segments/SubscribersBulkActionHandlerMock.php new file mode 100644 index 0000000000..7a659c10eb --- /dev/null +++ b/tests/unit/Segments/SubscribersBulkActionHandlerMock.php @@ -0,0 +1,11 @@ +