Merge pull request #186 from mailpoet/newsletter_options

Newsletter options
This commit is contained in:
Marco
2015-10-21 14:06:22 +02:00
7 changed files with 328 additions and 2 deletions

View File

@ -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();
}
}
}

View File

@ -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;

View File

@ -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(

View 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();
}
}

View 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');
}
}

View File

@ -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();
}

View 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();
}
}