Compare commits

..

77 Commits

Author SHA1 Message Date
841c69af59 Merge pull request #348 from mailpoet/page_reviews
Page reviews
2016-02-12 13:36:47 -05:00
56b4688f93 updated unit tests for segments 2016-02-12 19:29:30 +01:00
e60bc7c387 handle duplicates in model 2016-02-12 19:24:04 +01:00
6094a83f4b Merge pull request #350 from mailpoet/rendering_engine_image_update
Updates logic behind image dimensions based on column width
2016-02-12 19:14:49 +02:00
91ddb98f56 Merge pull request #349 from mailpoet/exception_namescape_fix
Fixes namespace issue when catching exceptions
2016-02-12 19:11:25 +02:00
27d5972306 - Updates logic behind image dimensions based on column width 2016-02-12 12:05:27 -05:00
6088497433 Bump up release version to 0.0.15 2016-02-12 18:25:12 +02:00
0d894a6fef - Fixes namespace issue when catching exceptions 2016-02-12 11:20:43 -05:00
57f0b88299 Merge pull request #347 from mailpoet/sending_frequency
Implements sending frequency
2016-02-12 14:23:22 +02:00
5121dbe0c8 Form Editor Round 3
- added prefix to form styles so that it does not conflict when multiple forms are on the same page
- added validation on form save for segments
2016-02-12 12:45:07 +01:00
f874ffc19c Merge pull request #346 from mailpoet/rendering_engine_image_update
Updates image rendering & unit test
2016-02-12 12:42:49 +02:00
e928a5c2bc Segments page review
- remove edit link for WordPress users list
- hide trashed segments from Import
- fixed display issue in listing's item actions
2016-02-12 11:30:08 +01:00
d11badf3ce - Implements sending frequency
- Updates sending queue worker
2016-02-11 22:46:45 -05:00
3006c982cb - Updates image rendering & unit test 2016-02-11 21:28:43 -05:00
b29e31fdd6 Merge pull request #344 from mailpoet/router_update_sending_queue
Sending queue router update
2016-02-11 11:31:49 -05:00
bc42c8e280 Merge branch 'router_update_sending_queue' of mailpoet:mailpoet/mailpoet into router_update_sending_queue 2016-02-11 11:30:08 -05:00
409697ee64 Sending queue router update
- cleaned up useless code
- bugfixes
- improved code coverage
2016-02-11 11:30:01 -05:00
cfb4265971 Merge pull request #343 from mailpoet/queue_worker_rewrite
Sending queue worker rewrite
2016-02-11 18:16:07 +02:00
13d78aac05 Merge branch 'queue_worker_rewrite' of mailpoet:mailpoet/mailpoet into queue_worker_rewrite 2016-02-11 10:37:26 -05:00
6f176f4e6c - Updates MailChimp unit test 2016-02-11 10:34:24 -05:00
9b584296a5 - Updates queue worker based on code review comments 2016-02-11 10:23:41 -05:00
5ea87c5eed Sending queue router update
- cleaned up useless code
- bugfixes
- improved code coverage
2016-02-11 09:37:53 +01:00
7522084ccb - Rewrites sending queue worker and updates router
- Implements batch sending for queue worker
- Fixes mailer class issue when sender data can be empty
- Updates values for cron execution timeout/limit
2016-02-10 22:34:54 -05:00
214aa60d0e Merge pull request #338 from mailpoet/editor_polishing_2
Change `padded` image attribute to `fullWidth`
2016-02-10 22:34:36 -05:00
7a049ce1b7 - Rewrites sending queue worker and updates router
- Implements batch sending for queue worker
- Fixes mailer class issue when sender data can be empty
- Updates values for cron execution timeout/limit
2016-02-10 22:32:39 -05:00
94d293deb7 Merge pull request #339 from mailpoet/mailchimp_update
Updates MailChimp class and unit test
2016-02-09 18:04:43 +01:00
bd2d38d757 updated MP.Notice in order to handle arrays as error messages 2016-02-09 17:58:40 +01:00
abec524daa Merge pull request #340 from mailpoet/fix_registration_in_comments
Subscribe in comments
2016-02-09 18:41:58 +02:00
cac6beb4ac - Fixes display of error messages 2016-02-09 11:26:00 -05:00
cac995e15b fixed subscribe in comments 2016-02-09 16:55:00 +01:00
b26380fd10 - Updates MailChimp class and unit test 2016-02-09 10:03:29 -05:00
6c6a4070be Remove obsolete attribute from server response 2016-02-09 15:47:56 +02:00
8b001d820b Change padded image attribute to fullWidth 2016-02-09 15:26:06 +02:00
2ae3d8ebdf Merge pull request #337 from mailpoet/fix_listing_pagination
Pagination issues
2016-02-09 12:23:39 +02:00
459ec21f9d fixed pagination issues 2016-02-08 17:11:11 +01:00
9c7790d07e Merge pull request #336 from mailpoet/listing_empty_trash
Listing update + Unit tests
2016-02-08 16:01:42 +02:00
f9c5b99e46 updated Subscriber:: -> self:: in Models\Subscriber 2016-02-08 14:43:59 +01:00
95b0b39366 Fixed bulk_action success messages
- uptaded Subscriber & Segment routers' test
- moved add/remove segments logic to Subscriber::createOrUpdate
- fixed Router\Segments save not returning errors
2016-02-08 13:36:35 +01:00
4b6fa0e760 Added "Subscribers without a segment" filter
- removed useless dependency in filters.jsx
- fixed issue with Router\Subscribers::save() not updating segments
2016-02-08 10:32:06 +01:00
67a3440ced updated router unit tests - refactor + test bulk delete 2016-02-08 10:10:43 +01:00
0de372344a fixed bulkDelete 2016-02-06 15:17:19 +01:00
7a04eeb650 Listing: Empty trash button 2016-02-06 15:15:07 +01:00
8dbfe82922 Bump version up to 0.0.14 2016-02-05 17:34:53 +02:00
7322f2151c Merge pull request #334 from mailpoet/unit_tests_update
Enables conditional bypassing of unit tests
2016-02-05 16:38:31 +02:00
c43d2f240d - Updates MailChimp test and .env.sample 2016-02-05 09:35:32 -05:00
bbcd267b6f - Updates .env.sample with available options for unit tests 2016-02-05 09:00:28 -05:00
bbc4acb2a4 Merge pull request #335 from mailpoet/mailer_class_Fix
Fixes detection of reply_to address
2016-02-05 12:52:39 +02:00
c89cc5a919 Merge pull request #333 from mailpoet/test_email_fix
Test email fix
2016-02-05 12:19:40 +02:00
33075940de - Fixes detection of reply_to address 2016-02-04 19:22:11 -05:00
51c09b8360 Merge pull request #325 from mailpoet/router_unit_tests
Unit tests (Router\NewsletterTemplates & Router\Segments)
2016-02-04 18:59:09 -05:00
2fbf85f371 - Catches exception returned by mailer class when sender is not configured 2016-02-04 18:57:07 -05:00
24cb614adb - Enables conditional bypassing of unit tests 2016-02-04 18:41:18 -05:00
55f851208b Major update of unit tests / updated routers + models + react 2016-02-04 19:04:52 +01:00
990dac7727 Merge pull request #332 from mailpoet/editor_fixes
Editor bug fixes
2016-02-04 09:02:21 -05:00
233020ca20 fix unit tests 2016-02-04 14:38:25 +01:00
0c419cde16 Unit tests (Router\NewsletterTemplates & Router\Segments
- moved json_decode(body) inside NewsletterTemplate->asArray (override)
- updated NewsletterTemplate router accordingly
- finished Segments unit test
2016-02-04 14:36:08 +01:00
35f9530d8e Merge pull request #326 from mailpoet/router_unit_tests_2
More Unit Tests + Initializer fix
2016-02-04 08:24:15 -05:00
992fe2a6e9 Fix preventing dragging by settings/delete block tools 2016-02-04 13:47:46 +02:00
c2cb88f995 Unit tests fixed + models & routers update 2016-02-04 11:41:05 +01:00
ba69d659ab Changed editor to not send 'last_modified', let server pick one 2016-02-03 18:21:30 +02:00
397d988eb1 Allow block dragging only with "Move" tool, but not with others 2016-02-03 18:21:30 +02:00
d85f2341ec Change Posts/ALC to use MailPoet specific image size 2016-02-03 18:21:30 +02:00
2b3c288b5f Merge pull request #330 from mailpoet/template_footer_fix
Removes footer text/link color overrides for coffee shop template
2016-02-03 11:19:43 -05:00
8ec28a23a7 Removes footer text/link color overrides for coffee shop template 2016-02-03 15:04:18 +02:00
12c9623e2f Better Error handling for models
- added (array)getErrors() to models, returns false if no errors
- converted Forms::saveEditor method to use getErrors
- added error handling on the form editor view
2016-02-03 12:23:42 +01:00
8ba9fdccbc fix for initializer - widget is now registered 2016-02-03 10:42:56 +01:00
a2ef62302f More Unit Tests + Initializer fix
- added unit test for Router\Forms
- updated unit test for Model\Segment to reflect changes
2016-02-02 17:22:11 +01:00
24ecc879d3 Merge pull request #319 from mailpoet/php53-fix
Updates code to work with PHP 5.3
2016-02-02 13:25:23 +01:00
a1104a7f90 Merge pull request #320 from mailpoet/sending_queue_worker_fix
Sending queue worker fix
2016-02-01 16:32:42 +02:00
aa959810e9 Merge pull request #322 from mailpoet/code_coverage
Code coverage report
2016-02-01 16:31:53 +02:00
45b7a79277 Merge pull request #321 from mailpoet/router_upgrade_3
Router upgrade 3
2016-02-01 15:41:13 +02:00
41c8c0dae5 Code coverage report 2016-02-01 14:07:54 +01:00
2aeab7aaff Router Upgrade #3 & bugfix on Cron/Supervisor
- ALC
- Cron
- ImportExport
- Mailer
- Newsletters (only get method for consistency with other router get methods)
- Permissions
2016-02-01 13:00:11 +01:00
4fd0c4b484 Router updates + unit tests + React
- added -f flag to run unit test command in order to fail fast
- pass only id to "$endpoint->get($id)" in React forms instead of array
- updated routers according to the ->get($id) change
- refactored a bit the way form creation works
- added unit tests for Segments router
2016-02-01 11:56:21 +01:00
d4623cf763 Router update for Settings and Setup + unit tests 2016-02-01 11:56:21 +01:00
181c4fed08 - Fixes an issues with the sending queue worker throwing and error when
newsletter is not found
2016-01-31 21:35:34 -05:00
7884dd8389 - Updates code to work with PHP 5.3. Closes #307 2016-01-31 14:02:57 -05:00
119 changed files with 2565 additions and 1805 deletions

View File

@ -1,2 +1,16 @@
WP_TEST_PATH="/var/www/wordpress"
WP_TEST_ENABLE_NETWORK_TESTS="true"
WP_TEST_IMPORT_MAILCHIMP_API=""
WP_TEST_IMPORT_MAILCHIMP_LISTS="" // (separated with comma)
WP_TEST_MAILER_ENABLE_SENDING="true"
WP_TEST_MAILER_AMAZON_ACCESS=""
WP_TEST_MAILER_AMAZON_SECRET=""
WP_TEST_MAILER_AMAZON_REGION=""
WP_TEST_MAILER_ELASTICEMAIL_API=""
WP_TEST_MAILER_MAILGUN_API=""
WP_TEST_MAILER_MAILGUN_DOMAIN=""
WP_TEST_MAILER_MAILPOET_API=""
WP_TEST_MAILER_SENDGRID_API=""
WP_TEST_MAILER_SMTP_HOST=""
WP_TEST_MAILER_SMTP_LOGIN=""
WP_TEST_MAILER_SMTP_PASSWORD=""

View File

@ -105,7 +105,18 @@ class RoboFile extends \Robo\Tasks {
function testUnit($file = null) {
$this->loadEnv();
$this->_exec('vendor/bin/codecept build');
$this->_exec('vendor/bin/codecept run unit '.(($file) ? $file : ''));
$this->_exec('vendor/bin/codecept run unit -f '.(($file) ? $file : ''));
}
function testCoverage($file = null) {
$this->loadEnv();
$this->_exec('vendor/bin/codecept build');
$this->_exec(join(' ', array(
'vendor/bin/codecept run',
(($file) ? $file : ''),
'--coverage',
'--coverage-html'
)));
}
function testJavascript() {

View File

@ -48,7 +48,7 @@ define(
MailPoet.Ajax.post({
endpoint: this.props.endpoint,
action: 'get',
data: { id: id }
data: id
}).done(function(response) {
if(response === false) {
this.setState({

View File

@ -25,58 +25,49 @@ const columns = [
const messages = {
onTrash: function(response) {
if(response) {
let message = null;
if(~~response === 1) {
message = (
'1 form was moved to the trash.'
);
} else if(~~response > 1) {
message = (
'%$1d forms were moved to the trash.'
).replace('%$1d', ~~response);
}
var count = ~~response;
var message = null;
if(message !== null) {
MailPoet.Notice.success(message);
}
if(count === 1) {
message = (
'1 form was moved to the trash.'
);
} else {
message = (
'%$1d forms were moved to the trash.'
).replace('%$1d', count);
}
MailPoet.Notice.success(message);
},
onDelete: function(response) {
if(response) {
let message = null;
if(~~response === 1) {
message = (
'1 form was permanently deleted.'
);
} else if(~~response > 1) {
message = (
'%$1d forms were permanently deleted.'
).replace('%$1d', ~~response);
}
var count = ~~response;
var message = null;
if(message !== null) {
MailPoet.Notice.success(message);
}
if(count === 1) {
message = (
'1 form was permanently deleted.'
);
} else {
message = (
'%$1d forms were permanently deleted.'
).replace('%$1d', count);
}
MailPoet.Notice.success(message);
},
onRestore: function(response) {
if(response) {
let message = null;
if(~~response === 1) {
message = (
'1 form has been restored from the trash.'
);
} else if(~~response > 1) {
message = (
'%$1d forms have been restored from the trash.'
).replace('%$1d', ~~response);
}
var count = ~~response;
var message = null;
if(message !== null) {
MailPoet.Notice.success(message);
}
if(count === 1) {
message = (
'1 form has been restored from the trash.'
);
} else {
message = (
'%$1d forms have been restored from the trash.'
).replace('%$1d', count);
}
MailPoet.Notice.success(message);
}
};
@ -125,8 +116,8 @@ const FormList = React.createClass({
endpoint: 'forms',
action: 'create'
}).done(function(response) {
if(response !== false) {
window.location = response;
if(response.result && response.form_id) {
window.location = mailpoet_form_edit_url + response.form_id;
}
});
},

View File

@ -14,6 +14,9 @@ function(
})
return this.props.onSelectFilter(filters);
},
handleEmptyTrash: function() {
return this.props.onEmptyTrash();
},
getAvailableFilters: function() {
let filters = this.props.filters;
@ -34,7 +37,7 @@ function(
const available_filters = this.getAvailableFilters()
.map(function(filter, i) {
let default_value = false;
if(selected_filters[filter] !== undefined && selected_filters[filter]) {
if (selected_filters[filter] !== undefined && selected_filters[filter]) {
default_value = selected_filters[filter]
} else {
jQuery(`select[name="${filter}"]`).val('');
@ -60,9 +63,10 @@ function(
let button = false;
if(available_filters.length > 0) {
if (available_filters.length > 0) {
button = (
<input
id="post-query-submit"
onClick={ this.handleFilterAction }
type="submit"
defaultValue="Filter"
@ -70,10 +74,23 @@ function(
);
}
let empty_trash = false;
if (this.props.group === 'trash') {
empty_trash = (
<input
onClick={ this.handleEmptyTrash }
type="submit"
value="Empty Trash"
className="button"
/>
);
}
return (
<div className="alignleft actions actions">
{ available_filters }
{ button }
{ empty_trash }
</div>
);
}

View File

@ -74,10 +74,11 @@ define(
);
}
var custom_actions = this.props.item_actions;
var item_actions = false;
const custom_actions = this.props.item_actions;
let item_actions = false;
if(custom_actions.length > 0) {
let is_first = true;
item_actions = custom_actions.map(function(action, index) {
if(action.display !== undefined) {
if(action.display(this.props.item) === false) {
@ -85,10 +86,12 @@ define(
}
}
let custom_action = null;
if(action.name === 'trash') {
return (
custom_action = (
<span key={ 'action-'+index } className="trash">
{(index > 0) ? ' | ' : ''}
{(!is_first) ? ' | ' : ''}
<a
href="javascript:;"
onClick={ this.handleTrashItem.bind(
@ -100,27 +103,27 @@ define(
</span>
);
} else if(action.refresh) {
return (
custom_action = (
<span
onClick={ this.props.onRefreshItems }
key={ 'action-'+index } className={ action.name }>
{(index > 0) ? ' | ' : ''}
{(!is_first) ? ' | ' : ''}
{ action.link(this.props.item) }
</span>
);
} else if(action.link) {
return (
custom_action = (
<span
key={ 'action-'+index } className={ action.name }>
{(index > 0) ? ' | ' : ''}
{(!is_first) ? ' | ' : ''}
{ action.link(this.props.item) }
</span>
);
} else {
return (
custom_action = (
<span
key={ 'action-'+index } className={ action.name }>
{(index > 0) ? ' | ' : ''}
{(!is_first) ? ' | ' : ''}
<a href="javascript:;" onClick={
(action.onClick !== undefined)
? action.onClick.bind(null,
@ -132,6 +135,12 @@ define(
</span>
);
}
if(custom_action !== null && is_first === true) {
is_first = false;
}
return custom_action;
}.bind(this));
} else {
item_actions = (
@ -504,10 +513,21 @@ define(
this.getItems();
}.bind(this));
},
handleEmptyTrash: function() {
this.handleBulkAction('all', {
action: 'delete',
group: 'trash'
}, function(response) {
MailPoet.Notice.success(
MailPoetI18n.permanentlyDeleted.replace('%d', response)
);
});
},
handleBulkAction: function(selected_ids, params, callback) {
if(
this.state.selection === false
&& this.state.selected_ids.length === 0
&& selected_ids !== 'all'
) {
return;
}
@ -520,8 +540,10 @@ define(
limit: 0,
filter: this.state.filter,
group: this.state.group,
search: this.state.search,
selection: selected_ids
search: this.state.search
}
if(selected_ids !== 'all') {
data.listing.selection = selected_ids;
}
MailPoet.Ajax.post({
@ -715,7 +737,10 @@ define(
<ListingFilters
filters={ this.state.filters }
filter={ this.state.filter }
onSelectFilter={ this.handleFilter } />
group={ this.state.group }
onSelectFilter={ this.handleFilter }
onEmptyTrash={ this.handleEmptyTrash }
/>
<ListingPages
count={ this.state.count }
page={ this.state.page }

View File

@ -7,7 +7,11 @@ define(['react', 'classnames'], function(React, classNames) {
}
},
setPage: function(page) {
this.props.onSetPage(page);
this.setState({
page: null
}, function () {
this.props.onSetPage(this.constrainPage(page));
}.bind(this));
},
setFirstPage: function() {
this.setPage(1);
@ -16,10 +20,14 @@ define(['react', 'classnames'], function(React, classNames) {
this.setPage(this.getLastPage());
},
setPreviousPage: function() {
this.setPage(this.constrainPage(this.props.page - 1));
this.setPage(this.constrainPage(
parseInt(this.props.page, 10) - 1)
);
},
setNextPage: function() {
this.setPage(this.constrainPage(this.props.page + 1));
this.setPage(this.constrainPage(
parseInt(this.props.page, 10) + 1)
);
},
constrainPage: function(page) {
return Math.min(Math.max(1, Math.abs(~~page)), this.getLastPage());
@ -27,14 +35,16 @@ define(['react', 'classnames'], function(React, classNames) {
handleSetManualPage: function(e) {
if(e.which === 13) {
this.setPage(this.state.page);
this.setState({ page: null });
}
},
handleChangeManualPage: function(e) {
this.setState({
page: this.constrainPage(e.target.value)
page: e.target.value
});
},
handleBlurManualPage: function(e) {
this.setPage(e.target.value);
},
getLastPage: function() {
return Math.ceil(this.props.count / this.props.limit);
},
@ -101,6 +111,11 @@ define(['react', 'classnames'], function(React, classNames) {
);
}
let pageValue = this.props.page;
if(this.state.page !== null) {
pageValue = this.state.page;
}
pagination = (
<span className="pagination-links">
{firstPage}
@ -115,10 +130,11 @@ define(['react', 'classnames'], function(React, classNames) {
type="text"
onChange={ this.handleChangeManualPage }
onKeyUp={ this.handleSetManualPage }
onBlur={ this.handleBlurManualPage }
aria-describedby="table-paging"
size="1"
ref="page"
value={ this.state.page || this.props.page }
value={ pageValue }
name="paged"
id="current-page-selector"
className="current-page" />

View File

@ -35,7 +35,7 @@ define([
titlePosition: 'inTextBlock', // 'inTextBlock'|'aboveBlock',
titleAlignment: 'left', // 'left'|'center'|'right'
titleIsLink: false, // false|true
imagePadded: true, // true|false
imageFullWidth: false, // true|false
//imageAlignment: 'centerPadded', // 'centerFull'|'centerPadded'|'left'|'right'|'alternate'|'none'
showAuthor: 'no', // 'no'|'aboveText'|'belowText'
authorPrecededBy: 'Author:',
@ -63,7 +63,7 @@ define([
initialize: function() {
base.BlockView.prototype.initialize.apply(this, arguments);
this.fetchPosts();
this.on('change:amount change:contentType change:terms change:inclusionType change:displayType change:titleFormat change:titlePosition change:titleAlignment change:titleIsLink change:imagePadded change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:sortBy change:showDivider', this._scheduleFetchPosts, this);
this.on('change:amount change:contentType change:terms change:inclusionType change:displayType change:titleFormat change:titlePosition change:titleAlignment change:titleIsLink change:imageFullWidth change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:sortBy change:showDivider', this._scheduleFetchPosts, this);
this.listenTo(this.get('readMoreButton'), 'change', this._scheduleFetchPosts);
this.listenTo(this.get('divider'), 'change', this._scheduleFetchPosts);
},
@ -144,7 +144,7 @@ define([
"change .mailpoet_automated_latest_content_include_or_exclude": _.partial(this.changeField, "inclusionType"),
"change .mailpoet_automated_latest_content_title_position": _.partial(this.changeField, "titlePosition"),
"change .mailpoet_automated_latest_content_title_alignment": _.partial(this.changeField, "titleAlignment"),
"change .mailpoet_automated_latest_content_image_padded": _.partial(this.changeBoolField, "imagePadded"),
"change .mailpoet_automated_latest_content_image_full_width": _.partial(this.changeBoolField, "imageFullWidth"),
"change .mailpoet_automated_latest_content_show_author": _.partial(this.changeField, "showAuthor"),
"keyup .mailpoet_automated_latest_content_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
"change .mailpoet_automated_latest_content_show_categories": _.partial(this.changeField, "showCategories"),

View File

@ -20,7 +20,7 @@ define([
link: 'http://example.org',
src: 'no-image.png',
alt: 'An image of...',
padded: true, // true | false - Padded or full width
fullWidth: true, // true | false
width: '64px',
height: '64px',
styles: {
@ -45,10 +45,10 @@ define([
this.toolsView = new Module.ImageBlockToolsView({ model: this.model });
this.toolsRegion.show(this.toolsView);
if (this.model.get('padded')) {
this.$el.removeClass('mailpoet_full_image');
} else {
if (this.model.get('fullWidth')) {
this.$el.addClass('mailpoet_full_image');
} else {
this.$el.removeClass('mailpoet_full_image');
}
},
});
@ -64,7 +64,7 @@ define([
"keyup .mailpoet_field_image_link": _.partial(this.changeField, "link"),
"keyup .mailpoet_field_image_address": _.partial(this.changeField, "src"),
"keyup .mailpoet_field_image_alt_text": _.partial(this.changeField, "alt"),
"change .mailpoet_field_image_padded": _.partial(this.changeBoolCheckboxField, "padded"),
"change .mailpoet_field_image_full_width": _.partial(this.changeBoolCheckboxField, "fullWidth"),
"change .mailpoet_field_image_alignment": _.partial(this.changeField, "styles.block.textAlign"),
"click .mailpoet_field_image_select_another_image": "showMediaManager",
"click .mailpoet_done_editing": "close",

View File

@ -46,7 +46,7 @@ define([
titlePosition: 'inTextBlock', // 'inTextBlock'|'aboveBlock',
titleAlignment: 'left', // 'left'|'center'|'right'
titleIsLink: false, // false|true
imagePadded: true, // true|false
imageFullWidth: false, // true|false
//imageAlignment: 'centerPadded', // 'centerFull'|'centerPadded'|'left'|'right'|'alternate'|'none'
showAuthor: 'no', // 'no'|'aboveText'|'belowText'
authorPrecededBy: 'Author:',
@ -88,7 +88,7 @@ define([
this.on('change:amount change:contentType change:terms change:inclusionType change:postStatus change:search change:sortBy', refreshAvailablePosts);
this.listenTo(this.get('_selectedPosts'), 'add remove reset', refreshTransformedPosts);
this.on('change:displayType change:titleFormat change:titlePosition change:titleAlignment change:titleIsLink change:imagePadded change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:showDivider', refreshTransformedPosts);
this.on('change:displayType change:titleFormat change:titlePosition change:titleAlignment change:titleIsLink change:imageFullWidth change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:showDivider', refreshTransformedPosts);
this.listenTo(this.get('readMoreButton'), 'change', refreshTransformedPosts);
this.listenTo(this.get('divider'), 'change', refreshTransformedPosts);
@ -396,7 +396,7 @@ define([
"change .mailpoet_posts_include_or_exclude": _.partial(this.changeField, "inclusionType"),
"change .mailpoet_posts_title_position": _.partial(this.changeField, "titlePosition"),
"change .mailpoet_posts_title_alignment": _.partial(this.changeField, "titleAlignment"),
"change .mailpoet_posts_image_padded": _.partial(this.changeBoolField, "imagePadded"),
"change .mailpoet_posts_image_full_width": _.partial(this.changeBoolField, "imageFullWidth"),
"change .mailpoet_posts_show_author": _.partial(this.changeField, "showAuthor"),
"keyup .mailpoet_posts_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
"change .mailpoet_posts_show_categories": _.partial(this.changeField, "showCategories"),

View File

@ -11,7 +11,7 @@ define([
// Does not hold newsletter content nor newsletter styles, those are
// handled by other components.
Module.NewsletterModel = SuperModel.extend({
stale: ['body'],
stale: ['body', 'created_at', 'deleted_at', 'updated_at'],
initialize: function(options) {
this.on('change', function() {
App.getChannel().trigger('autoSave');

View File

@ -225,6 +225,11 @@ define([
showPreview: function() {
var json = App.toJSON();
// Stringify to enable transmission of primitive non-string value types
if (!_.isUndefined(json.body)) {
json.body = JSON.stringify(json.body);
}
MailPoet.Ajax.post({
endpoint: 'newsletters',
action: 'render',

View File

@ -43,58 +43,49 @@ define(
var messages = {
onTrash: function(response) {
var count = ~~response.newsletters;
var count = ~~response;
var message = null;
if(count === 1 || response === true) {
if(count === 1) {
message = (
'1 newsletter was moved to the trash.'
);
} else if(count > 1) {
} else {
message = (
'%$1d newsletters were moved to the trash.'
).replace('%$1d', count);
}
if(message !== null) {
MailPoet.Notice.success(message);
}
MailPoet.Notice.success(message);
},
onDelete: function(response) {
var count = ~~response.newsletters;
var count = ~~response;
var message = null;
if(count === 1 || response === true) {
if(count === 1) {
message = (
'1 newsletter was permanently deleted.'
);
} else if(count > 1) {
} else {
message = (
'%$1d newsletters were permanently deleted.'
).replace('%$1d', count);
}
if(message !== null) {
MailPoet.Notice.success(message);
}
MailPoet.Notice.success(message);
},
onRestore: function(response) {
var count = ~~response.newsletters;
var count = ~~response;
var message = null;
if(count === 1 || response === true) {
if(count === 1) {
message = (
'1 newsletter has been restored from the trash.'
);
} else if(count > 1) {
} else {
message = (
'%$1d newsletters have been restored from the trash.'
).replace('%$1d', count);
}
if(message !== null) {
MailPoet.Notice.success(message);
}
MailPoet.Notice.success(message);
}
};

View File

@ -29,7 +29,7 @@ define(
action: 'save',
data: template
}).done(function(response) {
if(response === true) {
if(response.result === true) {
this.props.onImport(template);
} else {
response.map(function(error) {

View File

@ -29,12 +29,14 @@ define(
subject: 'Draft newsletter',
}
}).done(function(response) {
if(response.id !== undefined) {
this.history.pushState(null, `/template/${response.id}`);
if(response.result && response.newsletter.id) {
this.history.pushState(null, `/template/${response.newsletter.id}`);
} else {
response.map(function(error) {
MailPoet.Notice.error(error);
});
if(response.errors.length > 0) {
response.errors.map(function(error) {
MailPoet.Notice.error(error);
});
}
}
}.bind(this));
},

View File

@ -138,12 +138,14 @@ define(
options: this.state,
},
}).done(function(response) {
if(response.id !== undefined) {
this.showTemplateSelection(response.id);
if(response.result && response.newsletter.id) {
this.showTemplateSelection(response.newsletter.id);
} else {
response.map(function(error) {
MailPoet.Notice.error(error);
});
if(response.errors.length > 0) {
response.errors.map(function(error) {
MailPoet.Notice.error(error);
});
}
}
}.bind(this));
},

View File

@ -32,12 +32,15 @@ define(
type: 'standard',
}
}).done(function(response) {
if(response.id !== undefined) {
this.showTemplateSelection(response.id);
console.log(response);
if(response.result && response.newsletter.id) {
this.showTemplateSelection(response.newsletter.id);
} else {
response.map(function(error) {
MailPoet.Notice.error(error);
});
if(response.errors.length > 0) {
response.errors.map(function(error) {
MailPoet.Notice.error(error);
});
}
}
}.bind(this));
},

View File

@ -111,12 +111,14 @@ define(
options: this.state,
},
}).done(function(response) {
if(response.id !== undefined) {
this.showTemplateSelection(response.id);
if(response.result && response.newsletter.id) {
this.showTemplateSelection(response.newsletter.id);
} else {
response.map(function(error) {
MailPoet.Notice.error(error);
});
if(response.errors.length > 0) {
response.errors.map(function(error) {
MailPoet.Notice.error(error);
});
}
}
}.bind(this));
},

View File

@ -192,21 +192,28 @@ define('notice', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
error: function(message, options) {
this.show(jQuery.extend({}, {
type: 'error',
message: '<p>'+message+'</p>'
message: '<p>'+this.formatMessage(message)+'</p>'
}, options));
},
success: function(message, options) {
this.show(jQuery.extend({}, {
type: 'success',
message: '<p>'+message+'</p>'
message: '<p>'+this.formatMessage(message)+'</p>'
}, options));
},
system: function(message, options) {
this.show(jQuery.extend({}, {
type: 'system',
static: true,
message: message
message: '<p>'+this.formatMessage(message)+'</p>'
}, options));
},
formatMessage: function(message) {
if(Array.isArray(message)) {
return message.join('<br />');
} else {
return message;
}
}
};
});

View File

@ -12,7 +12,7 @@ define(
Form
) {
var fields = [
let fields = [
{
name: 'name',
label: 'Name',
@ -25,7 +25,7 @@ define(
}
];
var messages = {
const messages = {
onUpdate: function() {
MailPoet.Notice.success('Segment successfully updated!');
},
@ -34,7 +34,7 @@ define(
}
};
var SegmentForm = React.createClass({
const SegmentForm = React.createClass({
mixins: [
Router.History
],

View File

@ -42,58 +42,49 @@ var columns = [
const messages = {
onTrash: function(response) {
if(response) {
let message = null;
if(~~response === 1) {
message = (
'1 segment was moved to the trash.'
);
} else if(~~response > 1) {
message = (
'%$1d segments were moved to the trash.'
).replace('%$1d', ~~response);
}
var count = ~~response;
var message = null;
if(message !== null) {
MailPoet.Notice.success(message);
}
if(count === 1) {
message = (
'1 segment was moved to the trash.'
);
} else {
message = (
'%$1d segments were moved to the trash.'
).replace('%$1d', count);
}
MailPoet.Notice.success(message);
},
onDelete: function(response) {
if(response) {
let message = null;
if(~~response === 1) {
message = (
'1 segment was permanently deleted.'
);
} else if(~~response > 1) {
message = (
'%$1d segments were permanently deleted.'
).replace('%$1d', ~~response);
}
var count = ~~response;
var message = null;
if(message !== null) {
MailPoet.Notice.success(message);
}
if(count === 1) {
message = (
'1 segment was permanently deleted.'
);
} else {
message = (
'%$1d segments were permanently deleted.'
).replace('%$1d', count);
}
MailPoet.Notice.success(message);
},
onRestore: function(response) {
if(response) {
let message = null;
if(~~response === 1) {
message = (
'1 segment has been restored from the trash.'
);
} else if(~~response > 1) {
message = (
'%$1d segments have been restored from the trash.'
).replace('%$1d', ~~response);
}
var count = ~~response;
var message = null;
if(message !== null) {
MailPoet.Notice.success(message);
}
if(count === 1) {
message = (
'1 segment has been restored from the trash.'
);
} else {
message = (
'%$1d segments have been restored from the trash.'
).replace('%$1d', count);
}
MailPoet.Notice.success(message);
}
};
@ -105,6 +96,9 @@ const item_actions = [
return (
<Link to={ `/edit/${item.id}` }>Edit</Link>
);
},
display: function(segment) {
return (segment.type !== 'wp_users');
}
},
{

View File

@ -193,7 +193,7 @@ define(
}).done(function (response) {
if (response.result === false) {
MailPoet.Notice.hide();
MailPoet.Notice.error(response.error, {
MailPoet.Notice.error(response.errors, {
timeout: 3000,
});
jQuery('.mailpoet_mailchimp-key-status')
@ -245,7 +245,7 @@ define(
}
else {
MailPoet.Notice.hide();
MailPoet.Notice(response.message, {
MailPoet.Notice.error(response.errors, {
timeout: 3000,
});
}
@ -1082,7 +1082,7 @@ define(
}).done(function (response) {
MailPoet.Modal.loading(false);
if (response.result === false) {
MailPoet.Notice.error(response.error, {
MailPoet.Notice.error(response.errors, {
timeout: 3000,
});
} else {

View File

@ -19,3 +19,12 @@ modules:
user: ''
password: ''
dump: tests/_data/dump.sql
coverage:
enabled: true
whitelist:
include:
- lib/*
exclude:
blacklist:
include:
exclude:

View File

@ -36,8 +36,9 @@ class Env {
self::$views_path = self::$path . '/views';
self::$assets_path = self::$path . '/assets';
self::$assets_url = plugins_url('/assets', $file);
self::$temp_path = wp_upload_dir()['path'];
self::$temp_URL = wp_upload_dir()['url'];
$wp_upload_dir = wp_upload_dir();
self::$temp_path = $wp_upload_dir['path'];
self::$temp_URL = $wp_upload_dir['url'];
self::$languages_path = self::$path . '/lang';
self::$lib_path = self::$path . '/lib';
self::$plugin_prefix = 'mailpoet_';
@ -72,19 +73,4 @@ class Env {
);
return implode('', $source_name);
}
static function isPluginActivated() {
$activatesPlugins = get_option('active_plugins');
$isActivated = (
in_array(
sprintf('%s/%s.php', basename(self::$path), self::$plugin_name),
$activatesPlugins
) ||
in_array(
sprintf('%s/%s.php', explode('/', plugin_basename(__FILE__))[0], self::$plugin_name),
$activatesPlugins
)
);
return ($isActivated) ? true : false;
}
}

View File

@ -9,10 +9,17 @@ class Hooks {
function init() {
// Subscribe in comments
if((bool)Setting::getValue('subscribe.on_comment.enabled')) {
add_action(
'comment_form_after_fields',
'\MailPoet\Subscription\Comment::extendForm'
);
if(is_user_logged_in()) {
add_action(
'comment_form_field_comment',
'\MailPoet\Subscription\Comment::extendLoggedInForm'
);
} else {
add_action(
'comment_form_after_fields',
'\MailPoet\Subscription\Comment::extendLoggedOutForm'
);
}
add_action(
'comment_post',

View File

@ -9,6 +9,8 @@ use MailPoet\Settings\Pages;
if(!defined('ABSPATH')) exit;
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
class Initializer {
function __construct($params = array(
'file' => '',
@ -18,17 +20,25 @@ class Initializer {
}
function init() {
$this->setupDB();
register_activation_hook(Env::$file, array($this, 'runMigrator'));
register_activation_hook(Env::$file, array($this, 'runPopulator'));
add_action('plugins_loaded', array($this, 'setup'));
add_action('widgets_init', array($this, 'setupWidget'));
}
function setup() {
try {
$this->setupDB();
$this->setupRenderer();
$this->setupLocalizer();
$this->setupMenu();
$this->setupRouter();
$this->setupWidget();
$this->setupAnalytics();
$this->setupPermissions();
$this->setupChangelog();
$this->setupPublicAPI();
$this->setupAnalytics();
$this->setupChangelog();
$this->runQueueSupervisor();
$this->setupShortcodes();
$this->setupHooks();
@ -56,8 +66,6 @@ class Initializer {
$newsletters = Env::$db_prefix . 'newsletters';
$newsletter_templates = Env::$db_prefix . 'newsletter_templates';
$segments = Env::$db_prefix . 'segments';
$filters = Env::$db_prefix . 'filters';
$segment_filter = Env::$db_prefix . 'segment_filter';
$forms = Env::$db_prefix . 'forms';
$subscriber_segment = Env::$db_prefix . 'subscriber_segment';
$newsletter_segment = Env::$db_prefix . 'newsletter_segment';
@ -72,8 +80,6 @@ class Initializer {
define('MP_SETTINGS_TABLE', $settings);
define('MP_NEWSLETTERS_TABLE', $newsletters);
define('MP_SEGMENTS_TABLE', $segments);
define('MP_FILTERS_TABLE', $filters);
define('MP_SEGMENT_FILTER_TABLE', $segment_filter);
define('MP_FORMS_TABLE', $forms);
define('MP_SUBSCRIBER_SEGMENT_TABLE', $subscriber_segment);
define('MP_NEWSLETTER_TEMPLATES_TABLE', $newsletter_templates);
@ -86,8 +92,12 @@ class Initializer {
define('MP_NEWSLETTER_STATISTICS_TABLE', $newsletter_statistics);
}
function runMigrator() {
$migrator = new Migrator();
$migrator->up();
}
function runPopulator() {
$this->init();
$populator = new Populator();
$populator->up();
}
@ -103,10 +113,7 @@ class Initializer {
}
function setupMenu() {
$menu = new Menu(
$this->renderer,
Env::$assets_url
);
$menu = new Menu($this->renderer, Env::$assets_url);
$menu->init();
}
@ -156,9 +163,7 @@ class Initializer {
}
function runQueueSupervisor() {
if(php_sapi_name() === 'cli' ||
!Env::isPluginActivated()
) return;
if(php_sapi_name() === 'cli') return;
try {
$supervisor = new Supervisor();
$supervisor->checkDaemon();

View File

@ -11,8 +11,7 @@ class Localizer {
function init() {
add_action(
'init',
array($this, 'setup'),
0
array($this, 'setup')
);
}

View File

@ -236,10 +236,7 @@ class Migrator {
'newsletter_id mediumint(9) NOT NULL,',
'subscriber_id mediumint(9) NOT NULL,',
'queue_id mediumint(9) NOT NULL,',
'sent_at TIMESTAMP NOT NULL DEFAULT 0,',
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
'deleted_at TIMESTAMP NULL DEFAULT NULL,',
'sent_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
'PRIMARY KEY (id)',
);
return $this->sqlify(__FUNCTION__, $attributes);

View File

@ -68,7 +68,7 @@ class FranksRoastHouseTemplate {
"link" => "http://www.example.com",
"src" => $this->template_image_url . "/header-v2.jpg",
"alt" => __("Frank's Roast House"),
"padded" => false,
"fullWidth" => true,
"width" => "600px",
"height" => "220px",
"styles" => array(
@ -95,7 +95,7 @@ class FranksRoastHouseTemplate {
"link" => "http://example.org",
"src" => $this->template_image_url . "/coffee-grain.jpg",
"alt" => __("coffee-grain-3-1329675-1599x941"),
"padded" => true,
"fullWidth" => false,
"width" => "1599px",
"height" => "777px",
"styles" => array(
@ -139,7 +139,7 @@ class FranksRoastHouseTemplate {
"link" => "http://example.org",
"src" => $this->template_image_url . "/sandwich.jpg",
"alt" => "sandwich",
"padded" => true,
"fullWidth" => false,
"width" => "640px",
"height" => "344px",
"styles" => array(
@ -238,7 +238,7 @@ class FranksRoastHouseTemplate {
"link" => "http://example.org",
"src" => $this->template_image_url . "/map-v2.jpg",
"alt" => __("map-v2"),
"padded" => true,
"fullWidth" => false,
"width" => "636px",
"height" => "342px",
"styles" => array(
@ -279,19 +279,19 @@ class FranksRoastHouseTemplate {
"blocks" => array(
array(
"type" => "footer",
"text" => __("<p><span style=\"color: #000000;\"><a href=\"[unsubscribeUrl]\" style=\"color: #000000;\">Unsubscribe</a> | <a href=\"[manageSubscriptionUrl]\" style=\"color: #000000;\">Manage subscription</a></span><br /><span style=\"color: #000000;\">12345 MailPoet Drive, EmailVille, 76543</span></p>"),
"text" => __("<p><a href=\"[unsubscribeUrl]\">Unsubscribe</a> | <a href=\"[manageSubscriptionUrl]\">Manage subscription</a><br />12345 MailPoet Drive, EmailVille, 76543</p>"),
"styles" => array(
"block" => array(
"backgroundColor" => "#a9a7a7"
),
"text" => array(
"fontColor" => "#ffffff",
"fontColor" => "#000000",
"fontFamily" => "Arial",
"fontSize" => "12px",
"textAlign" => "center"
),
"link" => array(
"fontColor" => "#ffffff",
"fontColor" => "#000000",
"textDecoration" => "underline"
)
)

View File

@ -90,7 +90,7 @@ class PostNotificationsBlankTemplate {
"link" => "http://example.org",
"src" => $this->template_image_url . "/ALC-widget-icon.png",
"alt" => __("ALC-widget-icon"),
"padded" => true,
"fullWidth" => false,
"width" => "200px",
"height" => "134px",
"styles" => array(

View File

@ -68,7 +68,7 @@ class WelcomeTemplate {
"link" => "http://example.org",
"src" => $this->template_image_url . "/logo-header.gif",
"alt" => "logo-header",
"padded" => true,
"fullWidth" => false,
"width" => "233px",
"height" => "118px",
"styles" => array(

View File

@ -9,13 +9,12 @@ class Widget {
}
function init() {
add_action('widgets_init', array($this, 'registerWidget'));
$this->registerWidget();
if(!is_admin()) {
//$this->setupActions();
add_action('widgets_init', array($this, 'setupDependencies'));
$this->setupDependencies();
} else {
add_action('widgets_init', array($this, 'setupAdminDependencies'));
$this->setupAdminDependencies();
}
}
@ -69,6 +68,9 @@ class Widget {
}
}
// TODO: extract this method into an Initializer
// - the "ajax" part might probably be useless
// - the "post" (non-ajax) part needs to be redone properly
function setupActions() {
// ajax requests
add_action(

View File

@ -7,8 +7,9 @@ use MailPoet\Util\Security;
if(!defined('ABSPATH')) exit;
class CronHelper {
static $daemon_execution_limit = 30;
static $daemon_timeout_limit = 30;
const daemon_execution_limit = 20;
const daemon_execution_timeout = 35;
const daemon_request_timeout = 2;
static function createDaemon($token) {
$daemon = array(
@ -36,12 +37,12 @@ class CronHelper {
return Security::generateRandomString();
}
static function accessDaemon($token) {
static function accessDaemon($token, $timeout = self::daemon_request_timeout) {
$payload = serialize(array('token' => $token));
$url = '/?mailpoet-api&section=queue&action=run&request_payload=' .
base64_encode($payload);
$args = array(
'timeout' => 1,
'timeout' => $timeout,
'user-agent' => 'MailPoet (www.mailpoet.com) Cron'
);
$result = wp_remote_get(

View File

@ -11,6 +11,7 @@ class Daemon {
public $daemon;
public $request_payload;
public $refreshed_token;
const daemon_request_timeout = 5;
private $timer;
function __construct($request_payload = array()) {
@ -36,11 +37,11 @@ class Daemon {
try {
$sending_queue = new SendingQueue($this->timer);
$sending_queue->process();
} catch(Exception $e) {
} catch(\Exception $e) {
}
$elapsed_time = microtime(true) - $this->timer;
if($elapsed_time < CronHelper::$daemon_execution_limit) {
sleep(CronHelper::$daemon_execution_limit - $elapsed_time);
if($elapsed_time < CronHelper::daemon_execution_limit) {
sleep(CronHelper::daemon_execution_limit - $elapsed_time);
}
// after each execution, re-read daemon data in case it was deleted or
// its status has changed
@ -72,7 +73,7 @@ class Daemon {
}
function callSelf() {
CronHelper::accessDaemon($this->token);
CronHelper::accessDaemon($this->token, self::daemon_request_timeout);
exit;
}
}

View File

@ -31,13 +31,13 @@ class Supervisor {
$elapsed_time = time() - (int) $daemon['updated_at'];
// if it's been less than 40 seconds since last execution and we're not
// force-running the daemon, return its status and do nothing
if($elapsed_time < CronHelper::$daemon_timeout_limit && !$this->force_run) {
if($elapsed_time < CronHelper::daemon_execution_timeout && !$this->force_run) {
return $this->formatDaemonStatusMessage($daemon['status']);
}
// if it's been less than 40 seconds since last execution, we are
// force-running the daemon and it's either being started or stopped,
// return its status and do nothing
elseif($elapsed_time < CronHelper::$daemon_timeout_limit &&
elseif($elapsed_time < CronHelper::daemon_execution_timeout &&
$this->force_run &&
in_array($daemon['status'], array(
'stopping',
@ -62,7 +62,7 @@ class Supervisor {
list(, $message) = explode(':', $status[0]);
$message = base64_decode($message);
}
return $this->formatResult(
return $this->formatResultMessage(
false,
$message
);

View File

@ -5,125 +5,186 @@ use MailPoet\Cron\CronHelper;
use MailPoet\Mailer\Mailer;
use MailPoet\Models\Newsletter;
use MailPoet\Models\NewsletterStatistics;
use MailPoet\Models\Setting;
use MailPoet\Models\Subscriber;
use MailPoet\Newsletter\Renderer\Renderer;
use MailPoet\Newsletter\Shortcodes\Shortcodes;
use MailPoet\Util\Helpers;
if(!defined('ABSPATH')) exit;
class SendingQueue {
public $mta_config;
public $mta_log;
public $processing_method;
private $timer;
const batch_size = 50;
function __construct($timer = false) {
$this->mta_config = $this->getMailerConfig();
$this->mta_log = $this->getMailerLog();
$this->processing_method = ($this->mta_config['method'] === 'MailPoet') ?
'processBulkSubscribers' :
'processIndividualSubscriber';
$this->timer = ($timer) ? $timer : microtime(true);
}
function process() {
// TODO: implement mailer sending frequency limits
foreach($this->getQueues() as $queue) {
$newsletter = Newsletter::findOne($queue->newsletter_id)
->asArray();
$newsletter = Newsletter::findOne($queue->newsletter_id);
if(!$newsletter) {
continue;
};
$mailer = $this->configureMailerForNewsletter($newsletter);
$subscribers = json_decode($queue->subscribers, true);
$subscribers_to_process = $subscribers['to_process'];
if(!isset($subscribers['processed'])) $subscribers['processed'] = array();
if(!isset($subscribers['failed'])) $subscribers['failed'] = array();
foreach(array_chunk($subscribers_to_process, 200) as $subscriber_ids) {
$db_subscribers = Subscriber::whereIn('id', $subscriber_ids)
}
$queue->subscribers = (object) unserialize($queue->subscribers);
if(!isset($queue->subscribers->processed)) {
$queue->subscribers->processed = array();
}
if(!isset($queue->subscribers->failed)) {
$queue->subscribers->failed = array();
}
$newsletter = $newsletter->asArray();
$newsletter['body'] = $this->renderNewsletter($newsletter);
$mailer = $this->configureMailer($newsletter);
foreach(array_chunk($queue->subscribers->to_process, self::batch_size) as
$subscribers_ids) {
$subscribers = Subscriber::whereIn('id', $subscribers_ids)
->findArray();
foreach($db_subscribers as $db_subscriber) {
$this->checkExecutionTimer();
$result = $this->sendNewsletter(
$queue->subscribers = call_user_func_array(
array(
$this,
$this->processing_method
),
array(
$mailer,
$this->processNewsletter($newsletter, $db_subscriber),
$db_subscriber);
if($result) {
$this->updateStatistics($newsletter['id'], $db_subscriber['id'], $queue->id);
$subscribers['processed'][] = $db_subscriber['id'];
} else {
$subscribers['failed'][] = $db_subscriber['id'];
}
$this->updateQueue($queue, $subscribers);
}
$newsletter,
$subscribers,
$queue
)
);
}
}
}
function processNewsletter($newsletter, $subscriber) {
$rendered_newsletter = $this->renderNewsletter($newsletter);
$shortcodes = new Shortcodes($rendered_newsletter['body']['html'], $newsletter, $subscriber);
$processed_newsletter['body']['html'] = $shortcodes->replace();
$shortcodes = new Shortcodes($rendered_newsletter['body']['text'], $newsletter, $subscriber);
$processed_newsletter['body']['text'] = $shortcodes->replace();
$processed_newsletter['subject'] = $rendered_newsletter['subject'];
return $processed_newsletter;
function processBulkSubscribers($mailer, $newsletter, $subscribers, $queue) {
foreach($subscribers as $subscriber) {
$processed_newsletters[] =
$this->processNewsletter($newsletter, $subscriber);
$transformed_subscribers[] =
$mailer->transformSubscriber($subscriber);
}
$result = $this->sendNewsletter(
$mailer,
$processed_newsletters,
$transformed_subscribers
);
$subscribers_ids = Helpers::arrayColumn($subscribers, 'id');
if(!$result) {
$queue->subscribers->failed = array_merge(
$queue->subscribers->failed,
$subscribers_ids
);
} else {
$newsletter_statistics =
array_map(function ($data) use ($newsletter, $subscribers_ids, $queue) {
return array(
$newsletter['id'],
$subscribers_ids[$data],
$queue->id
);
}, range(0, count($transformed_subscribers) - 1));
$newsletter_statistics = Helpers::flattenArray($newsletter_statistics);
$this->updateMailerLog();
$this->updateNewsletterStatistics($newsletter_statistics);
$queue->subscribers->processed = array_merge(
$queue->subscribers->processed,
$subscribers_ids
);
}
$this->updateQueue($queue);
$this->checkSendingLimit();
$this->checkExecutionTimer();
return $queue->subscribers;
}
function processIndividualSubscriber($mailer, $newsletter, $subscribers, $queue) {
foreach($subscribers as $subscriber) {
$this->checkSendingLimit();
$processed_newsletter = $this->processNewsletter($newsletter, $subscriber);
$transformed_subscriber = $mailer->transformSubscriber($subscriber);
$result = $this->sendNewsletter(
$mailer,
$processed_newsletter,
$transformed_subscriber
);
if(!$result) {
$queue->subscribers->failed[] = $subscriber['id'];;
} else {
$queue->subscribers->processed[] = $subscriber['id'];
$newsletter_statistics = array(
$newsletter['id'],
$subscriber['id'],
$queue->id
);
$this->updateMailerLog();
$this->updateNewsletterStatistics($newsletter_statistics);
}
$this->updateQueue($queue);
$this->checkExecutionTimer();
}
return $queue->subscribers;
}
function updateNewsletterStatistics($data) {
return NewsletterStatistics::createMultiple($data);
}
function renderNewsletter($newsletter) {
$renderer = new Renderer($newsletter);
return $renderer->render();
}
function processNewsletter($newsletter, $subscriber = false) {
$divider = '***MailPoet***';
$shortcodes = new Shortcodes(
implode($divider, $newsletter['body']),
$newsletter,
$subscriber
);
list($newsletter['body']['html'], $newsletter['body']['text']) =
explode($divider, $shortcodes->replace());
return $newsletter;
}
function sendNewsletter($mailer, $newsletter, $subscriber) {
return $mailer->mailer_instance->send(
$newsletter,
$mailer->transformSubscriber($subscriber)
$subscriber
);
}
function updateStatistics($newsletter_id, $subscriber_id, $queue_id) {
$newsletter_statistic = NewsletterStatistics::create();
$newsletter_statistic->subscriber_id = $newsletter_id;
$newsletter_statistic->newsletter_id = $subscriber_id;
$newsletter_statistic->queue_id = $queue_id;
$newsletter_statistic->save();
}
function updateQueue($queue, $subscribers) {
$subscribers['to_process'] = array_values(
array_diff(
$subscribers['to_process'],
array_merge($subscribers['processed'], $subscribers['failed'])
)
);
$queue->count_processed =
count($subscribers['processed']) + count($subscribers['failed']);
$queue->count_to_process = count($subscribers['to_process']);
$queue->count_failed = count($subscribers['failed']);
$queue->count_total =
$queue->count_processed + $queue->count_to_process;
if(!$queue->count_to_process) {
$queue->processed_at = date('Y-m-d H:i:s');
$queue->status = 'completed';
}
$queue->subscribers = json_encode($subscribers);
$queue->save();
}
function configureMailerForNewsletter($newsletter) {
if(!empty($newsletter['sender_address']) && !empty($newsletter['sender_name'])) {
$sender = array(
'name' => $newsletter['sender_name'],
'address' => $newsletter['sender_address']
);
} else {
function configureMailer($newsletter) {
$sender['address'] = (!empty($newsletter['sender_address'])) ?
$newsletter['sender_address'] :
false;
$sender['name'] = (!empty($newsletter['sender_name'])) ?
$newsletter['sender_name'] :
false;
$reply_to['address'] = (!empty($newsletter['reply_to_address'])) ?
$newsletter['reply_to_address'] :
false;
$reply_to['name'] = (!empty($newsletter['reply_to_name'])) ?
$newsletter['reply_to_name'] :
false;
if(!$sender['address']) {
$sender = false;
}
if(!empty($newsletter['reply_to_address']) && !empty($newsletter['reply_to_name'])) {
$reply_to = array(
'name' => $newsletter['reply_to_name'],
'address' => $newsletter['reply_to_address']
);
} else {
if(!$reply_to['address']) {
$reply_to = false;
}
$mailer = new Mailer($method = false, $sender, $reply_to);
return $mailer;
}
function checkExecutionTimer() {
$elapsed_time = microtime(true) - $this->timer;
if($elapsed_time >= CronHelper::$daemon_execution_limit) throw new \Exception(__('Maximum execution time reached.'));
}
function getQueues() {
return \MailPoet\Models\SendingQueue::orderByDesc('priority')
->whereNull('deleted_at')
@ -131,9 +192,78 @@ class SendingQueue {
->findResultSet();
}
function renderNewsletter($newsletter) {
$renderer = new Renderer($newsletter);
$newsletter['body'] = $renderer->render();
return $newsletter;
function updateQueue($queue) {
$queue = clone($queue);
$queue->subscribers->to_process = array_diff(
$queue->subscribers->to_process,
array_merge(
$queue->subscribers->processed,
$queue->subscribers->failed
)
);
$queue->subscribers->to_process = array_values($queue->subscribers->to_process);
$queue->count_processed =
count($queue->subscribers->processed) + count($queue->subscribers->failed);
$queue->count_to_process = count($queue->subscribers->to_process);
$queue->count_failed = count($queue->subscribers->failed);
$queue->count_total =
$queue->count_processed + $queue->count_to_process;
if(!$queue->count_to_process) {
$queue->processed_at = date('Y-m-d H:i:s');
$queue->status = 'completed';
}
$queue->subscribers = serialize((array) $queue->subscribers);
$queue->save();
}
function updateMailerLog() {
$this->mta_log['sent']++;
return Setting::setValue('mta_log', $this->mta_log);
}
function getMailerConfig() {
$mta_config = Setting::getValue('mta');
if(!$mta_config) {
throw new \Exception(__('Mailer is not configured.'));
}
return $mta_config;
}
function getMailerLog() {
$mta_log = Setting::getValue('mta_log');
if(!$mta_log) {
$mta_log = array(
'sent' => 0,
'started' => time()
);
Setting::setValue('mta_log', $mta_log);
}
return $mta_log;
}
function checkSendingLimit() {
$frequency_interval = (int) $this->mta_config['frequency']['interval'] * 60;
$frequency_limit = (int) $this->mta_config['frequency']['emails'];
$elapsed_time = time() - (int) $this->mta_log['started'];
if($this->mta_log['sent'] === $frequency_limit &&
$elapsed_time <= $frequency_interval
) {
throw new \Exception(__('Sending frequency limit reached.'));
}
if($elapsed_time > $frequency_interval) {
$this->mta_log = array(
'sent' => 0,
'started' => time()
);
Setting::setValue('mta_log', $this->mta_log);
}
return;
}
function checkExecutionTimer() {
$elapsed_time = microtime(true) - $this->timer;
if($elapsed_time >= CronHelper::daemon_execution_limit) {
throw new \Exception(__('Maximum execution time reached.'));
}
}
}

View File

@ -13,9 +13,11 @@ class Renderer {
return $html;
}
static function renderStyles($form = array()) {
static function renderStyles($form = array(), $prefix = null) {
$styles = new Util\Styles(static::getStyles($form));
$html = '<style type="text/css">';
$html .= static::getStyles($form);
$html .= $styles->render($prefix);
$html .= '</style>';
return $html;

View File

@ -101,7 +101,7 @@ EOL;
}
private function stripComments($stylesheet) {
// remove comments
// remove comments
return preg_replace('!/\*.*?\*/!s', '', $stylesheet);
}
@ -111,7 +111,6 @@ EOL;
private function setStyles($styles) {
$this->_styles = $styles;
return $this;
}

View File

@ -65,6 +65,8 @@ class Widget extends \WP_Widget {
)
);
$form_edit_url = admin_url('admin.php?page=mailpoet-form-editor&id=');
// set title
$title = isset($instance['title']) ? strip_tags($instance['title']) : '';
@ -102,8 +104,9 @@ class Widget extends \WP_Widget {
endpoint: 'forms',
action: 'create'
}).done(function(response) {
if(response !== false) {
window.location = response;
if(response.result && response.form_id) {
window.location =
"<?php echo $form_edit_url; ?>" + response.form_id;
}
});
return false;
@ -151,12 +154,14 @@ class Widget extends \WP_Widget {
$output = '';
if(!empty($body)) {
$form_id = $this->id_base.'_'.$this->number;
$data = array(
'form_id' => $this->id_base.'_'.$this->number,
'form_id' => $form_id,
'form_type' => $form_type,
'form' => $form,
'title' => $title,
'styles' => FormRenderer::renderStyles($form),
'styles' => FormRenderer::renderStyles($form, '#'.$form_id),
'html' => FormRenderer::renderHTML($form),
'before_widget' => (!empty($before_widget) ? $before_widget : ''),
'after_widget' => (!empty($after_widget) ? $after_widget : ''),

View File

@ -102,7 +102,7 @@ class Mailer {
function getSender($sender = false) {
if(!$sender) {
$sender = Setting::getValue('sender', null);
if(!$sender) throw new \Exception(__('Sender name and email are not configured.'));
if(!$sender['address']) throw new \Exception(__('Sender name and email are not configured.'));
}
return array(
'from_name' => $sender['name'],
@ -122,7 +122,7 @@ class Mailer {
}
}
if(!$reply_to['address']) {
$reply_to['reply_to_email'] = $this->sender['from_email'];
$reply_to['address'] = $this->sender['from_email'];
}
return array(
'reply_to_name' => $reply_to['name'],

View File

@ -20,10 +20,11 @@ class SendGrid {
$this->url,
$this->request($newsletter, $subscriber)
);
$result_body = json_decode($result['body'], true);
return (
!is_wp_error($result) === true &&
!preg_match('!invalid!', $result['body']) === true &&
!isset(json_decode($result['body'], true)['errors']) === true &&
!isset($result_body['errors']) === true &&
wp_remote_retrieve_response_code($result) === 200
);
}

View File

@ -19,20 +19,22 @@ class CustomField extends Model {
function asArray() {
$model = parent::asArray();
$model['params'] = (
is_serialized($this->params)
? unserialize($this->params)
: $this->params
);
if(isset($model['params'])) {
$model['params'] = (is_array($this->params))
? $this->params
: unserialize($this->params);
}
return $model;
}
function save() {
if(is_null($this->params)) {
$this->params = array();
}
$this->set('params', (
is_serialized($this->params)
? $this->params
: serialize($this->params)
is_array($this->params)
? serialize($this->params)
: $this->params
));
return parent::save();
}
@ -66,12 +68,6 @@ class CustomField extends Model {
$custom_field->set($data);
}
try {
$custom_field->save();
return $custom_field;
} catch(Exception $e) {
return $custom_field->getValidationErrors();
}
return false;
return $custom_field->save();
}
}

View File

@ -1,16 +0,0 @@
<?php namespace MailPoet\Models;
class CustomValidator {
function __construct() {
$this->validator = new \Sudzy\Engine();
}
function init() {
$this->validator
->addValidator('isString', function ($val) {
return is_string($val);
});
return $this->validator;
}
}

View File

@ -1,50 +0,0 @@
<?php
namespace MailPoet\Models;
if(!defined('ABSPATH')) exit;
class Filter extends Model {
static $_table = MP_FILTERS_TABLE;
function __construct() {
parent::__construct();
$this->addValidations('name', array(
'required' => __('You need to specify a name.')
));
}
function delete() {
// delete all relations to subscribers
SegmentFilter::where('filter_id', $this->id)->deleteMany();
return parent::delete();
}
function segments() {
return $this->has_many_through(
__NAMESPACE__.'\Segment',
__NAMESPACE__.'\SegmentFilter',
'filter_id',
'segment_id'
);
}
static function createOrUpdate($data = array()) {
$filter = false;
if(isset($data['id']) && (int)$data['id'] > 0) {
$filter = self::findOne((int)$data['id']);
}
if($filter === false) {
$filter = self::create();
$filter->hydrate($data);
} else {
unset($data['id']);
$filter->set($data);
}
$filter->save();
return $filter;
}
}

View File

@ -17,36 +17,30 @@ class Form extends Model {
function asArray() {
$model = parent::asArray();
$model['body'] = (
is_serialized($this->body)
$model['body'] = (is_serialized($this->body))
? unserialize($this->body)
: $this->body
);
$model['settings'] = (
is_serialized($this->settings)
: $this->body;
$model['settings'] = (is_serialized($this->settings))
? unserialize($this->settings)
: $this->settings
);
: $this->settings;
return $model;
}
function save() {
$this->set('body', (
is_serialized($this->body)
$this->set('body', (is_serialized($this->body))
? $this->body
: serialize($this->body)
));
$this->set('settings', (
is_serialized($this->settings)
);
$this->set('settings', (is_serialized($this->settings))
? $this->settings
: serialize($this->settings)
));
);
return parent::save();
}
static function search($orm, $search = '') {
return $orm->where_like('name', '%'.$search.'%');
return $orm->whereLike('name', '%'.$search.'%');
}
static function groups() {
@ -67,9 +61,8 @@ class Form extends Model {
static function groupBy($orm, $group = null) {
if($group === 'trash') {
return $orm->whereNotNull('deleted_at');
} else {
$orm = $orm->whereNull('deleted_at');
}
return $orm->whereNull('deleted_at');
}
static function createOrUpdate($data = array()) {
@ -87,7 +80,6 @@ class Form extends Model {
$form->set($data);
}
$form->save();
return $form;
return $form->save();
}
}

View File

@ -4,25 +4,65 @@ namespace MailPoet\Models;
if(!defined('ABSPATH')) exit;
class Model extends \Sudzy\ValidModel {
protected $_errors;
function __construct() {
$customValidators = new CustomValidator();
parent::__construct($customValidators->init());
$this->_errors = array();
parent::__construct();
}
static function create() {
return parent::create();
}
function getErrors() {
if(empty($this->_errors)) {
return false;
} else {
return $this->_errors;
}
}
function setError($error = '') {
if(!empty($error)) {
if(is_array($error)) {
$this->_errors = array_merge($this->_errors, $error);
$this->_errors = array_unique($this->_errors);
} else {
$this->_errors[] = $error;
}
}
}
function save() {
$this->setTimestamp();
try {
parent::save();
return true;
} catch (\Sudzy\ValidationException $e) {
return array_unique($e->getValidationErrors());
} catch (\PDOException $e) {
return $e->getMessage();
} catch(\Sudzy\ValidationException $e) {
$this->setError($e->getValidationErrors());
} catch(\PDOException $e) {
switch($e->getCode()) {
case 23000:
preg_match("/for key \'(.*?)\'/i", $e->getMessage(), $matches);
if(isset($matches[1])) {
$column = $matches[1];
$this->setError(
sprintf(
__('Another record already exists. Please specify a different "%1$s".'),
$column
)
);
} else {
$this->setError($e->getMessage());
}
break;
default:
$this->setError($e->getMessage());
}
} catch(\Exception $e) {
$this->setError($e->getMessage());
}
return $this;
}
function trash() {

View File

@ -8,6 +8,10 @@ class Newsletter extends Model {
function __construct() {
parent::__construct();
$this->addValidations('type', array(
'required' => __('You need to specify a type.')
));
}
function save() {
@ -15,9 +19,23 @@ class Newsletter extends Model {
$this->set_expr('deleted_at', 'NULL');
}
$this->set('body',
is_array($this->body)
? json_encode($this->body)
: $this->body
);
return parent::save();
}
function asArray() {
$model = parent::asArray();
if(isset($model['body'])) {
$model['body'] = json_decode($model['body'], true);
}
return $model;
}
function delete() {
// delete all relations to segments
NewsletterSegment::where('newsletter_id', $this->id)->deleteMany();
@ -79,14 +97,13 @@ class Newsletter extends Model {
}
static function filterBy($orm, $filters = null) {
if(empty($filters)) {
return $orm;
}
foreach($filters as $key => $value) {
if($key === 'segment') {
$segment = Segment::findOne($value);
if($segment !== false) {
$orm = $segment->newsletters();
if(!empty($filters)) {
foreach($filters as $key => $value) {
if($key === 'segment') {
$segment = Segment::findOne($value);
if($segment !== false) {
$orm = $segment->newsletters();
}
}
}
}

View File

@ -9,4 +9,16 @@ class NewsletterStatistics extends Model {
function __construct() {
parent::__construct();
}
static function createMultiple($data) {
return self::rawExecute(
'INSERT INTO `' . NewsletterStatistics::$_table . '` ' .
'(newsletter_id, subscriber_id, queue_id) ' .
'VALUES ' . rtrim(
str_repeat('(?,?,?), ', count($data)/3),
', '
),
$data
);
}
}

View File

@ -17,6 +17,14 @@ class NewsletterTemplate extends Model {
));
}
function asArray() {
$template = parent::asArray();
if(isset($template['body'])) {
$template['body'] = json_decode($template['body'], true);
}
return $template;
}
static function createOrUpdate($data = array()) {
$template = false;
@ -32,16 +40,7 @@ class NewsletterTemplate extends Model {
$template->set($data);
}
$saved = $template->save();
if($saved === true) {
return true;
} else {
$errors = $template->getValidationErrors();
if(!empty($errors)) {
return $errors;
}
}
return false;
$template->save();
return $template;
}
}

View File

@ -122,6 +122,7 @@ class Segment extends Model {
->group_by(self::$_table.'.id')
->group_by(self::$_table.'.name')
->where(self::$_table.'.type', 'default')
->whereNull(self::$_table.'.deleted_at')
->findArray();
}
@ -164,8 +165,7 @@ class Segment extends Model {
$segment->set($data);
}
$segment->save();
return $segment;
return $segment->save();
}
static function getPublic() {

View File

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

View File

@ -15,7 +15,8 @@ class SendingQueue extends Model {
return false;
} else {
$this->set('status', 'paused');
return $this->save();
$this->save();
return ($this->getErrors() === false && $this->id() > 0);
}
}
@ -24,12 +25,14 @@ class SendingQueue extends Model {
return $this->complete();
} else {
$this->set_expr('status', 'NULL');
return $this->save();
$this->save();
return ($this->getErrors() === false && $this->id() > 0);
}
}
function complete() {
$this->set('status', 'completed');
return $this->save();
$this->save();
return ($this->getErrors() === false && $this->id() > 0);
}
}

View File

@ -10,8 +10,7 @@ class Setting extends Model {
parent::__construct();
$this->addValidations('name', array(
'required' => 'name_is_blank',
'isString' => 'name_is_not_string'
'required' => __('You need to specify a name.')
));
}
@ -36,6 +35,9 @@ class Setting extends Model {
if($setting !== $default) {
for($i = 0, $count = count($keys); $i < $count; $i++) {
if(!is_array($setting)) {
$setting = array();
}
if(array_key_exists($keys[$i], $setting)) {
$setting = $setting[$keys[$i]];
} else {
@ -55,10 +57,11 @@ class Setting extends Model {
$value = serialize($value);
}
return Setting::createOrUpdate(array(
$setting = Setting::createOrUpdate(array(
'name' => $key,
'value' => $value
));
return ($setting->id() > 0 && $setting->getErrors() === false);
} else {
$main_key = array_shift($keys);
@ -67,13 +70,6 @@ class Setting extends Model {
$last_key = array_pop($keys);
foreach($keys as $key) {
if(!is_array($current_value)) {
$current_value = array();
}
if(!array_key_exists($key, $current_value)) {
$current_value = array($key => array());
}
$current_value =& $current_value[$key];
}
if(is_scalar($current_value)) {
@ -100,17 +96,20 @@ class Setting extends Model {
return $settings;
}
public static function createOrUpdate($model) {
$exists = self::where('name', $model['name'])
->find_one();
public static function createOrUpdate($data = array()) {
$setting = false;
if($exists === false) {
$new_model = self::create();
$new_model->hydrate($model);
return $new_model->save();
if(isset($data['name'])) {
$setting = self::where('name', $data['name'])->findOne();
}
$exists->value = $model['value'];
return $exists->save();
if($setting === false) {
$setting = self::create();
$setting->hydrate($data);
} else {
$setting->value = $data['value'];
}
return $setting->save();
}
}

View File

@ -33,12 +33,17 @@ class Subscriber extends Model {
}
function addToSegments(array $segment_ids = array()) {
$segments = Segment::whereIn('id', $segment_ids)->findMany();
foreach($segments as $segment) {
$association = SubscriberSegment::create();
$association->subscriber_id = $this->id;
$association->segment_id = $segment->id;
$association->save();
// delete all relations to segments
SubscriberSegment::where('subscriber_id', $this->id)->deleteMany();
if(!empty($segment_ids)) {
$segments = Segment::whereIn('id', $segment_ids)->findMany();
foreach($segments as $segment) {
$association = SubscriberSegment::create();
$association->subscriber_id = $this->id;
$association->segment_id = $segment->id;
$association->save();
}
}
}
@ -53,7 +58,7 @@ class Subscriber extends Model {
return false;
}
$subscriber = static::createOrUpdate($subscriber_data);
$subscriber = self::createOrUpdate($subscriber_data);
if($subscriber !== false && $subscriber->id() > 0) {
// restore deleted subscriber
@ -92,20 +97,25 @@ class Subscriber extends Model {
$segments = Segment::orderByAsc('name')->findMany();
$segment_list = array();
$segment_list[] = array(
'label' => __('All lists'),
'label' => __('All segments'),
'value' => ''
);
$segment_list[] = array(
'label' => sprintf(
__('Subscribers without a segment (%d)'),
self::filter('withoutSegments')->count()
),
'value' => 'none'
);
foreach($segments as $segment) {
$subscribers_count = $segment->subscribers()
->whereNull('deleted_at')
->count();
if($subscribers_count > 0) {
$segment_list[] = array(
'label' => sprintf('%s (%d)', $segment->name, $subscribers_count),
'value' => $segment->id()
);
}
$segment_list[] = array(
'label' => sprintf('%s (%d)', $segment->name, $subscribers_count),
'value' => $segment->id()
);
}
$filters = array(
@ -121,9 +131,13 @@ class Subscriber extends Model {
}
foreach($filters as $key => $value) {
if($key === 'segment') {
$segment = Segment::findOne($value);
if($segment !== false) {
return $segment->subscribers();
if($value === 'none') {
return self::filter('withoutSegments');
} else {
$segment = Segment::findOne($value);
if($segment !== false) {
return $segment->subscribers();
}
}
}
}
@ -135,27 +149,27 @@ class Subscriber extends Model {
array(
'name' => 'all',
'label' => __('All'),
'count' => Subscriber::getPublished()->count()
'count' => self::getPublished()->count()
),
array(
'name' => 'subscribed',
'label' => __('Subscribed'),
'count' => Subscriber::filter('subscribed')->count()
'count' => self::filter('subscribed')->count()
),
array(
'name' => 'unconfirmed',
'label' => __('Unconfirmed'),
'count' => Subscriber::filter('unconfirmed')->count()
'count' => self::filter('unconfirmed')->count()
),
array(
'name' => 'unsubscribed',
'label' => __('Unsubscribed'),
'count' => Subscriber::filter('unsubscribed')->count()
'count' => self::filter('unsubscribed')->count()
),
array(
'name' => 'trash',
'label' => __('Trash'),
'count' => Subscriber::getTrashed()->count()
'count' => self::getTrashed()->count()
)
);
}
@ -226,17 +240,25 @@ class Subscriber extends Model {
$subscriber = false;
if(isset($data['id']) && (int)$data['id'] > 0) {
$subscriber = static::findOne((int)$data['id']);
$subscriber = self::findOne((int)$data['id']);
unset($data['id']);
}
if($subscriber === false && !empty($data['email'])) {
$subscriber = static::where('email', $data['email'])->findOne();
$subscriber = self::where('email', $data['email'])->findOne();
if($subscriber !== false) {
unset($data['email']);
}
}
// segments
$segment_ids = array();
if(isset($data['segments'])) {
$segment_ids = (array)$data['segments'];
unset($data['segments']);
}
// custom fields
$custom_fields = array();
@ -248,7 +270,7 @@ class Subscriber extends Model {
}
if($subscriber === false) {
$subscriber = static::create();
$subscriber = self::create();
$subscriber->hydrate($data);
} else {
$subscriber->set($data);
@ -260,6 +282,7 @@ class Subscriber extends Model {
$subscriber->setCustomField($custom_field_id, $value);
}
}
$subscriber->addToSegments($segment_ids);
}
return $subscriber;
}
@ -430,6 +453,19 @@ class Subscriber extends Model {
->where('status', 'unconfirmed');
}
static function withoutSegments($orm) {
return $orm->select(MP_SUBSCRIBERS_TABLE.'.*')
->leftOuterJoin(
MP_SUBSCRIBER_SEGMENT_TABLE,
array(
MP_SUBSCRIBERS_TABLE.'.id',
'=',
MP_SUBSCRIBER_SEGMENT_TABLE.'.subscriber_id'
)
)
->whereNull(MP_SUBSCRIBER_SEGMENT_TABLE.'.subscriber_id');
}
static function createMultiple($columns, $values) {
return self::rawExecute(
'INSERT INTO `' . self::$_table . '` ' .

View File

@ -22,12 +22,12 @@ class PostTransformer {
$content = $content_manager->filterContent($content);
$structure_transformer = new StructureTransformer();
$structure = $structure_transformer->transform($content, $this->args['imagePadded'] === 'true');
$structure = $structure_transformer->transform($content, $this->args['imageFullWidth'] === 'true');
$structure = $this->appendFeaturedImage(
$post,
$this->args['displayType'],
$this->args['imagePadded'] === 'true',
$this->args['imageFullWidth'] === 'true',
$structure
);
$structure = $this->appendPostTitle($post, $structure);
@ -36,7 +36,7 @@ class PostTransformer {
return $structure;
}
private function appendFeaturedImage($post, $display_type, $image_padded, $structure) {
private function appendFeaturedImage($post, $display_type, $image_full_width, $structure) {
if ($display_type === 'full') {
// No featured images for full posts
return $structure;
@ -45,7 +45,7 @@ class PostTransformer {
$featured_image = $this->getFeaturedImage(
$post->ID,
$post->post_title,
(bool)$image_padded
(bool)$image_full_width
);
if (is_array($featured_image)) {
@ -55,14 +55,14 @@ class PostTransformer {
return $structure;
}
private function getFeaturedImage($post_id, $post_title, $image_padded) {
private function getFeaturedImage($post_id, $post_title, $image_full_width) {
if(has_post_thumbnail($post_id)) {
$thumbnail_id = get_post_thumbnail_id($post_id);
// get attachment data (src, width, height)
$image_info = wp_get_attachment_image_src(
$thumbnail_id,
'single-post-thumbnail'
'mailpoet_newsletter_max'
);
// get alt text
@ -81,7 +81,7 @@ class PostTransformer {
'link' => get_permalink($post_id),
'src' => $image_info[0],
'alt' => $alt_text,
'padded' => $image_padded,
'fullWidth' => $image_full_width,
'width' => $image_info[1],
'height' => $image_info[2],
'styles' => array(

View File

@ -7,11 +7,11 @@ if(!defined('ABSPATH')) exit;
class StructureTransformer {
function transform($content, $image_padded) {
function transform($content, $image_full_width) {
$root = pQuery::parseStr($content);
$this->hoistImagesToRoot($root);
$structure = $this->transformTagsToBlocks($root, $image_padded);
$structure = $this->transformTagsToBlocks($root, $image_full_width);
$structure = $this->mergeNeighboringBlocks($structure);
return $structure;
}
@ -44,8 +44,8 @@ class StructureTransformer {
* Transforms HTML tags into their respective JSON objects,
* turns other root children into text blocks
*/
private function transformTagsToBlocks($root, $image_padded) {
return array_map(function($item) use ($image_padded) {
private function transformTagsToBlocks($root, $image_full_width) {
return array_map(function($item) use ($image_full_width) {
if ($item->tag === 'img' || $item->tag === 'a' && $item->query('img')) {
if ($item->tag === 'a') {
$link = $item->getAttribute('href');
@ -60,7 +60,7 @@ class StructureTransformer {
'link' => $link,
'src' => $image->getAttribute('src'),
'alt' => $image->getAttribute('alt'),
'padded' => $image_padded,
'fullWidth' => $image_full_width,
'width' => $image->getAttribute('width'),
'height' => $image->getAttribute('height'),
'styles' => array(

View File

@ -6,10 +6,12 @@ use MailPoet\Newsletter\Renderer\StylesHelper;
class Image {
static function render($element, $columnCount) {
$element = self::getImageDimensions($element, $columnCount);
$element['width'] = (int) $element['width'];
$element['height'] = (int) $element['height'];
$element = self::adjustImageDimensions($element, $columnCount);
$template = '
<tr>
<td class="mailpoet_image ' . $element['paddedClass'] . '" align="center" valign="top">
<td class="mailpoet_image ' . (($element['fullWidth'] === false) ? 'mailpoet_padded' : '') . '" align="center" valign="top">
<img style="max-width:' . $element['width'] . 'px;" src="' . $element['src'] . '"
width="' . $element['width'] . '" height="' . $element['height'] . '" alt="' . $element['alt'] . '"/>
</td>
@ -17,25 +19,22 @@ class Image {
return $template;
}
static function getImageDimensions($element, $column_count) {
static function adjustImageDimensions($element, $column_count) {
$column_width = ColumnsHelper::columnWidth($column_count);
$padded_width = StylesHelper::$padding_width * 2;
// resize image if it's wider than the column width
if((int) $element['width'] >= $column_width) {
$ratio = (int) $element['width'] / $column_width;
// scale image to fit column width
if($element['width'] > $column_width) {
$ratio = $element['width'] / $column_width;
$element['width'] = $column_width;
$element['height'] = ceil((int) $element['height'] / $ratio);
$element['height'] = (int) ceil($element['height'] / $ratio);
}
if($element['padded'] == "true" && $element['width'] >= $column_width) {
// resize image if the padded option is on
$ratio = (int) $element['width'] / ((int) $element['width'] - $padded_width);
$element['width'] = (int) $element['width'] - $padded_width;
$element['height'] = ceil((int) $element['height'] / $ratio);
$element['paddedClass'] = 'mailpoet_padded';
} else {
$element['width'] = (int) $element['width'];
$element['height'] = (int) $element['height'];
$element['paddedClass'] = '';
// resize image if the image is padded and wider than padded column width
if($element['fullWidth'] === false &&
$element['width'] > ($column_width - $padded_width)
) {
$ratio = $element['width'] / ($column_width - $padded_width);
$element['width'] = $column_width - $padded_width;
$element['height'] = (int) ceil($element['height'] / $ratio);
}
return $element;
}

View File

@ -11,12 +11,12 @@ class AutomatedLatestContent {
}
function getPostTypes() {
wp_send_json(get_post_types(array(), 'objects'));
return get_post_types(array(), 'objects');
}
function getTaxonomies($args) {
$post_type = (isset($args['postType'])) ? $args['postType'] : 'post';
wp_send_json(get_object_taxonomies($post_type, 'objects'));
return get_object_taxonomies($post_type, 'objects');
}
function getTerms($args) {
@ -24,20 +24,23 @@ class AutomatedLatestContent {
$search = (isset($args['search'])) ? $args['search'] : '';
$limit = (isset($args['limit'])) ? (int)$args['limit'] : 10;
$page = (isset($args['page'])) ? (int)$args['page'] : 1;
wp_send_json(get_terms($taxonomies, array(
'hide_empty' => false,
'search' => $search,
'number' => $limit,
'offset' => $limit * ($page - 1),
)));
return get_terms(
$taxonomies,
array(
'hide_empty' => false,
'search' => $search,
'number' => $limit,
'offset' => $limit * ($page - 1)
)
);
}
function getPosts($args) {
wp_send_json($this->ALC->getPosts($args));
return $this->ALC->getPosts($args);
}
function getTransformedPosts($args) {
$posts = $this->ALC->getPosts($args);
wp_send_json($this->ALC->transformPosts($args, $posts));
return $this->ALC->transformPosts($args, $posts);
}
}

View File

@ -11,7 +11,7 @@ if(!defined('ABSPATH')) exit;
class Cron {
function start() {
$supervisor = new Supervisor($force_run = true);
wp_send_json($supervisor->checkDaemon());
return $supervisor->checkDaemon();
}
function stop() {
@ -22,17 +22,15 @@ class Cron {
$daemon['status'] = 'stopping';
$result = CronHelper::saveDaemon($daemon);
}
wp_send_json(
array(
'result' => $result
)
return array(
'result' => $result
);
}
function getStatus() {
$daemon = Setting::where('name', 'cron_daemon')
->findOne();
wp_send_json(
return (
($daemon) ?
array_merge(
array(

View File

@ -33,30 +33,19 @@ class CustomFields {
function save($data = array()) {
$custom_field = CustomField::createOrUpdate($data);
$errors = $custom_field->getErrors();
if($custom_field === false) {
$result = array(
if(!empty($errors)) {
return array(
'result' => false,
'errors' => array(
__('The custom field could not be created.')
)
'errors' => $errors
);
} else {
$errors = $custom_field->getValidationErrors();
if(!empty($errors)) {
$result = array(
'result' => false,
'errors' => $errors
);
} else {
$result = array(
'result' => true,
'field' => $custom_field->asArray()
);
}
return array(
'result' => true,
'field' => $custom_field->asArray()
);
}
return $result;
}
function get($id) {

View File

@ -11,15 +11,12 @@ class Forms {
function __construct() {
}
function get($data = array()) {
$id = (isset($data['id']) ? (int)$data['id'] : 0);
function get($id = false) {
$form = Form::findOne($id);
if($form === false) {
wp_send_json(false);
return false;
} else {
$form = $form->asArray();
wp_send_json($form);
return $form->asArray();
}
}
@ -47,12 +44,7 @@ class Forms {
);
}
wp_send_json($listing_data);
}
function getAll() {
$collection = Form::findArray();
wp_send_json($collection);
return $listing_data;
}
function create() {
@ -88,24 +80,23 @@ class Forms {
)
);
$form = Form::createOrUpdate($form_data);
if($form !== false && $form->id()) {
wp_send_json(
admin_url('admin.php?page=mailpoet-form-editor&id='.$form->id())
);
} else {
wp_send_json(false);
}
return $this->save($form_data);
}
function save($data = array()) {
$form = Form::createOrUpdate($data);
$errors = $form->getErrors();
if($form !== false && $form->id()) {
wp_send_json($form->id());
if(!empty($errors)) {
return array(
'result' => false,
'errors' => $errors
);
} else {
wp_send_json($form);
return array(
'result' => true,
'form_id' => $form->id()
);
}
}
@ -119,10 +110,10 @@ class Forms {
// styles
$css = new Util\Styles(FormRenderer::getStyles($data));
wp_send_json(array(
return array(
'html' => $html,
'css' => $css->render()
));
);
}
function exportsEditor($id) {
@ -134,19 +125,19 @@ class Forms {
$exports = Util\Export::getAll($form->asArray());
}
wp_send_json($exports);
return $exports;
}
function saveEditor($data = array()) {
$form_id = (isset($data['id']) ? (int)$data['id'] : 0);
$name = (isset($data['name']) ? $data['name'] : array());
$name = (isset($data['name']) ? $data['name'] : __('New form'));
$body = (isset($data['body']) ? $data['body'] : array());
$settings = (isset($data['settings']) ? $data['settings'] : array());
$styles = (isset($data['styles']) ? $data['styles'] : array());
$styles = (isset($data['styles']) ? $data['styles'] : '');
if(empty($body) || empty($settings)) {
// error
wp_send_json(false);
return false;
} else {
// check if the form is used as a widget
$is_widget = false;
@ -178,7 +169,7 @@ class Forms {
}
}
// check list selectio
// check list selection
if($has_segment_selection === true) {
$settings['segments_selected_by'] = 'user';
} else {
@ -194,45 +185,42 @@ class Forms {
'styles' => $styles
));
// response
wp_send_json(array(
'result' => ($form !== false),
'is_widget' => $is_widget
));
if($form->getErrors() === false) {
return array(
'result' => true,
'is_widget' => $is_widget
);
} else {
return array(
'result' => false,
'errors' => $form->getErrors()
);
}
}
function restore($id) {
$result = false;
$form = Form::findOne($id);
if($form !== false) {
$result = $form->restore();
$form->restore();
}
wp_send_json($result);
return ($form->getErrors() === false);
}
function trash($id) {
$result = false;
$form = Form::findOne($id);
if($form !== false) {
$result = $form->trash();
$form->trash();
}
wp_send_json($result);
return ($form->getErrors() === false);
}
function delete($id) {
$result = false;
$form = Form::findOne($id);
if($form !== false) {
$form->delete();
$result = 1;
return 1;
}
wp_send_json($result);
return false;
}
function duplicate($id) {
@ -246,7 +234,7 @@ class Forms {
$result = $form->duplicate($data)->asArray();
}
wp_send_json($result);
return $result;
}
function bulkAction($data = array()) {
@ -255,6 +243,6 @@ class Forms {
$data
);
wp_send_json($bulk_action->apply());
return $bulk_action->apply();
}
}

View File

@ -10,17 +10,17 @@ if(!defined('ABSPATH')) exit;
class ImportExport {
function getMailChimpLists($data) {
$mailChimp = new MailChimp($data['api_key']);
wp_send_json($mailChimp->getLists());
return $mailChimp->getLists();
}
function getMailChimpSubscribers($data) {
$mailChimp = new MailChimp($data['api_key']);
wp_send_json($mailChimp->getSubscribers($data['lists']));
return $mailChimp->getSubscribers($data['lists']);
}
function addSegment($data) {
$segment = Segment::createOrUpdate($data);
wp_send_json(
return (
($segment->id) ?
array(
'result' => true,
@ -36,7 +36,7 @@ class ImportExport {
$customField = CustomField::create();
$customField->hydrate($data);
$result = $customField->save();
wp_send_json(
return (
($result) ?
array(
'result' => true,
@ -49,12 +49,16 @@ class ImportExport {
}
function processImport($data) {
$import = new \MailPoet\Subscribers\ImportExport\Import\Import(json_decode($data, true));
wp_send_json($import->process());
$import = new \MailPoet\Subscribers\ImportExport\Import\Import(
json_decode($data, true)
);
return $import->process();
}
function processExport($data) {
$export = new \MailPoet\Subscribers\ImportExport\Export\Export(json_decode($data, true));
wp_send_json($export->process());
$export = new \MailPoet\Subscribers\ImportExport\Export\Export(
json_decode($data, true)
);
return $export->process();
}
}

View File

@ -5,16 +5,19 @@ if(!defined('ABSPATH')) exit;
class Mailer {
function send($data) {
$mailer = new \MailPoet\Mailer\Mailer(
(isset($data['mailer'])) ? $data['mailer'] : false,
(isset($data['sender'])) ? $data['sender'] : false,
(isset($data['reply_to'])) ? $data['reply_to'] : false
);
$result = $mailer->send($data['newsletter'], $data['subscriber']);
wp_send_json(
array(
'result' => ($result) ? true : false
)
);
$response = array();
try {
$mailer = new \MailPoet\Mailer\Mailer(
(isset($data['mailer'])) ? $data['mailer'] : false,
(isset($data['sender'])) ? $data['sender'] : false,
(isset($data['reply_to'])) ? $data['reply_to'] : false
);
$result = $mailer->send($data['newsletter'], $data['subscriber']);
} catch(\Exception $e) {
$result = false;
$response['errors'] = array($e->getMessage());
}
$response['result'] = ($result) ? true : false;
return $response;
}
}

View File

@ -9,42 +9,33 @@ class NewsletterTemplates {
function __construct() {
}
function get($data = array()) {
$id = (isset($data['id'])) ? (int) $data['id'] : 0;
function get($id = false) {
$template = NewsletterTemplate::findOne($id);
if($template === false) {
wp_send_json(false);
return false;
} else {
$template->body = json_decode($template->body);
wp_send_json($template->asArray());
return $template->asArray();
}
}
function getAll() {
$collection = NewsletterTemplate::findArray();
$collection = array_map(function($item) {
$item['body'] = json_decode($item['body']);
return $item;
$collection = NewsletterTemplate::findMany();
return array_map(function($item) {
return $item->asArray();
}, $collection);
wp_send_json($collection);
}
function save($data = array()) {
$result = NewsletterTemplate::createOrUpdate($data);
if($result !== true) {
wp_send_json($result);
} else {
wp_send_json(true);
}
$template = NewsletterTemplate::createOrUpdate($data);
return ($template->getErrors() === false && $template->id() > 0);
}
function delete($id) {
$template = NewsletterTemplate::findOne($id);
if($template !== false) {
$result = $template->delete();
return $template->delete();
} else {
$result = false;
return false;
}
wp_send_json($result);
}
}

View File

@ -21,11 +21,10 @@ class Newsletters {
function __construct() {
}
function get($data = array()) {
$id = (isset($data['id'])) ? (int) $data['id'] : 0;
function get($id = false) {
$newsletter = Newsletter::findOne($id);
if($newsletter === false) {
wp_send_json(false);
return false;
} else {
$segments = $newsletter->segments()->findArray();
$options = $newsletter->options()->findArray();
@ -34,42 +33,32 @@ class Newsletters {
return $segment['id'];
}, $segments);
$newsletter['options'] = $options;
$newsletter['body'] = json_decode($newsletter['body']);
wp_send_json($newsletter);
return $newsletter;
}
}
function getAll() {
$collection = Newsletter::findArray();
$collection = array_map(function($item) {
$item['body'] = json_decode($item['body']);
return $item;
}, $collection);
wp_send_json($collection);
}
function save($data = array()) {
$segment_ids = array();
if(isset($data['segments'])) {
$segment_ids = $data['segments'];
unset($data['segments']);
}
$options = array();
if(isset($data['options'])) {
$options = $data['options'];
unset($data['options']);
}
$errors = array();
$result = false;
$newsletter = Newsletter::createOrUpdate($data);
$errors = $newsletter->getErrors();
if($newsletter !== false && !$newsletter->id()) {
$errors = $newsletter->getValidationErrors();
if(!empty($errors)) {
return array(
'result' => false,
'errors' => $errors
);
} else {
$result = true;
if(!empty($segment_ids)) {
NewsletterSegment::where('newsletter_id', $newsletter->id)
->deleteMany();
@ -86,132 +75,66 @@ class Newsletters {
NewsletterOption::where('newsletter_id', $newsletter->id)
->deleteMany();
$optionFields = NewsletterOptionField::where(
$option_fields = NewsletterOptionField::where(
'newsletter_type',
$data['type']
)->findArray();
foreach($optionFields as $optionField) {
if(isset($options[$optionField['name']])) {
foreach($option_fields as $option_field) {
if(isset($options[$option_field['name']])) {
$relation = NewsletterOption::create();
$relation->newsletter_id = $newsletter->id;
$relation->option_field_id = $optionField['id'];
$relation->value = $options[$optionField['name']];
$relation->option_field_id = $option_field['id'];
$relation->value = $options[$option_field['name']];
$relation->save();
}
}
}
return array(
'result' => true
);
}
wp_send_json(array(
'result' => $result,
'errors' => $errors
));
}
function restore($id) {
$result = false;
$newsletter = Newsletter::findOne($id);
if($newsletter !== false) {
$result = $newsletter->restore();
$newsletter->restore();
}
wp_send_json($result);
return ($newsletter->getErrors() === false);
}
function trash($id) {
$result = false;
$newsletter = Newsletter::findOne($id);
if($newsletter !== false) {
$result = $newsletter->trash();
$newsletter->trash();
}
wp_send_json($result);
return ($newsletter->getErrors() === false);
}
function delete($id) {
$result = false;
$newsletter = Newsletter::findOne($id);
if($newsletter !== false) {
$newsletter->delete();
$result = 1;
return 1;
}
wp_send_json($result);
return false;
}
function duplicate($id) {
$result = false;
function duplicate($id = false) {
$newsletter = Newsletter::findOne($id);
if($newsletter !== false) {
$data = array(
return $newsletter->duplicate(array(
'subject' => sprintf(__('Copy of %s'), $newsletter->subject)
);
$result = $newsletter->duplicate($data)->asArray();
))->asArray();
}
wp_send_json($result);
}
function send($data = array()) {
$newsletter = Newsletter::findOne($data['id'])->asArray();
if(empty($data['segments'])) {
return wp_send_json(array(
'errors' => array(
__("You need to select a list.")
)
));
}
$segments = Segment::whereIdIn($data['segments'])->findMany();
$subscribers = array();
foreach($segments as $segment) {
$segment_subscribers = $segment->subscribers()->findMany();
foreach($segment_subscribers as $segment_subscriber) {
$subscribers[$segment_subscriber->email] = $segment_subscriber
->asArray();
}
}
if(empty($subscribers)) {
return wp_send_json(array(
'errors' => array(
__("No subscribers found.")
)
));
}
// TODO: TO REMOVE once we add the columns from/reply_to
$newsletter = array_merge($newsletter, $data['newsletter']);
// END - TO REMOVE
$renderer = new Renderer(json_decode($newsletter['body'], true));
$newsletter['body'] = $renderer->render();
$subscribers = Subscriber::find_array();
$fromEmail = Setting::where('name', 'from_address')->findOne()->value;
$fromName = Setting::where('name', 'from_name')->findOne()->value;
$apiKey = Setting::where('name', 'api_key')->findOne()->value;
$mailer = new MailPoet($apiKey, $fromEmail, $fromName);
foreach ($subscribers as $subscriber) {
$result = $mailer->send(
$newsletter,
sprintf('%s %s <%s>', $subscriber['first_name'], $subscriber['last_name'], $subscriber['email'])
);
if ($result !== true) wp_send_json(false);
}
wp_send_json(true);
return false;
}
function render($data = array()) {
if(!isset($data['body'])) {
wp_send_json(false);
return false;
}
$renderer = new Renderer($data);
$rendered_newsletter = $renderer->render();
@ -220,7 +143,7 @@ class Newsletters {
$data
);
$rendered_newsletter = $shortcodes->replace();
wp_send_json(array('rendered_body' => $rendered_newsletter));
return array('rendered_body' => $rendered_newsletter);
}
function sendPreview($data = array()) {
@ -228,15 +151,15 @@ class Newsletters {
$newsletter = Newsletter::findOne($id);
if($newsletter === false) {
wp_send_json(array(
return array(
'result' => false
));
);
}
if(empty($data['subscriber'])) {
wp_send_json(array(
return array(
'result' => false,
'errors' => array(__('Please specify receiver information')),
));
'errors' => array(__('Please specify receiver information'))
);
}
$newsletter = $newsletter->asArray();
@ -264,15 +187,14 @@ class Newsletters {
$sender = false,
$reply_to = false
);
$result = $mailer->send($newsletter, $data['subscriber']);
wp_send_json(array(
'result' => $mailer->send($newsletter, $data['subscriber'])
));
return array('result' => $result);
} catch(\Exception $e) {
wp_send_json(array(
return array(
'result' => false,
'errors' => array($e->getMessage()),
));
);
}
}
@ -300,7 +222,7 @@ class Newsletters {
$item['queue'] = ($queue !== false) ? $queue->asArray() : null;
}
wp_send_json($listing_data);
return $listing_data;
}
function bulkAction($data = array()) {
@ -308,46 +230,54 @@ class Newsletters {
'\MailPoet\Models\Newsletter',
$data
);
wp_send_json($bulk_action->apply());
return $bulk_action->apply();
}
function create($data = array()) {
$newsletter = Newsletter::create();
$newsletter->type = $data['type'];
$newsletter->subject = $data['subject'];
$newsletter->body = '{}';
// try to load template data
$template_id = (!empty($data['template']) ? (int)$data['template'] : 0);
$template = NewsletterTemplate::findOne($template_id);
if($template !== false) {
$newsletter->body = $template->body;
}
$options = array();
if(isset($data['options'])) {
$options = $data['options'];
unset($data['options']);
}
$result = $newsletter->save();
if($result !== true) {
wp_send_json($newsletter->getValidationErrors());
$newsletter = Newsletter::createOrUpdate($data);
// try to load template data
$template_id = (!empty($data['template']) ? (int)$data['template'] : false);
$template = NewsletterTemplate::findOne($template_id);
if($template !== false) {
$newsletter->body = $template->body;
} else {
$newsletter->body = array();
}
$newsletter->save();
$errors = $newsletter->getErrors();
if(!empty($errors)) {
return array(
'result' => false,
'errors' =>$errors
);
} else {
if(!empty($options)) {
$optionFields = NewsletterOptionField::where('newsletter_type', $newsletter->type)->findArray();
$option_fields = NewsletterOptionField::where(
'newsletter_type', $newsletter->type
)->findArray();
foreach($optionFields as $optionField) {
if(isset($options[$optionField['name']])) {
foreach($option_fields as $option_field) {
if(isset($options[$option_field['name']])) {
$relation = NewsletterOption::create();
$relation->newsletter_id = $newsletter->id;
$relation->option_field_id = $optionField['id'];
$relation->value = $options[$optionField['name']];
$relation->option_field_id = $option_field['id'];
$relation->value = $options[$option_field['name']];
$relation->save();
}
}
}
$newsletter->body = json_decode($newsletter->body);
wp_send_json($newsletter->asArray());
return array(
'result' => true,
'newsletter' => $newsletter->asArray()
);
}
}
}
}

View File

@ -8,7 +8,6 @@ class Permissions {
}
function set($permissions = array()) {
$result = \MailPoet\Util\Permissions::set($permissions);
wp_send_json($result);
return \MailPoet\Util\Permissions::set($permissions);
}
}

View File

@ -30,7 +30,7 @@ class Router {
$endpoint = new $endpoint();
$response = $endpoint->$method($data);
wp_send_json($response);
} catch(Exception $e) {
} catch(\Exception $e) {
error_log($e->getMessage());
exit;
}

View File

@ -12,14 +12,12 @@ class Segments {
function __construct() {
}
function get($data = array()) {
$id = (isset($data['id']) ? (int)$data['id'] : 0);
function get($id = false) {
$segment = Segment::findOne($id);
if($segment === false) {
wp_send_json(false);
return false;
} else {
wp_send_json($segment->asArray());
return $segment->asArray();
}
}
@ -64,63 +62,48 @@ class Segments {
);
}
wp_send_json($listing_data);
}
function getAll() {
$collection = Segment::findArray();
wp_send_json($collection);
return $listing_data;
}
function save($data = array()) {
$errors = array();
$result = false;
$segment = Segment::createOrUpdate($data);
$errors = $segment->getErrors();
if($segment !== false && !$segment->id()) {
$errors = $segment->getValidationErrors();
if(!empty($errors)) {
return array(
'result' => false,
'errors' => $errors
);
} else {
$result = true;
return array(
'result' => true
);
}
wp_send_json(array(
'result' => $result,
'errors' => $errors
));
}
function restore($id) {
$result = false;
$segment = Segment::findOne($id);
if($segment !== false) {
$result = $segment->restore();
$segment->restore();
}
wp_send_json($result);
return ($segment->getErrors() === false);
}
function trash($id) {
$result = false;
$segment = Segment::findOne($id);
if($segment !== false) {
$result = $segment->trash();
$segment->trash();
}
wp_send_json($result);
return ($segment->getErrors() === false);
}
function delete($id) {
$result = false;
$segment = Segment::findOne($id);
if($segment !== false) {
$segment->delete();
$result = 1;
return 1;
}
wp_send_json($result);
return false;
}
function duplicate($id) {
@ -134,13 +117,13 @@ class Segments {
$result = $segment->duplicate($data)->asArray();
}
wp_send_json($result);
return $result;
}
function synchronize() {
$result = WP::synchronizeUsers();
wp_send_json($result);
return $result;
}
function bulkAction($data = array()) {
@ -149,6 +132,6 @@ class Segments {
$data
);
wp_send_json($bulk_action->apply());
return $bulk_action->apply();
}
}

View File

@ -13,25 +13,21 @@ class SendingQueue {
try {
new Mailer(false);
} catch(\Exception $e) {
wp_send_json(
array(
'result' => false,
'errors' => array($e->getMessage())
)
return array(
'result' => false,
'errors' => array($e->getMessage())
);
}
$queue = \MailPoet\Models\SendingQueue::where('newsletter_id', $data['newsletter_id'])
->whereNull('status')
$queue = \MailPoet\Models\SendingQueue::whereNull('status')
->where('newsletter_id', $data['newsletter_id'])
->findArray();
if(count($queue)) {
wp_send_json(
array(
'result' => false,
'errors' => array(__('Send operation is already in progress.'))
)
if(!empty($queue)) {
return array(
'result' => false,
'errors' => array(__('Send operation is already in progress.'))
);
exit;
}
$queue = \MailPoet\Models\SendingQueue::create();
$queue->newsletter_id = $data['newsletter_id'];
@ -40,50 +36,39 @@ class SendingQueue {
->findMany();
foreach($segments as $segment) {
$subscriber_ids = array_merge($subscriber_ids, Helpers::arrayColumn(
$segment->subscribers()
->findArray(),
'id'
));
$subscriber_ids = array_merge(
$subscriber_ids,
Helpers::arrayColumn(
$segment->subscribers()->findArray(), 'id'
)
);
}
if(empty($subscriber_ids)) {
wp_send_json(
array(
'result' => false,
'errors' => array(__('There are no subscribers.'))
)
return array(
'result' => false,
'errors' => array(__('There are no subscribers.'))
);
exit;
}
$subscriber_ids = array_unique($subscriber_ids);
$queue->subscribers = json_encode(
$queue->subscribers = serialize(
array(
'to_process' => $subscriber_ids
)
);
$queue->count_total = $queue->count_to_process = count($subscriber_ids);
$result = $queue->save();
if($result === false) {
$errors = array(__('Queue could not be created.'));
if(!empty($queue->getValidationErrors())) {
$errors = array_merge($errors, $queue->getValidationErrors());
}
wp_send_json(
array(
'result' => false,
'errors' => $errors
)
$queue->save();
$errors = $queue->getErrors();
if(!empty($errors)) {
return array(
'result' => false,
'errors' => $errors
);
} else {
wp_send_json(
array(
'result' => true,
'data' => array($queue->id)
)
return array(
'result' => true,
'data' => array($queue->id)
);
}
}
@ -94,14 +79,15 @@ class SendingQueue {
if($newsletter !== false) {
$queue = $newsletter->getQueue();
if($queue !== false && $queue->id() > 0) {
if($queue !== false) {
$result = $queue->pause();
}
}
wp_send_json(array(
return array(
'result' => $result
));
);
}
function resume($newsletter_id) {
@ -110,125 +96,14 @@ class SendingQueue {
if($newsletter !== false) {
$queue = $newsletter->getQueue();
if($queue !== false && $queue->id() > 0) {
if($queue !== false) {
$result = $queue->resume();
}
}
wp_send_json(array(
return array(
'result' => $result
));
}
function addQueues($data) {
$newsletterIds = Helpers::arrayColumn($data, 'newsletter_id');
$queues = \MailPoet\Models\SendingQueue::whereIn('newsletter_id', $newsletterIds)
->whereNull('status')
->findArray();
if(count($queues)) {
wp_send_json(
array(
'result' => false,
'errors' => array(__('Send operation is already in progress.'))
)
);
}
$result = array_map(function ($queueData) {
$queue = \MailPoet\Models\SendingQueue::create();
$queue->newsletter_id = $queueData['newsletter_id'];
$queue->subscribers = json_encode(
array(
'to_process' => $queueData['subscribers']
)
);
$queue->count_total = $queue->count_to_process = count($queueData['subscribers']);
$queue->save();
return array(
'newsletter_id' => $queue->newsletter_id,
'queue_id' => $queue->id
);
}, $data);
$result = Helpers::arrayColumn($result, 'queue_id', 'newsletter_id');
wp_send_json(
count($data) != count($result) ?
array(
'result' => false,
'errors' => array(__('Some queues could not be created.')),
'data' => $result
) :
array(
'result' => true,
'data' => $result
)
);
}
function deleteQueue($data) {
$queue = \MailPoet\Models\SendingQueue::whereNull('deleted_at')
->findOne($data['queue_id']);
if(!$queue) {
wp_send_json(
array(
'result' => false,
'errors' => array(__('Queue not found.'))
)
);
}
$queue->deleted_at = 'Y-m-d H:i:s';
$queue->save();
wp_send_json(array('result' => true));
}
function deleteQueues($data) {
$queues = \MailPoet\Models\SendingQueue::whereNull('deleted_at')
->whereIn('id', $data['queue_ids'])
->findResultSet();
if(!$queues->count()) {
wp_send_json(
array(
'result' => false,
'errors' => array(__('Queues not found.'))
)
);
}
foreach($queues as $queue) {
$queue->deleted_at = 'Y-m-d H:i:s';
$queue->save();
}
wp_send_json(array('result' => true));
}
function getQueueStatus($data) {
$queue = \MailPoet\Models\SendingQueue::whereNull('deleted_at')
->findOne($data['queue_id'])
->asArray();
wp_send_json(
!$queue ?
array(
'result' => false,
'errors' => array(__('Queue not found.'))
) :
array(
'result' => true,
'data' => $queue
)
);
}
function getQueuesStatus($data) {
$queues = \MailPoet\Models\SendingQueue::whereNull('deleted_at')
->whereIn('id', $data['queue_ids'])
->findArray();
wp_send_json(
!$queues ?
array(
'result' => false,
'errors' => array(__('Queue not found.'))
) :
array(
'result' => true,
'data' => $queues
)
);
}
}

View File

@ -10,17 +10,17 @@ class Settings {
function get() {
$settings = Setting::getAll();
wp_send_json($settings);
return $settings;
}
function set($settings = array()) {
if(empty($settings)) {
wp_send_json(false);
return false;
} else {
foreach($settings as $name => $value) {
Setting::setValue($name, $value);
}
wp_send_json(true);
return true;
}
}
}

View File

@ -14,11 +14,11 @@ class Setup {
$activator->deactivate();
$activator->activate();
$result = true;
} catch(Exception $e) {
} catch(\Exception $e) {
$result = false;
}
wp_send_json(array(
return array(
'result' => $result
));
);
}
}

View File

@ -15,9 +15,7 @@ class Subscribers {
function __construct() {
}
function get($data = array()) {
$id = (isset($data['id']) ? (int) $data['id'] : 0);
function get($id = false) {
$subscriber = Subscriber::findOne($id);
if($subscriber !== false && $subscriber->id() > 0) {
$segments = $subscriber->segments()->findArray();
@ -58,35 +56,20 @@ class Subscribers {
return $listing_data;
}
function getAll() {
return Subscriber::findArray();
}
function save($data = array()) {
$errors = array();
$result = false;
$segment_ids = array();
if(array_key_exists('segments', $data)) {
$segment_ids = (array)$data['segments'];
unset($data['segments']);
}
$subscriber = Subscriber::createOrUpdate($data);
$errors = $subscriber->getErrors();
if($subscriber !== false && !$subscriber->id()) {
$errors = $subscriber->getValidationErrors();
if(!empty($errors)) {
return array(
'result' => false,
'errors' => $errors
);
} else {
$result = true;
if(!empty($segment_ids)) {
$subscriber->addToSegments($segment_ids);
}
return array(
'result' => true
);
}
return array(
'result' => $result,
'errors' => $errors
);
}
function subscribe($data = array()) {
@ -193,37 +176,28 @@ class Subscribers {
}
function restore($id) {
$result = false;
$subscriber = Subscriber::findOne($id);
if($subscriber !== false) {
$result = $subscriber->restore();
$subscriber->restore();
}
return $result;
return ($subscriber->getErrors() === false);
}
function trash($id) {
$result = false;
$subscriber = Subscriber::findOne($id);
if($subscriber !== false) {
$result = $subscriber->trash();
$subscriber->trash();
}
return $result;
return ($subscriber->getErrors() === false);
}
function delete($id) {
$result = false;
$subscriber = Subscriber::findOne($id);
if($subscriber !== false) {
$subscriber->delete();
$result = 1;
return 1;
}
return $result;
return false;
}
function bulkAction($data = array()) {

View File

@ -61,10 +61,10 @@ class WP {
$segment = Segment::getWPUsers();
// count WP users
$users_count = \count_users()['total_users'];
$users_count = \count_users();
$linked_subscribers_count = $segment->subscribers()->count();
if($users_count !== $linked_subscribers_count) {
if($users_count['total_users'] !== $linked_subscribers_count) {
$linked_subscribers = Subscriber::select('wp_user_id')
->whereNotNull('wp_user_id')
->findArray();

View File

@ -104,7 +104,7 @@ class Export {
);
$writer->writeToFile($this->export_file);
}
} catch(Exception $e) {
} catch(\Exception $e) {
return array(
'result' => false,
'errors' => array($e->getMessage())

View File

@ -16,7 +16,7 @@ class Import {
public $subscribers_count;
public $import_time;
public $profiler_start;
public function __construct($data) {
$this->subscribers_data = $data['subscribers'];
$this->segments = $data['segments'];
@ -31,7 +31,7 @@ class Import {
$this->import_time = date('Y-m-d H:i:s');
$this->profiler_start = microtime(true);
}
function process() {
$subscriber_fields = $this->subscriber_fields;
$subscriber_custom_fields = $this->subscriber_custom_fields;
@ -89,7 +89,7 @@ class Import {
'profiler' => $this->timeExecution()
);
}
function filterExistingAndNewSubscribers($subscribers_data) {
$existing_records = array_filter(
array_map(function($subscriber_emails) {
@ -126,7 +126,7 @@ class Import {
}, $new_records);
}, $subscribers_data)
);
$existing_subscribers =
array_map(function($subscriber) use ($new_records) {
return array_values( // reindex array
@ -142,7 +142,7 @@ class Import {
$new_subscribers
);
}
function deleteExistingTrashedSubscribers($subscribers_data) {
$existing_trashed_records = array_filter(
array_map(function($subscriber_emails) {
@ -161,7 +161,7 @@ class Import {
->deleteMany();
}
}
function extendSubscribersAndFields($subscribers_data, $subscriber_fields) {
$subscribers_data['created_at'] = $this->filterSubscriberCreatedAtDate();
$subscriber_fields[] = 'created_at';
@ -170,7 +170,7 @@ class Import {
$subscriber_fields
);
}
function getSubscriberFields($subscriber_fields) {
return array_values(
array_filter(
@ -180,7 +180,7 @@ class Import {
)
);
}
function getCustomSubscriberFields($subscriber_fields) {
return array_values(
array_filter(
@ -190,11 +190,11 @@ class Import {
)
);
}
function filterSubscriberCreatedAtDate() {
return array_fill(0, $this->subscribers_count, $this->import_time);
}
function filterSubscriberStatus($subscribers_data, $subscriber_fields) {
if(!in_array('status', $subscriber_fields)) {
$subscribers_data['status'] =
@ -242,7 +242,7 @@ class Import {
$subscriber_fields
);
}
function createOrUpdateSubscribers(
$action,
$subscribers_data,
@ -295,7 +295,7 @@ class Import {
);
return $result;
}
function createOrUpdateCustomFields(
$action,
$db_subscribers,
@ -318,8 +318,8 @@ class Import {
$value
);
}, $count, $subscribers_data[$column]);
}, $subscriber_custom_fields)[0];
foreach(array_chunk($subscribers, 200) as $data) {
}, $subscriber_custom_fields);
foreach(array_chunk($subscribers[0], 200) as $data) {
if($action === 'create') {
SubscriberCustomField::createMultiple(
$data
@ -332,13 +332,13 @@ class Import {
}
}
}
function addSubscribersToSegments($subscribers, $segments) {
foreach(array_chunk($subscribers, 200) as $data) {
SubscriberSegment::createMultiple($segments, $data);
}
}
function timeExecution() {
$profiler_end = microtime(true);
return ($profiler_end - $this->profiler_start) / 60;

View File

@ -5,19 +5,19 @@ use MailPoet\Util\Helpers;
class MailChimp {
function __construct($APIKey, $lists = false) {
$this->APIKey = $this->getAPIKey($APIKey);
$this->maxPostSize = Helpers::getMaxPostSize('bytes');
$this->dataCenter = $this->getDataCenter($this->APIKey);
$this->listsURL = 'https://%s.api.mailchimp.com/2.0/lists/list?apikey=%s';
$this->exportURL = 'https://%s.api.mailchimp.com/export/1.0/list/?apikey=%s&id=%s';
$this->api_key = $this->getAPIKey($APIKey);
$this->max_post_size = Helpers::getMaxPostSize('bytes');
$this->data_center = $this->getDataCenter($this->api_key);
$this->lists_url = 'https://%s.api.mailchimp.com/2.0/lists/list?apikey=%s';
$this->export_url = 'https://%s.api.mailchimp.com/export/1.0/list/?apikey=%s&id=%s';
}
function getLists() {
if(!$this->APIKey || !$this->dataCenter) {
if(!$this->api_key || !$this->data_center) {
return $this->processError('API');
}
$connection = @fopen(sprintf($this->listsURL, $this->dataCenter, $this->APIKey), 'r');
$connection = @fopen(sprintf($this->lists_url, $this->data_center, $this->api_key), 'r');
if(!$connection) {
return $this->processError('connection');
@ -52,7 +52,7 @@ class MailChimp {
}
function getSubscribers($lists = array()) {
if(!$this->APIKey || !$this->dataCenter) {
if(!$this->api_key || !$this->data_center) {
return $this->processError('API');
}
@ -60,9 +60,9 @@ class MailChimp {
return $this->processError('lists');
}
$bytesFetched = 0;
$bytes_fetched = 0;
foreach ($lists as $list) {
$url = sprintf($this->exportURL, $this->dataCenter, $this->APIKey, $list);
$url = sprintf($this->export_url, $this->data_center, $this->api_key, $list);
$connection = @fopen($url, 'r');
if(!$connection) {
return $this->processError('connection');
@ -78,10 +78,10 @@ class MailChimp {
if(is_object($header) && isset($header->error)) {
return $this->processError('lists');
}
if(!isset($headerHash)) {
$headerHash = md5(implode(',', $header));
if(!isset($header_hash)) {
$header_hash = md5(implode(',', $header));
} else {
if(md5(implode(',', $header) !== $headerHash)) {
if(md5(implode(',', $header) !== $header_hash)) {
return $this->processError('headers');
}
}
@ -91,8 +91,8 @@ class MailChimp {
$i++;
}
$bytesFetched += strlen($buffer);
if($bytesFetched > $this->maxPostSize) {
$bytes_fetched += strlen($buffer);
if($bytes_fetched > $this->max_post_size) {
return $this->processError('size');
}
@ -119,8 +119,9 @@ class MailChimp {
}
function getDataCenter($APIKey) {
if (!preg_match('/-[a-zA-Z0-9]{3,}/', $APIKey)) return false;
// double parantheses: http://phpsadness.com/sad/51
return ($APIKey) ? end((explode('-', $APIKey))) : false;
return end((explode('-', $APIKey)));
}
function getAPIKey($APIKey) {
@ -150,7 +151,7 @@ class MailChimp {
}
return array(
'result' => false,
'error' => $errorMessage
'errors' => array($errorMessage)
);
}
}

View File

@ -8,13 +8,22 @@ class Comment {
const APPROVED = 1;
const PENDING_APPROVAL = 0;
static function extendForm() {
static function extendLoggedInForm($field) {
$field .= self::getSubscriptionField();
return $field;
}
static function extendLoggedOutForm() {
echo self::getSubscriptionField();
}
static function getSubscriptionField() {
$label = Setting::getValue(
'subscribe.on_comment.label',
__('Yes, add me to your mailing list.')
);
print '<p class="comment-form-mailpoet">
return '<p class="comment-form-mailpoet">
<label for="mailpoet_subscribe_on_comment">
<input
type="checkbox"

View File

@ -12,7 +12,7 @@ class DKIM {
'public' => self::trimKey($rsa_keys['publickey']),
'private' => self::trimKey($rsa_keys['privatekey'])
);
} catch(Exception $e) {
} catch(\Exception $e) {
return false;
}
}

View File

@ -1,12 +1,10 @@
<?php
use \MailPoet\Config\Initializer;
use \MailPoet\Config\Migrator;
if(!defined('ABSPATH')) exit;
use \MailPoet\Config\Initializer;
/*
* Plugin Name: MailPoet
* Version: 0.0.13
* Version: 0.0.15
* Plugin URI: http://www.mailpoet.com
* Description: MailPoet Newsletters.
* Author: MailPoet
@ -24,16 +22,10 @@ if(!defined('ABSPATH')) exit;
require 'vendor/autoload.php';
define('MAILPOET_VERSION', '0.0.13');
define('MAILPOET_VERSION', '0.0.15');
$initializer = new Initializer(array(
'file' => __FILE__,
'version' => MAILPOET_VERSION
));
$migrator = new Migrator();
register_activation_hook(__FILE__, array($migrator, 'up'));
register_activation_hook(__FILE__, array($initializer, 'runPopulator'));
add_action('init', array($initializer, 'init'));
$initializer->init();

View File

@ -9,10 +9,12 @@ $console->writeln('Loading WP core... ('.$wp_load_file.')');
$console->writeln('Cleaning up database...');
$models = array(
'CustomField',
'Form',
'Newsletter',
'NewsletterSegment',
'NewsletterTemplate',
'Segment',
'SendingQueue',
'Setting',
'Subscriber',
'SubscriberCustomField',

View File

@ -71,7 +71,7 @@ define([
});
it('has image width', function () {
expect(model.get('imagePadded')).to.be.a('boolean');
expect(model.get('imageFullWidth')).to.be.a('boolean');
});
it('has an option to display author', function () {
@ -126,7 +126,7 @@ define([
titlePosition: 'aboveBlock', // 'inTextBlock'|'aboveBlock',
titleAlignment: 'right', // 'left'|'center'|'right'
titleIsLink: true, // false|true
imagePadded: false, // true|false
imageFullWidth: false, // true|false
showAuthor: 'belowText', // 'no'|'aboveText'|'belowText'
authorPrecededBy: 'Custom config author preceded by',
showCategories: 'belowText', // 'no'|'aboveText'|'belowText'
@ -172,7 +172,7 @@ define([
expect(model.get('titlePosition')).to.equal('aboveBlock');
expect(model.get('titleAlignment')).to.equal('right');
expect(model.get('titleIsLink')).to.equal(true);
expect(model.get('imagePadded')).to.equal(false);
expect(model.get('imageFullWidth')).to.equal(false);
expect(model.get('showAuthor')).to.equal('belowText');
expect(model.get('authorPrecededBy')).to.equal('Custom config author preceded by');
expect(model.get('showCategories')).to.equal('belowText');
@ -346,8 +346,8 @@ define([
it('changes the model if image alignment changes', function () {
var newValue = false;
view.$('.mailpoet_automated_latest_content_image_padded').val(newValue).change();
expect(model.get('imagePadded')).to.equal(newValue);
view.$('.mailpoet_automated_latest_content_image_full_width').val(newValue).change();
expect(model.get('imageFullWidth')).to.equal(newValue);
});
it('changes the model if show author changes', function () {

View File

@ -30,8 +30,8 @@ define([
expect(model.get('alt')).to.be.a('string');
});
it('can be padded', function () {
expect(model.get('padded')).to.be.a('boolean');
it('can be full width', function () {
expect(model.get('fullWidth')).to.be.a('boolean');
});
it('has a width', function () {
@ -61,7 +61,7 @@ define([
model.set('link', 'http://example.net');
model.set('src', 'someNewImage.png');
model.set('alt', 'Some alt text');
model.set('padded', false);
model.set('fullWidth', false);
model.set('width', '63px');
model.set('height', '61px');
model.set('styles.block.textAlign', 'right');
@ -76,7 +76,7 @@ define([
link: 'http://example.org/customConfigPage',
src: 'http://example.org/someCustomConfigImage.png',
alt: 'Custom config alt',
padded: false,
fullWidth: false,
width: '1234px',
height: '2345px',
styles: {
@ -92,7 +92,7 @@ define([
expect(model.get('link')).to.equal('http://example.org/customConfigPage');
expect(model.get('src')).to.equal('http://example.org/someCustomConfigImage.png');
expect(model.get('alt')).to.equal('Custom config alt');
expect(model.get('padded')).to.equal(false);
expect(model.get('fullWidth')).to.equal(false);
expect(model.get('width')).to.equal('1234px');
expect(model.get('height')).to.equal('2345px');
expect(model.get('styles.block.textAlign')).to.equal('right');
@ -182,8 +182,8 @@ define([
it('updates the model when padding changes', function () {
var newValue = 'false';
view.$('.mailpoet_field_image_padded').prop('checked', false).change();
expect(model.get('padded')).to.equal(false);
view.$('.mailpoet_field_image_full_width').prop('checked', false).change();
expect(model.get('fullWidth')).to.equal(false);
});
it.skip('closes the sidepanel after "Done" is clicked', function() {

View File

@ -74,7 +74,7 @@ define([
});
it('has image specific alignment', function () {
expect(model.get('imagePadded')).to.be.a('boolean');
expect(model.get('imageFullWidth')).to.be.a('boolean');
});
it('has an option to display author', function () {
@ -129,7 +129,7 @@ define([
titlePosition: 'aboveBlock', // 'inTextBlock'|'aboveBlock',
titleAlignment: 'right', // 'left'|'center'|'right'
titleIsLink: true, // false|true
imagePadded: false, // true|false
imageFullWidth: false, // true|false
//imageAlignment: 'right', // 'centerFull'|'centerPadded'|'left'|'right'|'alternate'|'none'
showAuthor: 'belowText', // 'no'|'aboveText'|'belowText'
authorPrecededBy: 'Custom config author preceded by',
@ -176,7 +176,7 @@ define([
expect(model.get('titlePosition')).to.equal('aboveBlock');
expect(model.get('titleAlignment')).to.equal('right');
expect(model.get('titleIsLink')).to.equal(true);
expect(model.get('imagePadded')).to.equal(false);
expect(model.get('imageFullWidth')).to.equal(false);
expect(model.get('showAuthor')).to.equal('belowText');
expect(model.get('authorPrecededBy')).to.equal('Custom config author preceded by');
expect(model.get('showCategories')).to.equal('belowText');
@ -318,8 +318,8 @@ define([
it('changes the model if image alignment changes', function () {
var newValue = false;
view.$('.mailpoet_posts_image_padded').val(newValue).change();
expect(model.get('imagePadded')).to.equal(newValue);
view.$('.mailpoet_posts_image_full_width').val(newValue).change();
expect(model.get('imageFullWidth')).to.equal(newValue);
});
it('changes the model if show author changes', function () {

View File

@ -1,6 +1,7 @@
<?php
use MailPoet\Listing;
use MailPoet\Models\Subscriber;
class ListingCest {
function _before() {
@ -57,6 +58,6 @@ class ListingCest {
}
function _after() {
Subscriber::deleteMany();
}
}

View File

@ -94,6 +94,7 @@ class MailerCest {
}
function itCanSend() {
if(getenv('WP_TEST_MAILER_ENABLE_SENDING') !== 'true') return;
$mailer = new Mailer($this->mailer, $this->sender, $this->reply_to);
expect($mailer->send($this->newsletter, $this->subscriber))->true();
}

View File

@ -6,16 +6,12 @@ use MailPoet\Models\SubscriberCustomField;
class CustomFieldCest {
function _before() {
$this->before_time = time();
$this->data = array(
'name' => 'DOB',
'type' => 'date',
'params' => 'none'
);
$this->customField = CustomField::create();
$this->customField->hydrate($this->data);
$this->saved = $this->customField->save();
$this->subscribersData = array(
$this->custom_field = CustomField::createOrUpdate(array(
'name' => 'Birthdate',
'type' => 'date'
));
$this->subscribers = array(
array(
'first_name' => 'John',
'last_name' => 'Mailer',
@ -30,98 +26,84 @@ class CustomFieldCest {
}
function itCanBeCreated() {
expect($this->saved)->equals(true);
expect($this->custom_field->id() > 0)->true();
expect($this->custom_field->getErrors())->false();
}
function itCanHaveName() {
expect($this->customField->name)->equals($this->data['name']);
function itHasAName() {
expect($this->custom_field->name)->equals('Birthdate');
}
function itCanHaveType() {
expect($this->customField->type)->equals($this->data['type']);
function itHasAType() {
expect($this->custom_field->type)->equals('date');
}
function itCanHaveParams() {
expect(unserialize($this->customField->params))->equals($this->data['params']);
function itCanDecodeParams() {
$custom_field = $this->custom_field->asArray();
expect($custom_field['params'])->hasKey('label');
}
function itHasDefaultParams() {
$params = unserialize($this->custom_field->params);
expect($params['label'])->equals('Birthdate');
}
function itHasToBeValid() {
$empty_model = CustomField::create();
expect($empty_model->save())->notEquals(true);
$validations = $empty_model->getValidationErrors();
expect(count($validations))->equals(2);
$invalid_custom_field = CustomField::create();
$result = $invalid_custom_field->save();
$errors = $result->getErrors();
expect(is_array($errors))->true();
expect($errors[0])->equals('You need to specify a name.');
expect($errors[1])->equals('You need to specify a type.');
}
function itHasACreatedAtOnCreation() {
$customField = CustomField::where('name', $this->data['name'])
->findOne();
$time_difference = strtotime($customField->created_at) >= $this->before_time;
expect($time_difference)->equals(true);
}
function itCanBeUpdated() {
$custom_field = $this->custom_field->asArray();
$custom_field['name'] = 'Favorite color';
$custom_field['type'] = 'text';
function itHasAnUpdatedAtOnCreation() {
$customField = CustomField::where('name', $this->data['name'])
->findOne();
$time_difference = strtotime($customField->updated_at) >= $this->before_time;
expect($time_difference)->equals(true);
}
$custom_field = CustomField::createOrUpdate($custom_field);
function itKeepsTheCreatedAtOnUpdate() {
$customField = CustomField::where('name', $this->data['name'])
->findOne();
$old_created_at = $customField->created_at;
$customField->name = 'new name';
$customField->save();
expect($old_created_at)->equals($customField->created_at);
}
expect($custom_field->getErrors())->false();
function itUpdatesTheUpdatedAtOnUpdate() {
$customField = CustomField::where('name', $this->data['name'])
->findOne();
$update_time = time();
$customField->name = 'new name';
$customField->save();
$time_difference = strtotime($customField->updated_at) >= $update_time;
expect($time_difference)->equals(true);
$updated_custom_field = CustomField::findOne($custom_field->id);
expect($updated_custom_field->name)->equals('Favorite color');
expect($updated_custom_field->type)->equals('text');
}
function itCanHaveManySubscribers() {
foreach ($this->subscribersData as $data) {
$subscriber = Subscriber::create();
$subscriber->hydrate($data);
$subscriber->save();
foreach($this->subscribers as $subscriber) {
$subscriber = Subscriber::createOrUpdate($subscriber);
$association = SubscriberCustomField::create();
$association->subscriber_id = $subscriber->id;
$association->custom_field_id = $this->customField->id;
$association->custom_field_id = $this->custom_field->id;
$association->save();
}
$customField = CustomField::findOne($this->customField->id);
$subscribers = $customField->subscribers()
->findArray();
$custom_field = CustomField::findOne($this->custom_field->id);
$subscribers = $custom_field->subscribers()->findArray();
expect(count($subscribers))->equals(2);
}
function itCanStoreCustomFieldValue() {
$subscriber = Subscriber::create();
$subscriber->hydrate($this->subscribersData[0]);
$subscriber->save();
function itCanHaveAValue() {
$subscriber = Subscriber::createOrUpdate($this->subscribers[0]);
$association = SubscriberCustomField::create();
$association->subscriber_id = $subscriber->id;
$association->custom_field_id = $this->customField->id;
$association->custom_field_id = $this->custom_field->id;
$association->value = '12/12/2012';
$association->save();
$customField = CustomField::findOne($this->customField->id);
$subscriber = $customField->subscribers()
->findOne();
$custom_field = CustomField::findOne($this->custom_field->id);
$subscriber = $custom_field->subscribers()->findOne();
expect($subscriber->value)->equals($association->value);
}
function _after() {
ORM::forTable(CustomField::$_table)
->deleteMany();
ORM::forTable(Subscriber::$_table)
->deleteMany();
ORM::forTable(SubscriberCustomField::$_table)
->deleteMany();
CustomField::deleteMany();
Subscriber::deleteMany();
SubscriberCustomField::deleteMany();
}
}

View File

@ -3,82 +3,69 @@ use MailPoet\Models\Form;
class FormCest {
function _before() {
$this->before_time = time();
$this->data = array(
'name' => 'my form',
);
$this->form = Form::create();
$this->form->hydrate($this->data);
$this->saved = $this->form->save();
$this->form = Form::createOrUpdate(array(
'name' => 'My Form'
));
}
function itCanBeCreated() {
expect($this->saved)->equals(true);
expect($this->form->id() > 0)->true();
expect($this->form->getErrors())->false();
}
function itHasToBeValid() {
expect($this->saved)->equals(true);
$empty_model = Form::create();
expect($empty_model->save())->notEquals(true);
$validations = $empty_model->getValidationErrors();
expect(count($validations))->equals(1);
$invalid_form = Form::create();
$result = $invalid_form->save();
$errors = $result->getErrors();
expect(is_array($errors))->true();
expect($errors[0])->equals('You need to specify a name.');
}
function itHasACreatedAtOnCreation() {
$form = Form::where('name', $this->data['name'])
->findOne();
$time_difference = strtotime($form->created_at) >= $this->before_time;
expect($time_difference)->equals(true);
function itCanBeGrouped() {
$forms = Form::filter('groupBy', 'all')->findArray();
expect($forms)->count(1);
$forms = Form::filter('groupBy', 'trash')->findArray();
expect($forms)->count(0);
$this->form->trash();
$forms = Form::filter('groupBy', 'trash')->findArray();
expect($forms)->count(1);
$forms = Form::filter('groupBy', 'all')->findArray();
expect($forms)->count(0);
$this->form->restore();
$forms = Form::filter('groupBy', 'all')->findArray();
expect($forms)->count(1);
}
function itHasAnUpdatedAtOnCreation() {
$form = Form::where('name', $this->data['name'])
->findOne();
$time_difference = strtotime($form->updated_at) >= $this->before_time;
expect($time_difference)->equals(true);
}
function itKeepsTheCreatedAtOnUpdate() {
$form = Form::where('name', $this->data['name'])
->findOne();
$old_created_at = $form->created_at;
$form->name = 'new name';
$form->save();
expect($old_created_at)->equals($form->created_at);
}
function itUpdatesTheUpdatedAtOnUpdate() {
$form = Form::where('name', $this->data['name'])
->findOne();
$update_time = time();
$form->name = 'new name';
$form->save();
$time_difference = strtotime($form->updated_at) >= $update_time;
expect($time_difference)->equals(true);
function itCanBeSearched() {
$form = Form::filter('search', 'my F')->findOne();
expect($form->name)->equals('My Form');
}
function itCanCreateOrUpdate() {
$is_created = Form::createOrUpdate(array(
'name' => 'new form'
$created_form = Form::createOrUpdate(array(
'name' => 'Created Form'
));
expect($is_created)->notEquals(false);
expect($is_created->getValidationErrors())->isEmpty();
expect($created_form->id > 0)->true();
expect($created_form->getErrors())->false();
$form = Form::where('name', 'new form')->findOne();
expect($form->name)->equals('new form');
$form = Form::findOne($created_form->id);
expect($form->name)->equals('Created Form');
$is_updated = Form::createOrUpdate(array(
'id' => $form->id,
'name' => 'updated form'
'id' => $created_form->id,
'name' => 'Updated Form'
));
$form = Form::where('name', 'updated form')->findOne();
expect($form->name)->equals('updated form');
$form = Form::findOne($created_form->id);
expect($form->name)->equals('Updated Form');
}
function _after() {
ORM::forTable(Form::$_table)
->deleteMany();
Form::deleteMany();
}
}

View File

@ -2,85 +2,91 @@
use MailPoet\Models\Newsletter;
use MailPoet\Models\Segment;
use MailPoet\Models\SendingQueue;
use MailPoet\Models\NewsletterSegment;
use MailPoet\Models\NewsletterOptionField;
use MailPoet\Models\NewsletterOption;
class NewsletterCest {
function _before() {
$this->before_time = time();
$this->data = array(
'subject' => 'new newsletter',
'body' => 'body',
'type' => 'standard',
'preheader' => 'preheader'
);
$this->newsletter = Newsletter::createOrUpdate(array(
'subject' => 'My Standard Newsletter',
'preheader' => 'Pre Header',
'type' => 'standard'
));
$newsletter = Newsletter::create();
$newsletter->hydrate($this->data);
$this->newsletter = $newsletter;
$this->result = $newsletter->save();
$this->segment_1 = Segment::createOrUpdate(array(
'name' => 'Segment 1'
));
$association = NewsletterSegment::create();
$association->newsletter_id = $this->newsletter->id;
$association->segment_id = $this->segment_1->id;
$association->save();
$this->segment_2 = Segment::createOrUpdate(array(
'name' => 'Segment 2'
));
$association = NewsletterSegment::create();
$association->newsletter_id = $this->newsletter->id;
$association->segment_id = $this->segment_2->id;
$association->save();
}
function itCanBeCreated() {
expect($this->result)->equals(true);
expect($this->newsletter->id() > 0)->true();
expect($this->newsletter->getErrors())->false();
}
function itHasSubject() {
$newsletter = Newsletter::where('subject', $this->data['subject'])
->findOne();
expect($newsletter->subject)->equals($this->data['subject']);
$newsletter = Newsletter::findOne($this->newsletter->id);
expect($newsletter->subject)->equals($this->newsletter->subject);
}
function itHasType() {
$newsletter = Newsletter::where('type', $this->data['type'])
->findOne();
expect($newsletter->type)->equals($this->data['type']);
function itHasAType() {
$newsletter = Newsletter::findOne($this->newsletter->id);
expect($newsletter->type)->equals($this->newsletter->type);
}
function itHasBody() {
$newsletter = Newsletter::where('body', $this->data['body'])
->findOne();
expect($newsletter->body)->equals($this->data['body']);
function itHasABody() {
$newsletter = Newsletter::findOne($this->newsletter->id);
expect($newsletter->body)->equals($this->newsletter->body);
}
function itHasPreheader() {
$newsletter = Newsletter::where('preheader', $this->data['preheader'])
->findOne();
expect($newsletter->preheader)->equals($this->data['preheader']);
$newsletter = Newsletter::findOne($this->newsletter->id);
expect($newsletter->preheader)->equals($this->newsletter->preheader);
}
function itCanHaveASegment() {
$segmentData = array(
'name' => 'my first list'
);
function itCanBeQueued() {
$queue = $this->newsletter->getQueue();
expect($queue)->false();
$segment = Segment::create();
$segment->hydrate($segmentData);
$segment->save();
$sending_queue = SendingQueue::create();
$sending_queue->newsletter_id = $this->newsletter->id;
$sending_queue->save();
$newsletter = Newsletter::create();
$newsletter->hydrate($this->data);
$newsletter->save();
$queue = $this->newsletter->getQueue();
expect($queue->id() > 0)->true();
}
$association = NewsletterSegment::create();
$association->newsletter_id = $newsletter->id();
$association->segment_id = $segment->id();
$association->save();
$newsletter = Newsletter::findOne($newsletter->id);
$newsletterSegment = $newsletter->segments()->findOne();
expect($newsletterSegment->id)->equals($segment->id);
function itCanHaveSegments() {
$newsletter_segments = $this->newsletter->segments()->findArray();
expect($newsletter_segments)->count(2);
expect($newsletter_segments[0]['id'])->equals($this->segment_1->id);
expect($newsletter_segments[0]['name'])->equals('Segment 1');
expect($newsletter_segments[1]['id'])->equals($this->segment_2->id);
expect($newsletter_segments[1]['name'])->equals('Segment 2');
}
function itCanCreateOrUpdate() {
$is_created = Newsletter::createOrUpdate(
array(
'subject' => 'new newsletter',
'type' => 'standard',
'body' => 'body'
));
expect($is_created)->notEquals(false);
expect($is_created->getValidationErrors())->isEmpty();
expect($is_created->id() > 0)->true();
expect($is_created->getErrors())->false();
$newsletter = Newsletter::where('subject', 'new newsletter')
->findOne();
@ -89,17 +95,65 @@ class NewsletterCest {
$is_updated = Newsletter::createOrUpdate(
array(
'id' => $newsletter->id,
'subject' => 'updated newsletter',
'body' => 'body'
'subject' => 'updated newsletter'
));
$newsletter = Newsletter::findOne($newsletter->id);
expect($newsletter->subject)->equals('updated newsletter');
}
function itCannotSetAnEmptyDeletedAt() {
$this->newsletter->deleted_at = '';
$newsletter = $this->newsletter->save();
expect($newsletter->deleted_at)->equals('NULL');
}
function itCanBeFilteredBySegment() {
// no filter
$newsletters = Newsletter::filter('filterBy')->findArray();
expect($newsletters)->count(1);
// filter by segment
$newsletters = Newsletter::filter('filterBy', array(
'segment' => $this->segment_1->id
))->findArray();
expect($newsletters)->count(1);
expect($newsletters[0]['subject'])->equals($this->newsletter->subject);
// remove all segment relations to newsletters
NewsletterSegment::deleteMany();
$newsletters = Newsletter::filter('filterBy', array(
'segment' => $this->segment_1->id
))->findArray();
expect($newsletters)->isEmpty();
}
function itCanBeGrouped() {
$newsletters = Newsletter::filter('groupBy', 'all')->findArray();
expect($newsletters)->count(1);
$newsletters = Newsletter::filter('groupBy', 'trash')->findArray();
expect($newsletters)->count(0);
$this->newsletter->trash();
$newsletters = Newsletter::filter('groupBy', 'trash')->findArray();
expect($newsletters)->count(1);
$newsletters = Newsletter::filter('groupBy', 'all')->findArray();
expect($newsletters)->count(0);
$this->newsletter->restore();
$newsletters = Newsletter::filter('groupBy', 'all')->findArray();
expect($newsletters)->count(1);
}
function itHasSearchFilter() {
Newsletter::createOrUpdate(
array(
'subject' => 'search for "pineapple"',
'type' => 'standard',
'body' => 'body'
));
$newsletter = Newsletter::filter('search', 'pineapple')
@ -108,16 +162,16 @@ class NewsletterCest {
}
function itCanHaveOptions() {
$newsletterOptionFieldData = array(
$newsletter_options = array(
'name' => 'Event',
'newsletter_type' => 'welcome',
);
$optionField = NewsletterOptionField::create();
$optionField->hydrate($newsletterOptionFieldData);
$optionField->save();
$option_field = NewsletterOptionField::create();
$option_field->hydrate($newsletter_options);
$option_field->save();
$association = NewsletterOption::create();
$association->newsletter_id = $this->newsletter->id;
$association->option_field_id = $optionField->id;
$association->option_field_id = $option_field->id;
$association->value = 'list';
$association->save();
$newsletter = Newsletter::filter('filterWithOptions')
@ -126,7 +180,7 @@ class NewsletterCest {
}
function itCanFilterOptions() {
$newsletterOptionFieldData = array(
$newsletter_options = array(
array(
'name' => 'Event',
'newsletter_type' => 'welcome',
@ -136,13 +190,13 @@ class NewsletterCest {
'newsletter_type' => 'welcome',
)
);
foreach ($newsletterOptionFieldData as $data) {
$optionField = NewsletterOptionField::create();
$optionField->hydrate($data);
$optionField->save();
$createdOptionFields[] = $optionField->asArray();
foreach ($newsletter_options as $data) {
$option_field = NewsletterOptionField::create();
$option_field->hydrate($data);
$option_field->save();
$createdOptionFields[] = $option_field->asArray();
}
$newsletterOptionData = array(
$newsletter_options = array(
array(
'newsletter_id' => $this->newsletter->id,
'option_field_id' => $createdOptionFields[0]['id'],
@ -154,12 +208,12 @@ class NewsletterCest {
'value' => '1'
)
);
foreach ($newsletterOptionData as $data) {
foreach($newsletter_options as $data) {
$association = NewsletterOption::create();
$association->hydrate($data);
$association->save();
$createdAssociations[] = $association->asArray();
}
$newsletter = Newsletter::filter('filterWithOptions')
->filter('filterSearchCustomFields', array(
array(
@ -198,11 +252,11 @@ class NewsletterCest {
}
function _after() {
ORM::forTable(NewsletterOption::$_table)
->deleteMany();
ORM::forTable(NewsletterOptionField::$_table)
->deleteMany();
ORM::for_table(Newsletter::$_table)
->deleteMany();
NewsletterOption::deleteMany();
NewsletterOptionField::deleteMany();
Newsletter::deleteMany();
Segment::deleteMany();
NewsletterSegment::deleteMany();
SendingQueue::deleteMany();
}
}

View File

@ -9,19 +9,21 @@ class NewsletterOptionFieldCest {
$this->before_time = time();
$this->data = array(
'name' => 'Event',
'newsletter_type' => 'welcome',
'newsletter_type' => 'welcome'
);
$this->optionField = NewsletterOptionField::create();
$this->optionField->hydrate($this->data);
$this->saved = $this->optionField->save();
$this->newslettersData = array(
$this->option_field = NewsletterOptionField::create();
$this->option_field->hydrate($this->data);
$this->saved = $this->option_field->save();
$this->newsletter_data = array(
array(
'subject' => 'Test newsletter 1',
'type' => 'standard',
'preheader' => '',
'body' => '{}'
),
array(
'subject' => 'Test newsletter 2',
'type' => 'standard',
'preheader' => 'A newsletter',
'body' => '{}'
)
@ -29,89 +31,92 @@ class NewsletterOptionFieldCest {
}
function itCanBeCreated() {
expect($this->saved)->equals(true);
expect($this->saved->id() > 0)->true();
expect($this->saved->getErrors())->false();
}
function itHasName() {
$optionField = NewsletterOptionField::where('name', $this->data['name'])
$option_field = NewsletterOptionField::where('name', $this->data['name'])
->findOne();
expect($optionField->name)->equals($this->data['name']);
expect($option_field->name)->equals($this->data['name']);
}
function itHasNewsletterType() {
$optionField = NewsletterOptionField::where('name', $this->data['name'])
$option_field = NewsletterOptionField::where('name', $this->data['name'])
->findOne();
expect($optionField->newsletter_type)->equals($this->data['newsletter_type']);
expect($option_field->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);
$invalid_newsletter_option = NewsletterOptionField::create();
$result = $invalid_newsletter_option->save();
$errors = $result->getErrors();
expect(is_array($errors))->true();
expect($errors[0])->equals('You need to specify a name.');
expect($errors[1])->equals('You need to specify a newsletter type.');
}
function itHasACreatedAtOnCreation() {
$optionField = NewsletterOptionField::where('name', $this->data['name'])
$option_field = NewsletterOptionField::where('name', $this->data['name'])
->findOne();
$time_difference = strtotime($optionField->created_at) >= $this->before_time;
$time_difference = strtotime($option_field->created_at) >= $this->before_time;
expect($time_difference)->equals(true);
}
function itHasAnUpdatedAtOnCreation() {
$optionField = NewsletterOptionField::where('name', $this->data['name'])
$option_field = NewsletterOptionField::where('name', $this->data['name'])
->findOne();
$time_difference = strtotime($optionField->updated_at) >= $this->before_time;
$time_difference = strtotime($option_field->updated_at) >= $this->before_time;
expect($time_difference)->equals(true);
}
function itKeepsTheCreatedAtOnUpdate() {
$optionField = NewsletterOptionField::where('name', $this->data['name'])
$option_field = 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);
$old_created_at = $option_field->created_at;
$option_field->name = 'new name';
$option_field->save();
expect($old_created_at)->equals($option_field->created_at);
}
function itUpdatesTheUpdatedAtOnUpdate() {
$optionField = NewsletterOptionField::where('name', $this->data['name'])
$option_field = NewsletterOptionField::where('name', $this->data['name'])
->findOne();
$update_time = time();
$optionField->name = 'new name';
$optionField->save();
$time_difference = strtotime($optionField->updated_at) >= $update_time;
$option_field->name = 'new name';
$option_field->save();
$time_difference = strtotime($option_field->updated_at) >= $update_time;
expect($time_difference)->equals(true);
}
function itCanHaveManyNewsletters() {
foreach ($this->newslettersData as $data) {
foreach($this->newsletter_data 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->option_field_id = $this->option_field->id;
$association->save();
}
$optionField = NewsletterOptionField::findOne($this->optionField->id);
$newsletters = $optionField->newsletters()
$option_field = NewsletterOptionField::findOne($this->option_field->id);
$newsletters = $option_field->newsletters()
->findArray();
expect(count($newsletters))->equals(2);
}
function itCanStoreOptionValue() {
$newsletter = Newsletter::create();
$newsletter->hydrate($this->newslettersData[0]);
$newsletter->hydrate($this->newsletter_data[0]);
$newsletter->save();
$association = NewsletterOption::create();
$association->newsletter_id = $newsletter->id;
$association->option_field_id = $this->optionField->id;
$association->option_field_id = $this->option_field->id;
$association->value = 'list';
$association->save();
$optionField = NewsletterOptionField::findOne($this->optionField->id);
$newsletter = $optionField->newsletters()
$option_field = NewsletterOptionField::findOne($this->option_field->id);
$newsletter = $option_field->newsletters()
->findOne();
expect($newsletter->value)->equals($association->value);
}

View File

@ -8,23 +8,27 @@ class NewsletterTemplateCest {
$this->data = array(
'name' => 'Some template',
'description' => 'My nice template',
'body' => '{content: {}, globalStyles: {}}',
'body' => '{}',
);
$template = NewsletterTemplate::create();
$template->hydrate($this->data);
$this->result = $template->save();
$this->saved = $template->save();
}
function itCanBeCreated() {
expect($this->result)->equals(true);
expect($this->saved->id() > 0)->true();
expect($this->saved->getErrors())->false();
}
function itHasToBeValid() {
$empty_model = NewsletterTemplate::create();
expect($empty_model->save())->notEquals(true);
$validations = $empty_model->getValidationErrors();
expect(count($validations))->equals(2);
$invalid_newsletter_template = NewsletterTemplate::create();
$result = $invalid_newsletter_template->save();
$errors = $result->getErrors();
expect(is_array($errors))->true();
expect($errors[0])->equals('You need to specify a name.');
expect($errors[1])->equals('Template body cannot be empty.');
}
function itHasName() {
@ -46,25 +50,28 @@ class NewsletterTemplateCest {
}
function itCanCreateOrUpdate() {
$is_created = NewsletterTemplate::createOrUpdate(
$created_template = NewsletterTemplate::createOrUpdate(
array(
'name' => 'Another template',
'description' => 'Another template description',
'body' => '{content: {}, globalStyles: {}}',
));
expect($is_created)->equals(true);
expect($created_template->id() > 0)->true();
expect($created_template->getErrors())->false();
$template = NewsletterTemplate::where('name', 'Another template')
->findOne();
expect($template->name)->equals('Another template');
$is_updated = NewsletterTemplate::createOrUpdate(
$updated_template = NewsletterTemplate::createOrUpdate(
array(
'id' => $template->id,
'name' => 'Another template updated',
'body' => '{}'
));
expect($is_updated)->equals(true);
expect($updated_template->id() > 0)->true();
expect($updated_template->getErrors())->false();
$template = NewsletterTemplate::findOne($template->id);
expect($template->name)->equals('Another template updated');
}

View File

@ -13,7 +13,7 @@ class SegmentCest {
'name' => 'some name',
'description' => 'some description'
);
$this->subscribersData = array(
$this->subscribers_data = array(
array(
'first_name' => 'John',
'last_name' => 'Mailer',
@ -27,21 +27,22 @@ class SegmentCest {
'email' => 'mike@maipoet.com'
)
);
$this->newslettersData = array(
$this->newsletters_data = array(
array(
'subject' => 'My first newsletter'
'subject' => 'My first newsletter',
'type' => 'standard'
),
array(
'subject' => 'My second newsletter'
'subject' => 'My second newsletter',
'type' => 'standard'
)
);
$this->segment = Segment::create();
$this->segment->hydrate($this->data);
$this->saved = $this->segment->save();
$this->segment = Segment::createOrUpdate($this->data);
}
function itCanBeCreated() {
expect($this->saved)->equals(true);
expect($this->segment->id() > 0)->true();
expect($this->segment->getErrors())->false();
}
function itCanHaveName() {
@ -51,7 +52,13 @@ class SegmentCest {
function nameMustBeUnique() {
$segment = Segment::create();
$segment->hydrate($this->data);
expect($segment->save())->contains('Duplicate');
$result = $segment->save();
$errors = $result->getErrors();
expect(is_array($errors))->true();
expect($errors[0])->equals(
'Another record already exists. Please specify a different "name".'
);
}
function itCanHaveDescription() {
@ -59,11 +66,13 @@ class SegmentCest {
}
function itHasToBeValid() {
expect($this->saved)->equals(true);
$empty_model = Segment::create();
expect($empty_model->save())->notEquals(true);
$validations = $empty_model->getValidationErrors();
expect(count($validations))->equals(1);
$invalid_segment = Segment::create();
$result = $invalid_segment->save();
$errors = $result->getErrors();
expect(is_array($errors))->true();
expect($errors[0])->equals('You need to specify a name.');
}
function itHasACreatedAtOnCreation() {
@ -101,10 +110,10 @@ class SegmentCest {
function itCanCreateOrUpdate() {
$is_created = Segment::createOrUpdate(array(
'name' => 'new list'
));
expect($is_created)->notEquals(false);
expect($is_created->getValidationErrors())->isEmpty();
'name' => 'new list'
));
expect($is_created->id() > 0)->true();
expect($is_created->getErrors())->false();
$segment = Segment::where('name', 'new list')
->findOne();
@ -121,9 +130,9 @@ class SegmentCest {
}
function itCanHaveManySubscribers() {
foreach ($this->subscribersData as $subscriberData) {
foreach($this->subscribers_data as $subscriber_data) {
$subscriber = Subscriber::create();
$subscriber->hydrate($subscriberData);
$subscriber->hydrate($subscriber_data);
$subscriber->save();
$association = SubscriberSegment::create();
$association->subscriber_id = $subscriber->id;
@ -138,9 +147,9 @@ class SegmentCest {
}
function itCanHaveManyNewsletters() {
foreach ($this->newslettersData as $newsletterData) {
foreach($this->newsletters_data as $newsletter_data) {
$newsletter = Newsletter::create();
$newsletter->hydrate($newsletterData);
$newsletter->hydrate($newsletter_data);
$newsletter->save();
$association = NewsletterSegment::create();
$association->newsletter_id = $newsletter->id;
@ -155,9 +164,9 @@ class SegmentCest {
}
function itCanGetSegmentsWithSubscriberCount() {
foreach ($this->subscribersData as $subscriberData) {
foreach($this->subscribers_data as $subscriber_data) {
$subscriber = Subscriber::create();
$subscriber->hydrate($subscriberData);
$subscriber->hydrate($subscriber_data);
$subscriber->save();
$association = SubscriberSegment::create();
$association->subscriber_id = $subscriber->id;
@ -169,9 +178,9 @@ class SegmentCest {
}
function itCanGetSegmentsForExport() {
foreach ($this->subscribersData as $index => $subscriberData) {
foreach($this->subscribers_data as $index => $subscriber_data) {
$subscriber = Subscriber::create();
$subscriber->hydrate($subscriberData);
$subscriber->hydrate($subscriber_data);
$subscriber->save();
if(!$index) {
$association = SubscriberSegment::create();

View File

@ -2,61 +2,52 @@
use MailPoet\Models\Setting;
class SettingCest {
function _before() {
$this->before_time = time();
$this->data = array(
'name' => 'sending_method',
'value' => 'smtp'
);
$setting = Setting::create();
$setting->hydrate($this->data);
$this->result = $setting->save();
}
function itCanBeCreated() {
expect($this->result)->equals(true);
}
function itHasToBeValid() {
expect($this->result)->equals(true);
$empty_model = Setting::create();
expect($empty_model->save())->notEquals(true);
$validations = $empty_model->getValidationErrors();
expect(count($validations))->equals(2);
$invalid_setting = Setting::createOrUpdate();
$errors = $invalid_setting->getErrors();
expect($errors)->notEmpty();
expect($errors[0])->equals('You need to specify a name.');
}
function itHasACreatedAtOnCreation() {
$setting = Setting::where('name', $this->data['name'])
->findOne();
$time_difference = strtotime($setting->created_at) >= $this->before_time;
expect($time_difference)->equals(true);
function itCanGetAllSettings() {
Setting::setValue('key_1', 'value_1');
Setting::setValue('key_2', 'value_2');
Setting::setValue('key_3', array(
'subkey_1' => 'subvalue_1',
'subkey_2' => 'subvalue_2'
));
$settings = Setting::getAll();
expect(array_keys($settings))->count(3);
expect($settings['key_1'])->equals('value_1');
expect($settings['key_2'])->equals('value_2');
expect($settings['key_3'])->equals(array(
'subkey_1' => 'subvalue_1',
'subkey_2' => 'subvalue_2'
));
}
function itHasAnUpdatedAtOnCreation() {
$setting = Setting::where('name', $this->data['name'])
->findOne();
$time_difference = strtotime($setting->updated_at) >= $this->before_time;
expect($time_difference)->equals(true);
}
function itReturnsDefaultValueIfNotSet() {
// try to get an "unknown" key
$setting = Setting::getValue('unknown_key', 'default_value');
expect($setting)->equals('default_value');
function itKeepsTheCreatedAtOnUpdate() {
$setting = Setting::where('name', $this->data['name'])
->findOne();
$old_created_at = $setting->created_at;
$setting->value = 'http_api';
$setting->save();
expect($old_created_at)->equals($setting->created_at);
}
// setting a "known" key
$setting = Setting::setValue('known_key', 'actual_value');
expect($setting)->equals(true);
function itUpdatesTheUpdatedAtOnUpdate() {
$setting = Setting::where('name', $this->data['name'])
->findOne();
$update_time = time();
$setting->value = 'http_api';
$setting->save();
$time_difference = strtotime($setting->updated_at) >= $update_time;
expect($time_difference)->equals(true);
// try to get a "known" key
$setting = Setting::getValue('known_key', 'default_value');
expect($setting)->equals('actual_value');
// try to get an "unknown" subkey of a "known" key
$setting = Setting::getValue('known_key.unknown_subkey', 'default_value');
expect($setting)->equals('default_value');
// try to get an "unknown" subkey of an "unknown" key
$setting = Setting::getValue('unknown_key.unknown_subkey', 'default_value');
expect($setting)->equals('default_value');
}
function itCanCreateOrUpdate() {
@ -65,18 +56,20 @@ class SettingCest {
'value' => 'data'
);
$result = Setting::createOrUpdate($data);
expect($result)->equals(true);
$record = Setting::where('name', $data['name'])
->find_one();
expect($record->value)->equals($data['value']);
$created_setting = Setting::createOrUpdate($data);
expect($created_setting->id() > 0)->true();
expect($created_setting->getErrors())->false();
$setting = Setting::where('name', $data['name'])->findOne();
expect($setting->value)->equals($data['value']);
$data['value'] = 'new data';
$result = Setting::createOrUpdate($data);
expect($result)->equals(true);
$record = Setting::where('name', $data['name'])
->find_one();
expect($record->value)->equals('new data');
$updated_setting = Setting::createOrUpdate($data);
expect($updated_setting->id() > 0)->true();
expect($updated_setting->getErrors())->false();
$setting = Setting::where('name', $data['name'])->findOne();
expect($setting->value)->equals('new data');
}
function itCanGetAndSetValue() {
@ -105,7 +98,6 @@ class SettingCest {
}
function _after() {
ORM::forTable(Setting::$_table)
->deleteMany();
Setting::deleteMany();
}
}

View File

@ -20,7 +20,8 @@ class SubscriberCest {
}
function itCanBeCreated() {
expect($this->saved)->true();
expect($this->saved->id() > 0)->true();
expect($this->saved->getErrors())->false();
}
function itHasFirstName() {
@ -62,14 +63,13 @@ class SubscriberCest {
}
function itCanChangeStatus() {
$subscriber = Subscriber::where('email', $this->data['email'])
->findOne();
$subscriber = Subscriber::where('email', $this->data['email'])->findOne();
$subscriber->status = 'subscribed';
expect($subscriber->save())->equals(true);
$subscriber_updated = Subscriber::where(
'email',
$this->data['email']
)
$subscriber->save();
expect($subscriber->id() > 0)->true();
expect($subscriber->getErrors())->false();
$subscriber_updated = Subscriber::where('email', $this->data['email'])
->findOne();
expect($subscriber_updated->status)->equals('subscribed');
}
@ -89,91 +89,78 @@ class SubscriberCest {
function itHasGroupFilter() {
$subscribers = Subscriber::filter('groupBy', 'unconfirmed')
->findMany();
foreach ($subscribers as $subscriber) {
foreach($subscribers as $subscriber) {
expect($subscriber->status)->equals('unconfirmed');
}
$subscribers = Subscriber::filter('groupBy', 'subscribed')
->findMany();
foreach ($subscribers as $subscriber) {
foreach($subscribers as $subscriber) {
expect($subscriber->status)->equals('subscribed');
}
$subscribers = Subscriber::filter('groupBy', 'unsubscribed')
->findMany();
foreach ($subscribers as $subscriber) {
foreach($subscribers as $subscriber) {
expect($subscriber->status)->equals('unsubscribed');
}
}
function itCanHaveSegment() {
$segmentData = array(
$segment = Segment::createOrUpdate(array(
'name' => 'some name'
);
$segment = Segment::create();
$segment->hydrate($segmentData);
$segment->save();
));
expect($segment->getErrors())->false();
$association = SubscriberSegment::create();
$association->subscriber_id = $this->subscriber->id;
$association->segment_id = $segment->id;
$association->save();
$subscriber = Subscriber::findOne($this->subscriber->id);
$subscriberSegment = $subscriber->segments()
->findOne();
expect($subscriberSegment->id)->equals($segment->id);
$subscriber_segment = $subscriber->segments()->findOne();
expect($subscriber_segment->id)->equals($segment->id);
}
function itCanHaveCustomFields() {
$customFieldData = array(
$custom_field = CustomField::createOrUpdate(array(
'name' => 'DOB',
'type' => 'date',
);
$customField = CustomField::create();
$customField->hydrate($customFieldData);
$customField->save();
));
$association = SubscriberCustomField::create();
$association->subscriber_id = $this->subscriber->id;
$association->custom_field_id = $customField->id;
$association->custom_field_id = $custom_field->id;
$association->value = '12/12/2012';
$association->save();
$subscriber = Subscriber::filter('filterWithCustomFields')
->findOne($this->subscriber->id);
expect($subscriber->DOB)->equals($association->value);
}
function itCanFilterCustomFields() {
$customFieldData = array(
array(
'name' => 'City',
'type' => 'text',
),
array(
'name' => 'Country',
'type' => 'text',
)
);
foreach ($customFieldData as $data) {
$customField = CustomField::create();
$customField->hydrate($data);
$customField->save();
$createdCustomFields[] = $customField->asArray();
}
$subscriberCustomFieldData = array(
array(
'subscriber_id' => $this->subscriber->id,
'custom_field_id' => $createdCustomFields[0]['id'],
'value' => 'Paris'
),
array(
'subscriber_id' => $this->subscriber->id,
'custom_field_id' => $createdCustomFields[1]['id'],
'value' => 'France'
)
);
foreach ($subscriberCustomFieldData as $data) {
$association = SubscriberCustomField::create();
$association->hydrate($data);
$association->save();
$createdAssociations[] = $association->asArray();
}
$cf_city = CustomField::createOrUpdate(array(
'name' => 'City',
'type' => 'text'
));
SubscriberCustomField::createOrUpdate(array(
'subscriber_id' => $this->subscriber->id,
'custom_field_id' => $cf_city->id,
'value' => 'Paris'
));
$cf_country = CustomField::createOrUpdate(array(
'name' => 'Country',
'type' => 'text'
));
SubscriberCustomField::createOrUpdate(array(
'subscriber_id' => $this->subscriber->id,
'custom_field_id' => $cf_country->id,
'value' => 'France'
));
$subscriber = Subscriber::filter('filterWithCustomFields')
->filter('filterSearchCustomFields', array(
array(
@ -196,6 +183,7 @@ class SubscriberCest {
))
->findArray();
expect(empty($subscriber))->false();
$subscriber = Subscriber::filter('filterWithCustomFields')
->filter('filterSearchCustomFields', array(
array(
@ -209,6 +197,7 @@ class SubscriberCest {
), 'OR')
->findArray();
expect(empty($subscriber))->false();
$subscriber = Subscriber::filter('filterWithCustomFields')
->filter('filterSearchCustomFields', array(
array(
@ -218,6 +207,7 @@ class SubscriberCest {
), 'AND', 'LIKE')
->findArray();
expect(empty($subscriber))->false();
$subscriber = Subscriber::filter('filterWithCustomFields')
->filter('filterSearchCustomFields', array(
array(
@ -227,6 +217,7 @@ class SubscriberCest {
))
->findArray();
expect(empty($subscriber))->true();
$subscriber = Subscriber::filter('filterWithCustomFields')
->filter('filterSearchCustomFields', array(
array(
@ -240,6 +231,7 @@ class SubscriberCest {
))
->findArray();
expect(empty($subscriber))->true();
$subscriber = Subscriber::filter('filterWithCustomFields')
->filter('filterSearchCustomFields', array(
array(
@ -253,6 +245,7 @@ class SubscriberCest {
), 'OR')
->findArray();
expect(empty($subscriber))->true();
$subscriber = Subscriber::filter('filterWithCustomFields')
->filter('filterSearchCustomFields', array(
array(
@ -271,8 +264,8 @@ class SubscriberCest {
'last_name' => 'Doe'
);
$result = Subscriber::createOrUpdate($data);
expect($result)->notEquals(false);
expect($result->getValidationErrors())->isEmpty();
expect($result->id() > 0)->true();
expect($result->getErrors())->false();
$record = Subscriber::where('email', $data['email'])
->findOne();

View File

@ -20,7 +20,9 @@ class SubscriberCustomFieldCest {
function itCanBeCreated() {
$subscriberCustomField = SubscriberCustomField::create();
$subscriberCustomField->hydrate($this->data[0]);
expect($subscriberCustomField->save())->true();
$subscriberCustomField->save();
expect($subscriberCustomField->id() > 0)->true();
expect($subscriberCustomField->getErrors())->false();
}
function itCanCreateOrUpdateMultipleRecords() {

View File

@ -23,6 +23,7 @@ class NewsletterRendererCest {
$this->DOM_parser = new \pQuery();
}
function itRendersCompleteNewsletter() {
$template = $this->renderer->render();
expect(isset($template['html']))->true();
@ -125,17 +126,33 @@ class NewsletterRendererCest {
expect($DOM('tr > td > img', 0)->attr('style'))->notEmpty();
}
function itAdjustImageSizeBasedOnColumnWidth() {
$newsletter = json_decode($this->newsletter['body'], true);
$template = $newsletter['content']['blocks'][0]['blocks'][0]['blocks'][1];
$template['width'] = '800px';
$DOM = $this->DOM_parser->parseStr(Image::render($template, $columnCount = 2));
// 800px resized to 330px (2-column layout) and 40px padding applied
expect($DOM('tr > td > img', 0)->attr('width'))->equals(290);
$template['width'] = '280px';
$DOM = $this->DOM_parser->parseStr(Image::render($template, $columnCount = 2));
// 280px image should not be resized and padding should not be applied
expect($DOM('tr > td > img', 0)->attr('width'))->equals(280);
function itAdjustsImageDimensions() {
// image gets scaled down when image width > column width
$image = array(
'width' => 800,
'height' => 600,
'fullWidth' => true
);
$new_image_dimensions = Image::adjustImageDimensions($image, $columnCount = 1);
expect($new_image_dimensions['width'])->equals(660);
expect($new_image_dimensions['height'])->equals(495);
// nothing happens when image width = column width
$image['width'] = 661;
$new_image_dimensions = Image::adjustImageDimensions($image, $columnCount = 1);
expect($new_image_dimensions['width'])->equals(660);
// nothing happens when image width < column width
$image['width'] = 659;
$new_image_dimensions = Image::adjustImageDimensions($image, $columnCount = 1);
expect($new_image_dimensions['width'])->equals(659);
// image is reduced by 40px when it's width > padded column width
$image['width'] = 621;
$image['fullWidth'] = false;
$new_image_dimensions = Image::adjustImageDimensions($image, $columnCount = 1);
expect($new_image_dimensions['width'])->equals(620);
// nothing happens when image with < padded column width
$image['width'] = 619;
$new_image_dimensions = Image::adjustImageDimensions($image, $columnCount = 1);
expect($new_image_dimensions['width'])->equals(619);
}
function itRendersText() {

View File

@ -44,7 +44,7 @@
"link": "",
"src": "http://test.mailpoet.net/wp-content/uploads/2015/12/660.png",
"alt": "660",
"padded": true,
"fullWidth": false,
"width": "660px",
"height": "250px",
"styles": {
@ -199,7 +199,7 @@
"link": "http://example.org",
"src": "http://test.mailpoet.net/wp-content/uploads/2015/12/660.png",
"alt": "660",
"padded": false,
"fullWidth": true,
"width": "660px",
"height": "250px",
"styles": {
@ -235,7 +235,7 @@
"link": "",
"src": "http://test.mailpoet.net/wp-content/uploads/2015/12/330x125.png",
"alt": "330x125",
"padded": true,
"fullWidth": false,
"width": "330px",
"height": "125px",
"styles": {
@ -390,7 +390,7 @@
"link": "http://example.org",
"src": "http://test.mailpoet.net/wp-content/uploads/2015/12/330x125.png",
"alt": "330x125",
"padded": false,
"fullWidth": true,
"width": "330px",
"height": "125px",
"styles": {
@ -415,7 +415,7 @@
"link": "",
"src": "http://test.mailpoet.net/wp-content/uploads/2015/12/330x125-copy-150x57.png",
"alt": "330x125 copy",
"padded": true,
"fullWidth": false,
"width": "150px",
"height": "57px",
"styles": {
@ -561,7 +561,7 @@
"link": "http://example.org",
"src": "http://test.mailpoet.net/wp-content/uploads/2015/12/330x125.png",
"alt": "330x125",
"padded": false,
"fullWidth": true,
"width": "330px",
"height": "125px",
"styles": {
@ -606,7 +606,7 @@
"link": "",
"src": "http://test.mailpoet.net/wp-content/uploads/2015/12/220x83-copy.png",
"alt": "220x83 copy",
"padded": true,
"fullWidth": false,
"width": "100px",
"height": "38px",
"styles": {
@ -761,7 +761,7 @@
"link": "",
"src": "http://test.mailpoet.net/wp-content/uploads/2015/12/220x83.png",
"alt": "220x83",
"padded": false,
"fullWidth": true,
"width": "220px",
"height": "83px",
"styles": {
@ -786,7 +786,7 @@
"link": "",
"src": "http://test.mailpoet.net/wp-content/uploads/2015/12/220x83.png",
"alt": "220x83",
"padded": true,
"fullWidth": false,
"width": "220px",
"height": "83px",
"styles": {
@ -941,7 +941,7 @@
"link": "http://example.org",
"src": "http://test.mailpoet.net/wp-content/uploads/2015/12/220x83.png",
"alt": "220x83",
"padded": false,
"fullWidth": true,
"width": "220px",
"height": "83px",
"styles": {
@ -966,7 +966,7 @@
"link": "",
"src": "http://test.mailpoet.net/wp-content/uploads/2015/12/220x83.png",
"alt": "220x83",
"padded": true,
"fullWidth": false,
"width": "220px",
"height": "83px",
"styles": {
@ -1121,7 +1121,7 @@
"link": "http://example.org",
"src": "http://test.mailpoet.net/wp-content/uploads/2015/12/220x83.png",
"alt": "220x83",
"padded": false,
"fullWidth": true,
"width": "220px",
"height": "83px",
"styles": {
@ -1215,4 +1215,4 @@
"backgroundColor": "#333333"
}
}
}
}

View File

@ -69,13 +69,17 @@ class CustomFieldsCest {
function itCanDeleteACustomField() {
$custom_field = CustomField::where('type', 'date')->findOne();
$custom_field_id = $custom_field->id();
$router = new CustomFields();
$response = $router->delete($custom_field->id());
$response = $router->delete($custom_field_id);
expect($response['result'])->true();
$custom_field = CustomField::where('type', 'date')->findOne();
expect($custom_field)->false();
$response = $router->delete($custom_field_id);
expect($response['result'])->false();
}
function itCanSaveACustomField() {
@ -120,6 +124,6 @@ class CustomFieldsCest {
}
function _after() {
ORM::forTable(CustomField::$_table)->deleteMany();
CustomField::deleteMany();
}
}

View File

@ -0,0 +1,194 @@
<?php
use \MailPoet\Router\Forms;
use \MailPoet\Models\Form;
use \MailPoet\Models\Segment;
class FormsCest {
function _before() {
Form::createOrUpdate(array('name' => 'Form 1'));
Form::createOrUpdate(array('name' => 'Form 2'));
Form::createOrUpdate(array('name' => 'Form 3'));
Segment::createOrUpdate(array('name' => 'Segment 1'));
Segment::createOrUpdate(array('name' => 'Segment 2'));
}
function itCanGetAForm() {
$form = Form::where('name', 'Form 1')->findOne();
$router = new Forms();
$response = $router->get(/* missing id */);
expect($response)->false();
$response = $router->get('not_an_id');
expect($response)->false();
$response = $router->get($form->id);
expect($response['id'])->equals($form->id);
expect($response['name'])->equals($form->name);
}
function itCanGetListingData() {
$router = new Forms();
$response = $router->listing();
expect($response)->hasKey('filters');
expect($response)->hasKey('groups');
expect($response['count'])->equals(3);
expect($response['items'])->count(3);
expect($response['items'][0]['name'])->equals('Form 1');
expect($response['items'][1]['name'])->equals('Form 2');
expect($response['items'][2]['name'])->equals('Form 3');
}
function itCanCreateANewForm() {
$router = new Forms();
$response = $router->create();
expect($response['result'])->true();
expect($response['form_id'] > 0)->true();
expect($response)->hasntKey('errors');
$created_form = Form::findOne($response['form_id']);
expect($created_form->name)->equals('New form');
}
function itCanSaveAForm() {
$form_data = array(
'name' => 'My first form'
);
$router = new Forms();
$response = $router->save(/* missing data */);
expect($response['result'])->false();
expect($response['errors'][0])->equals('You need to specify a name.');
$response = $router->save($form_data);
expect($response['result'])->true();
expect($response['form_id'] > 0)->true();
$form = Form::where('name', 'My first form')->findOne();
expect($form->id)->equals($response['form_id']);
expect($form->name)->equals('My first form');
}
function itCanPreviewAForm() {
$router = new Forms();
$response = $router->create();
expect($response['result'])->true();
expect($response['form_id'] > 0)->true();
$form = Form::findOne($response['form_id']);
$response = $router->previewEditor($form->asArray());
expect($response['html'])->notEmpty();
expect($response['css'])->notEmpty();
}
function itCanExportAForm() {
$router = new Forms();
$response = $router->create();
expect($response['result'])->true();
expect($response['form_id'] > 0)->true();
$response = $router->exportsEditor($response['form_id']);
expect($response['html'])->notEmpty();
expect($response['php'])->notEmpty();
expect($response['iframe'])->notEmpty();
expect($response['shortcode'])->notEmpty();
}
function itCanSaveFormEditor() {
$router = new Forms();
$response = $router->create();
expect($response['result'])->true();
expect($response['form_id'] > 0)->true();
$form = Form::findOne($response['form_id'])->asArray();
$form['name'] = 'Updated form';
$response = $router->saveEditor($form);
expect($response['result'])->true();
expect($response['is_widget'])->false();
$saved_form = Form::findOne($form['id']);
expect($saved_form->name)->equals('Updated form');
}
function itCanRestoreAForm() {
$form = Form::where('name', 'Form 1')->findOne();
$form->trash();
$trashed_form = Form::findOne($form->id);
expect($trashed_form->deleted_at)->notNull();
$router = new Forms();
$response = $router->restore($form->id);
expect($response)->true();
$restored_form = Form::findOne($form->id);
expect($restored_form->deleted_at)->null();
}
function itCanTrashAForm() {
$form = Form::where('name', 'Form 1')->findOne();
expect($form->deleted_at)->null();
$router = new Forms();
$response = $router->trash($form->id);
expect($response)->true();
$trashed_form = Form::findOne($form->id);
expect($trashed_form->deleted_at)->notNull();
}
function itCanDeleteAForm() {
$form = Form::where('name', 'Form 2')->findOne();
expect($form->deleted_at)->null();
$router = new Forms();
$response = $router->delete($form->id);
expect($response)->equals(1);
$deleted_form = Form::findOne($form->id);
expect($deleted_form)->false();
}
function itCanDuplicateAForm() {
$form = Form::where('name', 'Form 3')->findOne();
$router = new Forms();
$response = $router->duplicate($form->id);
expect($response['name'])->equals('Copy of '.$form->name);
$duplicated_form = Form::findOne($response['id']);
expect($duplicated_form->name)->equals('Copy of '.$form->name);
}
function itCanBulkDeleteForms() {
expect(Form::count())->equals(3);
$forms = Form::findMany();
foreach($forms as $form) {
$form->trash();
}
$router = new Forms();
$response = $router->bulkAction(array(
'action' => 'delete',
'listing' => array('group' => 'trash')
));
expect($response)->equals(3);
$response = $router->bulkAction(array(
'action' => 'delete',
'listing' => array('group' => 'trash')
));
expect($response)->equals(0);
}
function _after() {
Form::deleteMany();
Segment::deleteMany();
}
}

View File

@ -0,0 +1,82 @@
<?php
use \MailPoet\Router\NewsletterTemplates;
use \MailPoet\Models\NewsletterTemplate;
class NewsletterTemplatesCest {
function _before() {
NewsletterTemplate::createOrUpdate(array(
'name' => 'Template #1',
'description' => 'My First Template',
'body' => '{"key1": "value1"}'
));
NewsletterTemplate::createOrUpdate(array(
'name' => 'Template #2',
'description' => 'My Second Template',
'body' => '{"key2": "value2"}'
));
}
function itCanGetANewsletterTemplate() {
$template = NewsletterTemplate::where('name', 'Template #1')->findOne();
$router = new NewsletterTemplates();
$response = $router->get(/* missing id */);
expect($response)->false();
$response = $router->get('not_an_id');
expect($response)->false();
$response = $router->get($template->id());
expect($response['name'])->equals('Template #1');
expect($response['body']['key1'])->equals('value1');
}
function itCanGetAllNewsletterTemplates() {
$templates = NewsletterTemplate::findArray();
$router = new NewsletterTemplates();
$response = $router->getAll();
expect($response)->count(2);
expect($response[0]['name'])->equals('Template #1');
expect($response[0]['body']['key1'])->equals('value1');
expect($response[1]['name'])->equals('Template #2');
expect($response[1]['body']['key2'])->equals('value2');
}
function itCanSaveANewsletterTemplate() {
$template_data = array(
'name' => 'Template #3',
'description' => 'My Third Template',
'body' => '{"key3": "value3"}'
);
$router = new NewsletterTemplates();
$response = $router->save($template_data);
expect($response)->true();
$template = NewsletterTemplate::where('name', 'Template #3')->findOne();
expect($template->name)->equals('Template #3');
expect($template->description)->equals('My Third Template');
expect($template->body)->equals('{"key3": "value3"}');
}
function itCanDeleteANewsletterTemplate() {
$template = NewsletterTemplate::where('name', 'Template #2')->findOne();
expect($template->deleted_at)->null();
$router = new NewsletterTemplates();
$response = $router->delete($template->id());
expect($response)->true();
$deleted_template = NewsletterTemplate::findOne($template->id());
expect($deleted_template)->false();
}
function _after() {
NewsletterTemplate::deleteMany();
}
}

View File

@ -0,0 +1,198 @@
<?php
use \MailPoet\Router\Newsletters;
use \MailPoet\Models\Newsletter;
use \MailPoet\Models\NewsletterSegment;
use \MailPoet\Models\NewsletterTemplate;
use \MailPoet\Models\Segment;
class NewslettersCest {
function _before() {
$this->newsletter = Newsletter::createOrUpdate(array(
'subject' => 'My Standard Newsletter',
'type' => 'standard'
));
$this->post_notification = Newsletter::createOrUpdate(array(
'subject' => 'My Post Notification',
'type' => 'notification'
));
}
function itCanGetANewsletter() {
$router = new Newsletters();
$response = $router->get($this->newsletter->id());
expect($response['id'])->equals($this->newsletter->id());
$response = $router->get('not_an_id');
expect($response)->false();
$response = $router->get(/* missing argument */);
expect($response)->false();
}
function itCanSaveANewNewsletter() {
$valid_data = array(
'subject' => 'My First Newsletter',
'type' => 'standard'
);
$router = new Newsletters();
$response = $router->save($valid_data);
expect($response['result'])->true();
expect($response)->hasntKey('errors');
$invalid_data = array(
'subject' => 'Missing newsletter type'
);
$response = $router->save($invalid_data);
expect($response['result'])->false();
expect($response['errors'][0])->equals('You need to specify a type.');
}
function itCanSaveAnExistingNewsletter() {
$router = new Newsletters();
$newsletter_data = $this->newsletter->asArray();
$newsletter_data['subject'] = 'My Updated Newsletter';
$response = $router->save($newsletter_data);
expect($response['result'])->true();
$updated_newsletter = Newsletter::findOne($this->newsletter->id());
expect($updated_newsletter->subject)->equals('My Updated Newsletter');
}
function itCanRestoreANewsletter() {
$this->newsletter->trash();
expect($this->newsletter->deleted_at)->notNull();
$router = new Newsletters();
$router->restore($this->newsletter->id());
$restored_subscriber = Newsletter::findOne($this->newsletter->id());
expect($restored_subscriber->deleted_at)->null();
}
function itCanTrashANewsletter() {
$router = new Newsletters();
$response = $router->trash($this->newsletter->id());
expect($response)->true();
$trashed_subscriber = Newsletter::findOne($this->newsletter->id());
expect($trashed_subscriber->deleted_at)->notNull();
}
function itCanDeleteANewsletter() {
$router = new Newsletters();
$response = $router->delete($this->newsletter->id());
expect($response)->equals(1);
expect(Newsletter::findOne($this->newsletter->id()))->false();
}
function itCanDuplicateANewsletter() {
$router = new Newsletters();
$response = $router->duplicate($this->newsletter->id());
expect($response['subject'])->equals('Copy of My Standard Newsletter');
expect($response['type'])->equals('standard');
expect($response['body'])->equals($this->newsletter->body);
$response = $router->duplicate($this->post_notification->id());
expect($response['subject'])->equals('Copy of My Post Notification');
expect($response['type'])->equals('notification');
expect($response['body'])->equals($this->post_notification->body);
}
function itCanCreateANewsletter() {
$data = array(
'subject' => 'My New Newsletter',
'type' => 'standard'
);
$router = new Newsletters();
$response = $router->create($data);
expect($response['result'])->true();
expect($response['newsletter']['id'] > 0)->true();
expect($response['newsletter']['subject'])->equals('My New Newsletter');
expect($response['newsletter']['type'])->equals('standard');
expect($response['newsletter']['body'])->equals(array());
expect($response)->hasntKey('errors');
$response = $router->create();
expect($response['result'])->false();
expect($response['errors'][0])->equals('You need to specify a type.');
}
function itCanGetListingData() {
$segment_1 = Segment::createOrUpdate(array('name' => 'Segment 1'));
$segment_2 = Segment::createOrUpdate(array('name' => 'Segment 2'));
$newsletter_segment = NewsletterSegment::create();
$newsletter_segment->hydrate(array(
'newsletter_id' => $this->newsletter->id(),
'segment_id' => $segment_1->id()
));
$newsletter_segment->save();
$newsletter_segment = NewsletterSegment::create();
$newsletter_segment->hydrate(array(
'newsletter_id' => $this->newsletter->id(),
'segment_id' => $segment_2->id()
));
$newsletter_segment->save();
$newsletter_segment = NewsletterSegment::create();
$newsletter_segment->hydrate(array(
'newsletter_id' => $this->post_notification->id(),
'segment_id' => $segment_2->id()
));
$newsletter_segment->save();
$router = new Newsletters();
$response = $router->listing();
expect($response)->hasKey('filters');
expect($response)->hasKey('groups');
expect($response['count'])->equals(2);
expect($response['items'])->count(2);
expect($response['items'][0]['subject'])->equals('My Standard Newsletter');
expect($response['items'][1]['subject'])->equals('My Post Notification');
expect($response['items'][0]['segments'])->equals(array(
$segment_1->id(),
$segment_2->id()
));
expect($response['items'][1]['segments'])->equals(array(
$segment_2->id()
));
}
function itCanBulkDeleteNewsletters() {
expect(Newsletter::count())->equals(2);
$newsletters = Newsletter::findMany();
foreach($newsletters as $newsletter) {
$newsletter->trash();
}
$router = new Newsletters();
$response = $router->bulkAction(array(
'action' => 'delete',
'listing' => array('group' => 'trash')
));
expect($response)->equals(2);
$response = $router->bulkAction(array(
'action' => 'delete',
'listing' => array('group' => 'trash')
));
expect($response)->equals(0);
}
function _after() {
Newsletter::deleteMany();
Segment::deleteMany();
}
}

Some files were not shown because too many files have changed in this diff Show More