Merge pull request #186 from mailpoet/newsletter_options
Newsletter options
This commit is contained in:
@ -43,6 +43,8 @@ class Initializer {
|
||||
$newsletter_segment = Env::$db_prefix . 'newsletter_segment';
|
||||
$custom_fields = Env::$db_prefix . 'custom_fields';
|
||||
$subscriber_custom_field = Env::$db_prefix . 'subscriber_custom_field';
|
||||
$newsletter_option_fields = Env::$db_prefix . 'newsletter_option_fields';
|
||||
$newsletter_option = Env::$db_prefix . 'newsletter_option';
|
||||
|
||||
define('MP_SUBSCRIBERS_TABLE', $subscribers);
|
||||
define('MP_SETTINGS_TABLE', $settings);
|
||||
@ -53,6 +55,8 @@ class Initializer {
|
||||
define('MP_NEWSLETTER_SEGMENT_TABLE', $newsletter_segment);
|
||||
define('MP_CUSTOM_FIELDS_TABLE', $custom_fields);
|
||||
define('MP_SUBSCRIBER_CUSTOM_FIELD_TABLE', $subscriber_custom_field);
|
||||
define('MP_NEWSLETTER_OPTION_FIELDS_TABLE', $newsletter_option_fields);
|
||||
define('MP_NEWSLETTER_OPTION_TABLE', $newsletter_option);
|
||||
}
|
||||
|
||||
function setupActivator() {
|
||||
@ -92,4 +96,4 @@ class Initializer {
|
||||
$permissions = new Permissions();
|
||||
$permissions->init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,9 @@ class Migrator {
|
||||
'subscriber_segment',
|
||||
'newsletter_segment',
|
||||
'custom_fields',
|
||||
'subscriber_custom_field'
|
||||
'subscriber_custom_field',
|
||||
'newsletter_option_fields',
|
||||
'newsletter_option',
|
||||
);
|
||||
}
|
||||
|
||||
@ -161,6 +163,32 @@ class Migrator {
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function newsletter_option_fields() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'name varchar(90) NOT NULL,',
|
||||
'newsletter_type 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_newsletter_type (newsletter_type, name)'
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function newsletter_option() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'newsletter_id mediumint(9) NOT NULL,',
|
||||
'option_field_id mediumint(9) NOT NULL,',
|
||||
'value varchar(255) 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;
|
||||
|
||||
|
@ -19,6 +19,15 @@ class Newsletter extends Model {
|
||||
);
|
||||
}
|
||||
|
||||
function options() {
|
||||
return $this->has_many_through(
|
||||
__NAMESPACE__.'\NewsletterOptionField',
|
||||
__NAMESPACE__.'\NewsletterOption',
|
||||
'newsletter_id',
|
||||
'option_field_id'
|
||||
)->select_expr(MP_NEWSLETTER_OPTIONS_TABLE.'.value');
|
||||
}
|
||||
|
||||
static function search($orm, $search = '') {
|
||||
return $orm->where_like('subject', '%' . $search . '%');
|
||||
}
|
||||
@ -76,6 +85,28 @@ class Newsletter extends Model {
|
||||
return $orm;
|
||||
}
|
||||
|
||||
static function filterWithOptions($orm) {
|
||||
$orm = $orm->select(MP_NEWSLETTERS_TABLE.'.*');
|
||||
$optionFields = NewsletterOptionField::findArray();
|
||||
foreach ($optionFields as $optionField) {
|
||||
$orm = $orm->select_expr(
|
||||
'IFNULL(GROUP_CONCAT(CASE WHEN ' .
|
||||
MP_NEWSLETTER_OPTION_FIELDS_TABLE . '.id=' . $optionField['id'] . ' THEN ' .
|
||||
MP_NEWSLETTER_OPTION_TABLE . '.value END), NULL) as "' . $optionField['name'].'"');
|
||||
}
|
||||
$orm = $orm
|
||||
->left_outer_join(
|
||||
MP_NEWSLETTER_OPTION_TABLE,
|
||||
array(MP_NEWSLETTERS_TABLE.'.id', '=',
|
||||
MP_NEWSLETTER_OPTION_TABLE.'.newsletter_id'))
|
||||
->left_outer_join(
|
||||
MP_NEWSLETTER_OPTION_FIELDS_TABLE,
|
||||
array(MP_NEWSLETTER_OPTION_FIELDS_TABLE.'.id','=',
|
||||
MP_NEWSLETTER_OPTION_TABLE.'.option_field_id'))
|
||||
->group_by(MP_NEWSLETTERS_TABLE.'.id');
|
||||
return $orm;
|
||||
}
|
||||
|
||||
static function groups() {
|
||||
return array(
|
||||
array(
|
||||
|
12
lib/Models/NewsletterOption.php
Normal file
12
lib/Models/NewsletterOption.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
namespace MailPoet\Models;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class NewsletterOption extends Model {
|
||||
public static $_table = MP_NEWSLETTER_OPTION_TABLE;
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
}
|
27
lib/Models/NewsletterOptionField.php
Normal file
27
lib/Models/NewsletterOptionField.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
namespace MailPoet\Models;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class NewsletterOptionField extends Model {
|
||||
public static $_table = MP_NEWSLETTER_OPTION_FIELDS_TABLE;
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
$this->addValidations('name', array(
|
||||
'required' => __('You need to specify a name.')
|
||||
));
|
||||
$this->addValidations('newsletter_type', array(
|
||||
'required' => __('You need to specify a newsletter type.')
|
||||
));
|
||||
}
|
||||
|
||||
function newsletters() {
|
||||
return $this->has_many_through(
|
||||
__NAMESPACE__ . '\Newsletter',
|
||||
__NAMESPACE__ . '\NewsletterOption',
|
||||
'option_field_id',
|
||||
'newsletter_id'
|
||||
)->select_expr(MP_NEWSLETTER_OPTION_TABLE.'.value');
|
||||
}
|
||||
}
|
@ -3,6 +3,8 @@
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Models\NewsletterSegment;
|
||||
use MailPoet\Models\NewsletterOptionField;
|
||||
use MailPoet\Models\NewsletterOption;
|
||||
|
||||
class NewsletterCest {
|
||||
function _before() {
|
||||
@ -16,6 +18,7 @@ class NewsletterCest {
|
||||
|
||||
$newsletter = Newsletter::create();
|
||||
$newsletter->hydrate($this->data);
|
||||
$this->newsletter = $newsletter;
|
||||
$this->result = $newsletter->save();
|
||||
}
|
||||
|
||||
@ -104,7 +107,101 @@ class NewsletterCest {
|
||||
expect($newsletter->subject)->contains('pineapple');
|
||||
}
|
||||
|
||||
function itCanHaveOptions() {
|
||||
$newsletterOptionFieldData = array(
|
||||
'name' => 'Event',
|
||||
'newsletter_type' => 'welcome',
|
||||
);
|
||||
$optionField = NewsletterOptionField::create();
|
||||
$optionField->hydrate($newsletterOptionFieldData);
|
||||
$optionField->save();
|
||||
$association = NewsletterOption::create();
|
||||
$association->newsletter_id = $this->newsletter->id;
|
||||
$association->option_field_id = $optionField->id;
|
||||
$association->value = 'list';
|
||||
$association->save();
|
||||
$newsletter = Newsletter::filter('filterWithOptions')
|
||||
->findOne($this->newsletter->id);
|
||||
expect($newsletter->Event)->equals($association->value);
|
||||
}
|
||||
|
||||
function itCanFilterOptions() {
|
||||
$newsletterOptionFieldData = array(
|
||||
array(
|
||||
'name' => 'Event',
|
||||
'newsletter_type' => 'welcome',
|
||||
),
|
||||
array(
|
||||
'name' => 'List',
|
||||
'newsletter_type' => 'welcome',
|
||||
)
|
||||
);
|
||||
foreach ($newsletterOptionFieldData as $data) {
|
||||
$optionField = NewsletterOptionField::create();
|
||||
$optionField->hydrate($data);
|
||||
$optionField->save();
|
||||
$createdOptionFields[] = $optionField->asArray();
|
||||
}
|
||||
$newsletterOptionData = array(
|
||||
array(
|
||||
'newsletter_id' => $this->newsletter->id,
|
||||
'option_field_id' => $createdOptionFields[0]['id'],
|
||||
'value' => 'list'
|
||||
),
|
||||
array(
|
||||
'newsletter_id' => $this->newsletter->id,
|
||||
'option_field_id' => $createdOptionFields[1]['id'],
|
||||
'value' => '1'
|
||||
)
|
||||
);
|
||||
foreach ($newsletterOptionData as $data) {
|
||||
$association = NewsletterOption::create();
|
||||
$association->hydrate($data);
|
||||
$association->save();
|
||||
$createdAssociations[] = $association->asArray();
|
||||
}
|
||||
$newsletter = Newsletter::filter('filterWithOptions')
|
||||
->filter('filterSearchCustomFields', array(
|
||||
array(
|
||||
'name' => 'Event',
|
||||
'value' => 'list'
|
||||
)
|
||||
))
|
||||
->findArray();
|
||||
expect(empty($newsletter))->false();
|
||||
$newsletter = Newsletter::filter('filterWithOptions')
|
||||
->filter('filterSearchCustomFields', array(
|
||||
array(
|
||||
'name' => 'Event',
|
||||
'value' => 'list'
|
||||
),
|
||||
array(
|
||||
'name' => 'List',
|
||||
'value' => '1'
|
||||
)
|
||||
))
|
||||
->findArray();
|
||||
expect(empty($newsletter))->false();
|
||||
$newsletter = Newsletter::filter('filterWithOptions')
|
||||
->filter('filterSearchCustomFields', array(
|
||||
array(
|
||||
'name' => 'Event',
|
||||
'value' => 'list'
|
||||
),
|
||||
array(
|
||||
'name' => 'List',
|
||||
'value' => '2'
|
||||
)
|
||||
))
|
||||
->findArray();
|
||||
expect(empty($newsletter))->true();
|
||||
}
|
||||
|
||||
function _after() {
|
||||
ORM::forTable(NewsletterOption::$_table)
|
||||
->deleteMany();
|
||||
ORM::forTable(NewsletterOptionField::$_table)
|
||||
->deleteMany();
|
||||
ORM::for_table(Newsletter::$_table)
|
||||
->deleteMany();
|
||||
}
|
||||
|
127
tests/unit/Models/NewsletterOptionFieldCest.php
Normal file
127
tests/unit/Models/NewsletterOptionFieldCest.php
Normal file
@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\NewsletterOption;
|
||||
use MailPoet\Models\NewsletterOptionField;
|
||||
|
||||
class NewsletterOptionFieldCest {
|
||||
function _before() {
|
||||
$this->before_time = time();
|
||||
$this->data = array(
|
||||
'name' => 'Event',
|
||||
'newsletter_type' => 'welcome',
|
||||
);
|
||||
$this->optionField = NewsletterOptionField::create();
|
||||
$this->optionField->hydrate($this->data);
|
||||
$this->saved = $this->optionField->save();
|
||||
$this->newslettersData = array(
|
||||
array(
|
||||
'subject' => 'Test newsletter 1',
|
||||
'preheader' => '',
|
||||
'body' => '{}'
|
||||
),
|
||||
array(
|
||||
'subject' => 'Test newsletter 2',
|
||||
'preheader' => 'A newsletter',
|
||||
'body' => '{}'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function itCanBeCreated() {
|
||||
expect($this->saved)->equals(true);
|
||||
}
|
||||
|
||||
function itHasName() {
|
||||
$optionField = NewsletterOptionField::where('name', $this->data['name'])
|
||||
->findOne();
|
||||
expect($optionField->name)->equals($this->data['name']);
|
||||
}
|
||||
|
||||
function itHasNewsletterType() {
|
||||
$optionField = NewsletterOptionField::where('name', $this->data['name'])
|
||||
->findOne();
|
||||
expect($optionField->newsletter_type)->equals($this->data['newsletter_type']);
|
||||
}
|
||||
|
||||
function itHasToBeValid() {
|
||||
expect($this->saved)->equals(true);
|
||||
$empty_model = NewsletterOptionField::create();
|
||||
expect($empty_model->save())->notEquals(true);
|
||||
$validations = $empty_model->getValidationErrors();
|
||||
expect(count($validations))->equals(2);
|
||||
}
|
||||
|
||||
function itHasACreatedAtOnCreation() {
|
||||
$optionField = NewsletterOptionField::where('name', $this->data['name'])
|
||||
->findOne();
|
||||
$time_difference = strtotime($optionField->created_at) >= $this->before_time;
|
||||
expect($time_difference)->equals(true);
|
||||
}
|
||||
|
||||
function itHasAnUpdatedAtOnCreation() {
|
||||
$optionField = NewsletterOptionField::where('name', $this->data['name'])
|
||||
->findOne();
|
||||
$time_difference = strtotime($optionField->updated_at) >= $this->before_time;
|
||||
expect($time_difference)->equals(true);
|
||||
}
|
||||
|
||||
function itKeepsTheCreatedAtOnUpdate() {
|
||||
$optionField = NewsletterOptionField::where('name', $this->data['name'])
|
||||
->findOne();
|
||||
$old_created_at = $optionField->created_at;
|
||||
$optionField->name = 'new name';
|
||||
$optionField->save();
|
||||
expect($old_created_at)->equals($optionField->created_at);
|
||||
}
|
||||
|
||||
function itUpdatesTheUpdatedAtOnUpdate() {
|
||||
$optionField = NewsletterOptionField::where('name', $this->data['name'])
|
||||
->findOne();
|
||||
$update_time = time();
|
||||
$optionField->name = 'new name';
|
||||
$optionField->save();
|
||||
$time_difference = strtotime($optionField->updated_at) >= $update_time;
|
||||
expect($time_difference)->equals(true);
|
||||
}
|
||||
|
||||
function itCanHaveManyNewsletters() {
|
||||
foreach ($this->newslettersData as $data) {
|
||||
$newsletter = Newsletter::create();
|
||||
$newsletter->hydrate($data);
|
||||
$newsletter->save();
|
||||
$association = NewsletterOption::create();
|
||||
$association->newsletter_id = $newsletter->id;
|
||||
$association->option_field_id = $this->optionField->id;
|
||||
$association->save();
|
||||
}
|
||||
$optionField = NewsletterOptionField::findOne($this->optionField->id);
|
||||
$newsletters = $optionField->newsletters()
|
||||
->findArray();
|
||||
expect(count($newsletters))->equals(2);
|
||||
}
|
||||
|
||||
function itCanStoreOptionValue() {
|
||||
$newsletter = Newsletter::create();
|
||||
$newsletter->hydrate($this->newslettersData[0]);
|
||||
$newsletter->save();
|
||||
$association = NewsletterOption::create();
|
||||
$association->newsletter_id = $newsletter->id;
|
||||
$association->option_field_id = $this->optionField->id;
|
||||
$association->value = 'list';
|
||||
$association->save();
|
||||
$optionField = NewsletterOptionField::findOne($this->optionField->id);
|
||||
$newsletter = $optionField->newsletters()
|
||||
->findOne();
|
||||
expect($newsletter->value)->equals($association->value);
|
||||
}
|
||||
|
||||
function _after() {
|
||||
ORM::forTable(NewsletterOption::$_table)
|
||||
->deleteMany();
|
||||
ORM::forTable(NewsletterOptionField::$_table)
|
||||
->deleteMany();
|
||||
ORM::forTable(Newsletter::$_table)
|
||||
->deleteMany();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user