Merge pull request #1353 from mailpoet/subscriber-source
Subscriber source [MAILPOET-1377]
This commit is contained in:
@@ -14,6 +14,7 @@ use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Newsletter\Scheduler\Scheduler;
|
||||
use MailPoet\Segments\BulkAction;
|
||||
use MailPoet\Segments\SubscribersListings;
|
||||
use MailPoet\Subscribers\Source;
|
||||
use MailPoet\Subscription\Throttling as SubscriptionThrottling;
|
||||
use MailPoet\WP\Hooks;
|
||||
|
||||
@@ -191,6 +192,11 @@ class Subscribers extends APIEndpoint {
|
||||
return $this->badRequest($errors);
|
||||
}
|
||||
|
||||
if($subscriber->isNew()) {
|
||||
$subscriber = Source::setSource($subscriber, Source::ADMINISTRATOR);
|
||||
$subscriber->save();
|
||||
}
|
||||
|
||||
if(!empty($data['segments'])) {
|
||||
Scheduler::scheduleSubscriberWelcomeNotification($subscriber->id, $data['segments']);
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ use MailPoet\Models\Segment;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Models\SubscriberSegment;
|
||||
use MailPoet\Newsletter\Scheduler\Scheduler;
|
||||
use MailPoet\Subscribers\Source;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
@@ -165,6 +166,7 @@ class API {
|
||||
// add subscriber
|
||||
$new_subscriber = Subscriber::create();
|
||||
$new_subscriber->hydrate($default_fields);
|
||||
$new_subscriber = Source::setSource($new_subscriber, Source::API);
|
||||
$new_subscriber->save();
|
||||
if($new_subscriber->getErrors() !== false) {
|
||||
throw new \Exception(
|
||||
|
@@ -171,6 +171,7 @@ class Migrator {
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'deleted_at TIMESTAMP NULL,',
|
||||
'unconfirmed_data longtext,',
|
||||
'source ENUM("form", "imported", "administrator", "api", "wordpress_user", "unknown") DEFAULT "unknown",',
|
||||
'PRIMARY KEY (id),',
|
||||
'UNIQUE KEY email (email),',
|
||||
'KEY wp_user_id (wp_user_id),',
|
||||
|
@@ -2,6 +2,7 @@
|
||||
namespace MailPoet\Models;
|
||||
use MailPoet\Mailer\Mailer;
|
||||
use MailPoet\Newsletter\Scheduler\Scheduler;
|
||||
use MailPoet\Subscribers\Source;
|
||||
use MailPoet\Util\Helpers;
|
||||
use MailPoet\Subscription;
|
||||
|
||||
@@ -182,6 +183,8 @@ class Subscriber extends Model {
|
||||
// create new subscriber or update if no confirmation is required
|
||||
$subscriber = self::createOrUpdate($subscriber_data);
|
||||
if($subscriber->getErrors() !== false) {
|
||||
$subscriber = Source::setSource($subscriber, Source::FORM);
|
||||
$subscriber->save();
|
||||
return $subscriber;
|
||||
}
|
||||
|
||||
@@ -206,6 +209,8 @@ class Subscriber extends Model {
|
||||
}
|
||||
}
|
||||
|
||||
$subscriber = Source::setSource($subscriber, Source::FORM);
|
||||
|
||||
if($subscriber->save()) {
|
||||
// link subscriber to segments
|
||||
SubscriberSegment::subscribeToSegments($subscriber, $segment_ids);
|
||||
|
@@ -6,6 +6,7 @@ use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Models\SubscriberSegment;
|
||||
use MailPoet\Newsletter\Scheduler\Scheduler;
|
||||
use MailPoet\Subscribers\Source;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
@@ -50,12 +51,14 @@ class WP {
|
||||
'first_name' => $first_name,
|
||||
'last_name' => $last_name,
|
||||
'status' => Subscriber::STATUS_SUBSCRIBED,
|
||||
'source' => Source::WORDPRESS_USER,
|
||||
);
|
||||
|
||||
if($subscriber !== false) {
|
||||
$data['id'] = $subscriber->id();
|
||||
$data['deleted_at'] = null; // remove the user from the trash
|
||||
unset($data['status']); // don't override status for existing users
|
||||
unset($data['source']); // don't override status for existing users
|
||||
}
|
||||
|
||||
$subscriber = Subscriber::createOrUpdate($data);
|
||||
@@ -137,12 +140,12 @@ class WP {
|
||||
', $subscribers_table, $wpdb->users))->findArray();
|
||||
|
||||
Subscriber::raw_execute(sprintf('
|
||||
INSERT IGNORE INTO %1$s(wp_user_id, email, status, created_at)
|
||||
SELECT wu.id, wu.user_email, "subscribed", CURRENT_TIMESTAMP() FROM %2$s wu
|
||||
INSERT IGNORE INTO %1$s(wp_user_id, email, status, created_at, source)
|
||||
SELECT wu.id, wu.user_email, "subscribed", CURRENT_TIMESTAMP(), "%3$s" FROM %2$s wu
|
||||
LEFT JOIN %1$s mps ON wu.id = mps.wp_user_id
|
||||
WHERE mps.wp_user_id IS NULL AND wu.user_email != ""
|
||||
ON DUPLICATE KEY UPDATE wp_user_id = wu.id
|
||||
', $subscribers_table, $wpdb->users));
|
||||
', $subscribers_table, $wpdb->users, Source::WORDPRESS_USER));
|
||||
|
||||
return $inserterd_user_ids;
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@ use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Models\SubscriberCustomField;
|
||||
use MailPoet\Models\SubscriberSegment;
|
||||
use MailPoet\Subscribers\ImportExport\ImportExportFactory;
|
||||
use MailPoet\Subscribers\Source;
|
||||
use MailPoet\Util\Helpers;
|
||||
|
||||
class Import {
|
||||
@@ -108,6 +109,7 @@ class Import {
|
||||
// add, if required, missing required fields to new subscribers
|
||||
$new_subscribers = $this->addMissingRequiredFields($new_subscribers);
|
||||
$new_subscribers = $this->setSubscriptionStatusToSubscribed($new_subscribers);
|
||||
$new_subscribers = $this->setSource($new_subscribers);
|
||||
$created_subscribers =
|
||||
$this->createOrUpdateSubscribers(
|
||||
'create',
|
||||
@@ -286,6 +288,17 @@ class Import {
|
||||
return $subscribers_data;
|
||||
}
|
||||
|
||||
function setSource($subscribers_data) {
|
||||
$subscribers_count = count($subscribers_data['data'][key($subscribers_data['data'])]);
|
||||
$subscribers_data['fields'][] = 'source';
|
||||
$subscribers_data['data']['source'] = array_fill(
|
||||
0,
|
||||
$subscribers_count,
|
||||
Source::IMPORTED
|
||||
);
|
||||
return $subscribers_data;
|
||||
}
|
||||
|
||||
function getSubscribersFields($subscribers_fields) {
|
||||
return array_values(
|
||||
array_filter(
|
||||
|
37
lib/Subscribers/Source.php
Normal file
37
lib/Subscribers/Source.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace MailPoet\Subscribers;
|
||||
|
||||
use MailPoet\Models\Subscriber;
|
||||
|
||||
class Source {
|
||||
|
||||
const FORM = 'form';
|
||||
const IMPORTED = 'imported';
|
||||
const ADMINISTRATOR = 'administrator';
|
||||
const API = 'api';
|
||||
const WORDPRESS_USER = 'wordpress_user';
|
||||
const UNKNOWN = 'unknown';
|
||||
|
||||
private static $allowed_sources = array(
|
||||
Source::FORM,
|
||||
Source::IMPORTED,
|
||||
Source::ADMINISTRATOR,
|
||||
Source::API,
|
||||
Source::WORDPRESS_USER,
|
||||
Source::UNKNOWN,
|
||||
);
|
||||
|
||||
static function setSource(Subscriber $subscriber, $source) {
|
||||
if((isset($subscriber->source)) && ($subscriber->source !== Source::UNKNOWN)) {
|
||||
// we don't want to override source
|
||||
return $subscriber;
|
||||
}
|
||||
if(!in_array($source, Source::$allowed_sources)) {
|
||||
throw new \InvalidArgumentException('Invalid source "' . $source . '""');
|
||||
}
|
||||
$subscriber->set('source', $source);
|
||||
return $subscriber;
|
||||
}
|
||||
|
||||
}
|
@@ -16,6 +16,7 @@ use MailPoet\Models\SubscriberIP;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Models\SubscriberSegment;
|
||||
use MailPoet\Subscribers\Source;
|
||||
|
||||
class SubscribersTest extends \MailPoetTest {
|
||||
function _before() {
|
||||
@@ -29,7 +30,8 @@ class SubscribersTest extends \MailPoetTest {
|
||||
'email' => 'john@mailpoet.com',
|
||||
'first_name' => 'John',
|
||||
'last_name' => 'Doe',
|
||||
'status' => Subscriber::STATUS_UNCONFIRMED
|
||||
'status' => Subscriber::STATUS_UNCONFIRMED,
|
||||
'source' => Source::API,
|
||||
));
|
||||
$this->subscriber_2 = Subscriber::createOrUpdate(array(
|
||||
'email' => 'jane@mailpoet.com',
|
||||
@@ -39,7 +41,8 @@ class SubscribersTest extends \MailPoetTest {
|
||||
'segments' => array(
|
||||
$this->segment_1->id,
|
||||
$this->segment_2->id
|
||||
)
|
||||
),
|
||||
'source' => Source::API,
|
||||
));
|
||||
|
||||
$this->form = Form::createOrUpdate(array(
|
||||
@@ -125,6 +128,7 @@ class SubscribersTest extends \MailPoetTest {
|
||||
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
|
||||
expect($response->errors[0]['message'])
|
||||
->equals('Your email address is invalid!');
|
||||
expect($subscriber->source)->equals('administrator');
|
||||
}
|
||||
|
||||
function testItCanSaveAnExistingSubscriber() {
|
||||
@@ -140,9 +144,9 @@ class SubscribersTest extends \MailPoetTest {
|
||||
Subscriber::findOne($this->subscriber_2->id)->asArray()
|
||||
);
|
||||
expect($response->data['first_name'])->equals('Super Jane');
|
||||
expect($response->data['source'])->equals('api');
|
||||
}
|
||||
|
||||
|
||||
function testItCanRemoveListsFromAnExistingSubscriber() {
|
||||
$router = new Subscribers();
|
||||
$subscriber_data = $this->subscriber_2->asArray();
|
||||
|
@@ -294,6 +294,7 @@ class APITest extends \MailPoetTest {
|
||||
expect($result['id'])->greaterThan(0);
|
||||
expect($result['email'])->equals($subscriber['email']);
|
||||
expect($result['cf_' . $custom_field->id])->equals('test');
|
||||
expect($result['source'])->equals('api');
|
||||
}
|
||||
|
||||
function testItSubscribesToSegmentsWhenAddingSubscriber() {
|
||||
|
@@ -452,6 +452,8 @@ class ImportTest extends \MailPoetTest {
|
||||
expect($new_subscribers)->count(2);
|
||||
expect($new_subscribers[0]->status)->equals('subscribed');
|
||||
expect($new_subscribers[1]->status)->equals('subscribed');
|
||||
expect($new_subscribers[0]->source)->equals('imported');
|
||||
expect($new_subscribers[1]->source)->equals('imported');
|
||||
}
|
||||
|
||||
function testItRunsImport() {
|
||||
|
39
tests/unit/Subscribers/SourceTest.php
Normal file
39
tests/unit/Subscribers/SourceTest.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace MailPoet\Subscribers;
|
||||
|
||||
use MailPoet\Models\Subscriber;
|
||||
|
||||
class SourceTest extends \MailPoetTest {
|
||||
|
||||
function testItDoesntOverrideSource() {
|
||||
$subscriber = Subscriber::createOrUpdate(array(
|
||||
'source' => Source::FORM,
|
||||
));
|
||||
$updated_subscriber = Source::setSource($subscriber, Source::API);
|
||||
expect($updated_subscriber->source)->equals(Source::FORM);
|
||||
}
|
||||
|
||||
function testItDoesntAllowInvalidSource() {
|
||||
$subscriber = Subscriber::createOrUpdate(array(
|
||||
'source' => Source::UNKNOWN,
|
||||
));
|
||||
$this->setExpectedException('\InvalidArgumentException');
|
||||
Source::setSource($subscriber, 'invalid source');
|
||||
}
|
||||
|
||||
function testItWorksWhenNoSourceIsSet() {
|
||||
$subscriber = Subscriber::createOrUpdate(array());
|
||||
$updated_subscriber = Source::setSource($subscriber, Source::FORM);
|
||||
expect($updated_subscriber->source)->equals(Source::FORM);
|
||||
}
|
||||
|
||||
function testItWorks() {
|
||||
$subscriber = Subscriber::createOrUpdate(array(
|
||||
'source' => Source::UNKNOWN,
|
||||
));
|
||||
$updated_subscriber = Source::setSource($subscriber, Source::FORM);
|
||||
expect($updated_subscriber->source)->equals(Source::FORM);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user