Conflicts between Segment and Subscriber status.

This commit is contained in:
marco
2015-09-03 18:05:49 +02:00
10 changed files with 414 additions and 197 deletions

View File

@@ -13,13 +13,13 @@ define('ajax', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
onError: function(xhr, textStatus, errorThrown) {}
},
get: function(options) {
this.request('get', options);
return this.request('get', options);
},
post: function(options) {
this.request('post', options);
return this.request('post', options);
},
delete: function(options) {
this.request('delete', options);
return this.request('delete', options);
},
init: function(options) {
// merge options
@@ -46,18 +46,18 @@ define('ajax', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
endpoint: this.options.endpoint,
method: this.options.action,
data: this.options.data || {}
};
}, jqXHR;
// make ajax request depending on method
if(method === 'get') {
jQuery.get(
jqXHR = jQuery.get(
this.options.url,
params,
this.options.onSuccess,
'json'
);
} else {
jQuery.ajax({
jqXHR = jQuery.ajax({
url: this.options.url,
type : 'post',
data: params,
@@ -69,6 +69,8 @@ define('ajax', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
// clear options
this.options = {};
return jqXHR;
}
};
});

View File

@@ -33,10 +33,14 @@ class Initializer {
$subscribers = Env::$db_prefix . 'subscribers';
$settings = Env::$db_prefix . 'settings';
$newsletters = Env::$db_prefix . 'newsletters';
$segments = Env::$db_prefix . 'segments';
$subscriber_segment = Env::$db_prefix . 'subscriber_segment';
define('MP_SUBSCRIBERS_TABLE', $subscribers);
define('MP_SETTINGS_TABLE', $settings);
define('MP_NEWSLETTERS_TABLE', $newsletters);
define('MP_SEGMENTS_TABLE', $segments);
define('MP_SUBSCRIBER_SEGMENT_TABLE', $subscriber_segment);
}
function setupActivator() {

View File

@@ -12,7 +12,9 @@ class Migrator {
$this->models = array(
'subscribers',
'settings',
'newsletters'
'newsletters',
'segments',
'subscriber_segment'
);
}
@@ -78,6 +80,30 @@ class Migrator {
return $this->sqlify(__FUNCTION__, $attributes);
}
function segments() {
$attributes = array(
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
'name varchar(90) NOT NULL,',
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
'PRIMARY KEY (id),',
'UNIQUE KEY name (name)'
);
return $this->sqlify(__FUNCTION__, $attributes);
}
function subscriber_segment() {
$attributes = array(
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
'subscriber_id mediumint(9) NOT NULL,',
'segment_id mediumint(9) NOT NULL,',
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
'PRIMARY KEY (id)'
);
return $this->sqlify(__FUNCTION__, $attributes);
}
private function sqlify($model, $attributes) {
$table = $this->prefix . $model;

35
lib/Models/Segment.php Normal file
View File

@@ -0,0 +1,35 @@
<?php
namespace MailPoet\Models;
if(!defined('ABSPATH')) exit;
class Segment extends Model {
public static $_table = MP_SEGMENTS_TABLE;
function __construct() {
parent::__construct();
$this->addValidations('name', array(
'required' => 'name_is_blank',
'isString' => 'name_is_not_string'
));
}
public static function createOrUpdate($model) {
$exists = self::where('name', $model['name'])
->find_one();
if($exists === false) {
$new_model = self::create();
$new_model->name = $model['name'];
return $new_model->save();
}
$exists->name = $model['name_updated'];
return $exists->save();
}
public function subscribers() {
return $this->has_many_through(__NAMESPACE__ . '\Subscriber', __NAMESPACE__ . '\SubscriberSegment', 'segment_id', 'subscriber_id');
}
}

View File

@@ -20,11 +20,11 @@ class Setting extends Model {
}
public static function createOrUpdate($model) {
$exists = Setting::where('name', $model['name'])
$exists = self::where('name', $model['name'])
->find_one();
if($exists === false) {
$new_model = Setting::create();
$new_model = self::create();
$new_model->hydrate($model);
return $new_model->save();
}

View File

@@ -1,64 +1,68 @@
<?php
namespace MailPoet\Models;
if (!defined('ABSPATH')) exit;
class Subscriber extends Model {
public static $_table = MP_SUBSCRIBERS_TABLE;
function __construct() {
parent::__construct();
$this->addValidations('email', array(
'required' => __('You need to enter your email address.'),
'isEmail' => __('Your email address is invalid.')
));
}
static function search($orm, $search = '') {
if(strlen(trim($search) === 0)) {
return $orm;
}
return $orm->where_raw(
'(`email` LIKE ? OR `first_name` LIKE ? OR `last_name` LIKE ?)',
array('%'.$search.'%', '%'.$search.'%', '%'.$search.'%')
);
}
static function groups() {
return array(
array(
'name' => 'all',
'label' => __('All'),
'count' => Subscriber::count()
),
array(
'name' => 'subscribed',
'label' => __('Subscribed'),
'count' => Subscriber::where('status', 'subscribed')->count()
),
array(
'name' => 'unconfirmed',
'label' => __('Unconfirmed'),
'count' => Subscriber::where('status', 'unconfirmed')->count()
),
array(
'name' => 'unsubscribed',
'label' => __('Unsubscribed'),
'count' => Subscriber::where('status', 'unsubscribed')->count()
)
);
}
static function group($orm, $group = null) {
if($group === null or !in_array(
$group,
array('subscribed', 'unconfirmed', 'unsubscribed')
)) {
return $orm;
}
return $orm->where('status', $group);
}
}
<?php
namespace MailPoet\Models;
if(!defined('ABSPATH')) exit;
class Subscriber extends Model {
public static $_table = MP_SUBSCRIBERS_TABLE;
function __construct() {
parent::__construct();
$this->addValidations('email', array(
'required' => __('You need to enter your email address.'),
'isEmail' => __('Your email address is invalid.')
));
}
static function search($orm, $search = '') {
if(strlen(trim($search) === 0)) {
return $orm;
}
return $orm->where_raw(
'(`email` LIKE ? OR `first_name` LIKE ? OR `last_name` LIKE ?)',
array('%'.$search.'%', '%'.$search.'%', '%'.$search.'%')
);
}
static function groups() {
return array(
array(
'name' => 'all',
'label' => __('All'),
'count' => Subscriber::count()
),
array(
'name' => 'subscribed',
'label' => __('Subscribed'),
'count' => Subscriber::where('status', 'subscribed')->count()
),
array(
'name' => 'unconfirmed',
'label' => __('Unconfirmed'),
'count' => Subscriber::where('status', 'unconfirmed')->count()
),
array(
'name' => 'unsubscribed',
'label' => __('Unsubscribed'),
'count' => Subscriber::where('status', 'unsubscribed')->count()
)
);
}
static function group($orm, $group = null) {
if($group === null or !in_array(
$group,
array('subscribed', 'unconfirmed', 'unsubscribed')
)) {
return $orm;
}
return $orm->where('status', $group);
}
public function segments() {
return $this->has_many_through(__NAMESPACE__ . '\Segment', __NAMESPACE__ . '\SubscriberSegment', 'subscriber_id', 'segment_id');
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace MailPoet\Models;
if(!defined('ABSPATH')) exit;
class SubscriberSegment extends Model {
public static $_table = MP_SUBSCRIBER_SEGMENT_TABLE;
function __construct() {
parent::__construct();
}
}

View File

@@ -7,12 +7,14 @@ require_once(getenv('WP_TEST_PATH') . '/wp-load.php');
$console->writeln('Cleaning up database...');
$models = array(
"Subscriber",
"Setting",
"Newsletter"
'Subscriber',
'Setting',
'Newsletter',
'Segment',
'SubscriberSegment'
);
$destroy = function ($model) {
Model::factory("\MailPoet\Models\\" . $model)
->delete_many();
Model::factory('\MailPoet\Models\\' . $model)
->delete_many();
};
array_map($destroy, $models);

View File

@@ -0,0 +1,120 @@
<?php
use MailPoet\Models\SubscriberSegment;
use MailPoet\Models\Subscriber;
use MailPoet\Models\Segment;
class SegmentCest {
function _before() {
$this->before_time = time();
$this->data = array(
'name' => 'some name',
);
$this->segment = Segment::create();
$this->segment->hydrate($this->data);
$this->saved = $this->segment->save();
}
function itCanBeCreated() {
expect($this->saved)->equals(true);
}
function itHasToBeValid() {
expect($this->saved)->equals(true);
$empty_model = Segment::create();
expect($empty_model->save())->equals(false);
$validations = $empty_model->getValidationErrors();
expect(count($validations))->equals(2);
}
function itHasACreatedAtOnCreation() {
$segment = Segment::where('name', $this->data['name'])
->findOne();
$time_difference = strtotime($segment->created_at) >= $this->before_time;
expect($time_difference)->equals(true);
}
function itHasAnUpdatedAtOnCreation() {
$segment = Segment::where('name', $this->data['name'])
->findOne();
$time_difference = strtotime($segment->updated_at) >= $this->before_time;
expect($time_difference)->equals(true);
}
function itKeepsTheCreatedAtOnUpdate() {
$segment = Segment::where('name', $this->data['name'])
->findOne();
$old_created_at = $segment->created_at;
$segment->name = 'new name';
$segment->save();
expect($old_created_at)->equals($segment->created_at);
}
function itUpdatesTheUpdatedAtOnUpdate() {
$segment = Segment::where('name', $this->data['name'])
->findOne();
$update_time = time();
$segment->name = 'new name';
$segment->save();
$time_difference = strtotime($segment->updated_at) >= $update_time;
expect($time_difference)->equals(true);
}
function itCanCreateOrUpdate() {
$data = array(
'name' => 'some other new name'
);
$createNewRecord = Segment::createOrUpdate($data);
$data = array(
'name' => $this->data['name'],
'name_updated' => 'updated name',
);
$updateExistingRecord = Segment::createOrUpdate($data);
$allRecords = Segment::find_array();
expect(count($allRecords))->equals(2);
expect($allRecords[0]['name'])->equals($data['name_updated']);
}
function itCanHaveMultipleSubscribers() {
$subscribersData = array(
array(
'first_name' => 'John',
'last_name' => 'Mailer',
'email' => 'john@mailpoet.com'
),
array(
'first_name' => 'Mike',
'last_name' => 'Smith',
'email' => 'mike@maipoet.com'
)
);
foreach ($subscribersData as $subscriberData) {
$subscriber = Subscriber::create();
$subscriber->hydrate($subscriberData);
$subscriber->save();
$association = SubscriberSegment::create();
$association->subscriber_id = $subscriber->id;
$association->segment_id = $this->segment->id;
$association->save();
}
$segment = Segment::find_one($this->segment->id);
$subscribers = $segment->subscribers()
->find_array();
expect(count($subscribers))->equals(2);
}
function _after() {
ORM::for_table(Segment::$_table)
->delete_many();
ORM::for_table(Subscriber::$_table)
->delete_many();
ORM::for_table(SubscriberSegment::$_table)
->delete_many();
}
}

View File

@@ -1,119 +1,131 @@
<?php
use MailPoet\Models\Subscriber;
class SubscriberCest {
function _before() {
$this->data = array(
'first_name' => 'John',
'last_name' => 'Mailer',
'email' => 'jo@mailpoet.com'
);
$this->subscriber = Subscriber::create();
$this->subscriber->hydrate($this->data);
$this->saved = $this->subscriber->save();
$subscribed = Subscriber::create();
$subscribed->hydrate(array(
'email' => 'marco@mailpoet.com',
'status' => 'subscribed'
));
$subscribed->save();
$unsubscribed = Subscriber::create();
$unsubscribed->hydrate(array(
'email' => 'marco@mailpoet.com',
'status' => 'unsubscribed'
));
$unsubscribed->save();
}
function itCanBeCreated() {
expect($this->saved)->equals(true);
}
function itHasAFirstName() {
$subscriber =
Subscriber::where('email', $this->data['email'])
->findOne();
expect($subscriber->first_name)
->equals($this->data['first_name']);
}
function itHasALastName() {
$subscriber =
Subscriber::where('email', $this->data['email'])
->findOne();
expect($subscriber->last_name)
->equals($this->data['last_name']);
}
function itHasAnEmail() {
$subscriber =
Subscriber::where('email', $this->data['email'])
->findOne();
expect($subscriber->email)
->equals($this->data['email']);
}
function itHasAStatus() {
$subscriber =
Subscriber::where('email', $this->data['email'])
->findOne();
expect($subscriber->status)->equals('unconfirmed');
}
function itCanChangeStatus() {
$subscriber = Subscriber::where('email', $this->data['email'])->findOne();
$subscriber->status = 'subscribed';
expect($subscriber->save())->equals(true);
$subscriber_updated = Subscriber::where(
'email',
$this->data['email']
)->findOne();
expect($subscriber_updated->status)->equals('subscribed');
}
function itHasASearchFilter() {
$subscriber = Subscriber::filter('search', 'john')->findOne();
expect($subscriber->first_name)->equals($this->data['first_name']);
$subscriber = Subscriber::filter('search', 'mailer')->findOne();
expect($subscriber->last_name)->equals($this->data['last_name']);
$subscriber = Subscriber::filter('search', 'mailpoet')->findOne();
expect($subscriber->email)->equals($this->data['email']);
}
function itHasAGroupFilter() {
$subscribers = Subscriber::filter('group', 'unconfirmed')->findMany();
foreach($subscribers as $subscriber) {
expect($subscriber->status)->equals('unconfirmed');
}
$subscribers = Subscriber::filter('group', 'subscribed')->findMany();
foreach($subscribers as $subscriber) {
expect($subscriber->status)->equals('subscribed');
}
$subscribers = Subscriber::filter('group', 'unsubscribed')->findMany();
foreach($subscribers as $subscriber) {
expect($subscriber->status)->equals('unsubscribed');
}
}
function emailMustBeUnique() {
$conflict_subscriber = Subscriber::create();
$conflict_subscriber->hydrate($this->data);
$saved = $conflict_subscriber->save();
expect($saved)->equals(false);
}
function _after() {
ORM::for_table(Subscriber::$_table)
->delete_many();
}
}
<?php
use MailPoet\Models\Subscriber;
use MailPoet\Models\Segment;
use MailPoet\Models\SubscriberSegment;
class SubscriberCest {
function _before() {
$this->before_time = time();
$this->data = array(
'first_name' => 'John',
'last_name' => 'Mailer',
'email' => 'john@mailpoet.com'
);
$this->subscriber = Subscriber::create();
$this->subscriber->hydrate($this->data);
$this->saved = $this->subscriber->save();
}
function itCanBeCreated() {
expect($this->saved)->equals(true);
}
function itHasAFirstName() {
$subscriber =
Subscriber::where('email', $this->data['email'])
->findOne();
expect($subscriber->first_name)
->equals($this->data['first_name']);
}
function itHasALastName() {
$subscriber =
Subscriber::where('email', $this->data['email'])
->findOne();
expect($subscriber->last_name)
->equals($this->data['last_name']);
}
function itHasAnEmail() {
$subscriber =
Subscriber::where('email', $this->data['email'])
->findOne();
expect($subscriber->email)
->equals($this->data['email']);
}
function emailMustBeUnique() {
$conflict_subscriber = Subscriber::create();
$conflict_subscriber->hydrate($this->data);
$saved = $conflict_subscriber->save();
expect($saved)->equals(false);
}
function itHasAStatus() {
$subscriber =
Subscriber::where('email', $this->data['email'])
->findOne();
expect($subscriber->status)->equals('unconfirmed');
}
function itCanChangeStatus() {
$subscriber = Subscriber::where('email', $this->data['email'])->findOne();
$subscriber->status = 'subscribed';
expect($subscriber->save())->equals(true);
$subscriber_updated = Subscriber::where(
'email',
$this->data['email']
)->findOne();
expect($subscriber_updated->status)->equals('subscribed');
}
function itHasASearchFilter() {
$subscriber = Subscriber::filter('search', 'john')->findOne();
expect($subscriber->first_name)->equals($this->data['first_name']);
$subscriber = Subscriber::filter('search', 'mailer')->findOne();
expect($subscriber->last_name)->equals($this->data['last_name']);
$subscriber = Subscriber::filter('search', 'mailpoet')->findOne();
expect($subscriber->email)->equals($this->data['email']);
}
function itHasAGroupFilter() {
$subscribers = Subscriber::filter('group', 'unconfirmed')->findMany();
foreach($subscribers as $subscriber) {
expect($subscriber->status)->equals('unconfirmed');
}
$subscribers = Subscriber::filter('group', 'subscribed')->findMany();
foreach($subscribers as $subscriber) {
expect($subscriber->status)->equals('subscribed');
}
$subscribers = Subscriber::filter('group', 'unsubscribed')->findMany();
foreach($subscribers as $subscriber) {
expect($subscriber->status)->equals('unsubscribed');
}
}
function itCanHaveASegment() {
$segmentData = array(
'name' => 'some name'
);
$segment = Segment::create();
$segment->hydrate($segmentData);
$segment->save();
$association = SubscriberSegment::create();
$association->subscriber_id = $this->subscriber->id;
$association->segment_id = $segment->id;
$association->save();
$subscriber = Subscriber::find_one($this->subscriber->id);
$subscriberSegment = $subscriber->segments()
->find_one();
expect($subscriberSegment->id)->equals($segment->id);
}
function _after() {
ORM::for_table(Subscriber::$_table)
->delete_many();
ORM::for_table(Segment::$_table)
->delete_many();
ORM::for_table(SubscriberSegment::$_table)
->delete_many();
}
}