Compare commits
51 Commits
Author | SHA1 | Date | |
---|---|---|---|
c0ba218949 | |||
ee85139089 | |||
b4f83fe1bd | |||
bd83001ef5 | |||
fb3a9f485f | |||
fd44776ae9 | |||
6dbe338b01 | |||
1f06a7dd0b | |||
37c218f782 | |||
25016f2a8d | |||
792744a270 | |||
c5fbfca132 | |||
c2fde308cb | |||
533d9b0d38 | |||
2035b802e3 | |||
a5e66ec6a0 | |||
beb939df9e | |||
44e342c692 | |||
3a417d460f | |||
1950d6661f | |||
da6e154642 | |||
acebf669a7 | |||
4a2bbe3f88 | |||
9b011c0281 | |||
bf58d8a22d | |||
72d1eb79a6 | |||
bb4893c0a0 | |||
9929cf0aee | |||
83967e84ba | |||
9621cb3ca9 | |||
a413f666fe | |||
d1e2c6c074 | |||
3b6a9f7a6e | |||
d2e5fb89c2 | |||
97d1e95037 | |||
48fbce22e7 | |||
916fe76795 | |||
e10310fb5c | |||
367afcf814 | |||
67fa9e0993 | |||
d7553a5f27 | |||
8c847825fa | |||
d21d9b99b0 | |||
8461c13532 | |||
3b7ffe9ba7 | |||
1724fa22c1 | |||
01089d7a72 | |||
717ebfd20c | |||
98fb838169 | |||
62a164e4c6 | |||
9ab8b1f0c5 |
@ -47,6 +47,15 @@ class RoboFile extends \Robo\Tasks {
|
||||
->run();
|
||||
}
|
||||
|
||||
function watchCss() {
|
||||
$css_files = $this->rsearch('assets/css/src/', array('styl'));
|
||||
$this->taskWatch()
|
||||
->monitor($css_files, function() {
|
||||
$this->compileCss();
|
||||
})
|
||||
->run();
|
||||
}
|
||||
|
||||
function watchJs() {
|
||||
$this->_exec('./node_modules/webpack/bin/webpack.js --watch');
|
||||
}
|
||||
|
@ -13,4 +13,5 @@
|
||||
@require 'breadcrumb'
|
||||
@require 'form'
|
||||
|
||||
@require 'settings'
|
||||
@require 'settings'
|
||||
@require 'progress_bar'
|
@ -38,18 +38,21 @@
|
||||
right: 0
|
||||
bottom: 0
|
||||
background-color: rgba(255, 255, 255, 0.0)
|
||||
opacity: 0
|
||||
transition: all 200ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
||||
|
||||
&:hover
|
||||
background-color: rgba(255, 255, 255, 0.7)
|
||||
opacity: 1
|
||||
|
||||
&::after
|
||||
content: " "
|
||||
position: absolute
|
||||
top: 0
|
||||
left: 0
|
||||
bottom: 0
|
||||
right: 0
|
||||
background: url(../img/preview_magnifying_glass.svg) no-repeat center center
|
||||
&::after
|
||||
content: " "
|
||||
position: absolute
|
||||
top: 0
|
||||
left: 0
|
||||
bottom: 0
|
||||
right: 0
|
||||
background: url(../img/preview_magnifying_glass.svg) no-repeat center center
|
||||
|
||||
.mailpoet_boxes .mailpoet_description
|
||||
float:left
|
||||
|
@ -26,3 +26,25 @@ textarea.regular-text
|
||||
@media screen and (max-width: 782px)
|
||||
.select2-container
|
||||
width: 100% !important
|
||||
|
||||
// progress bars
|
||||
progress-border-radius = 5px
|
||||
progress-background = #efefef
|
||||
progress-foreground = #69b1e9
|
||||
|
||||
progress
|
||||
background-color: progress-background;
|
||||
height: 2em
|
||||
border: 0
|
||||
width: 100%
|
||||
|
||||
progress::-webkit-progress-bar
|
||||
background-color: progress-background;
|
||||
|
||||
progress::-webkit-progress-value
|
||||
background-color: progress-foreground
|
||||
border-radius: progress-border-radius
|
||||
|
||||
progress::-moz-progress-bar
|
||||
background-color: progress-foreground
|
||||
border-radius: progress-border-radius
|
||||
|
@ -76,13 +76,24 @@ $layer-selector-width = 30px
|
||||
display: inline-block
|
||||
padding: 2px
|
||||
vertical-align: top
|
||||
animation-background-color()
|
||||
|
||||
.mailpoet_tool
|
||||
padding: 0
|
||||
|
||||
.mailpoet_delete_block_activate
|
||||
max-width: 100%
|
||||
display: inline-block
|
||||
opacity: 1
|
||||
animation-fade-in-and-scale-horizontally()
|
||||
|
||||
.mailpoet_delete_block_confirm,
|
||||
.mailpoet_delete_block_cancel
|
||||
display: none
|
||||
max-width: 0
|
||||
opacity: 0
|
||||
overflow: hidden
|
||||
display: inline-block
|
||||
animation-fade-in-and-scale-horizontally()
|
||||
|
||||
.mailpoet_delete_block_activated
|
||||
width: auto
|
||||
@ -93,11 +104,14 @@ $layer-selector-width = 30px
|
||||
height: auto
|
||||
|
||||
.mailpoet_delete_block_activate
|
||||
display: none
|
||||
overflow: hidden
|
||||
max-width: 0
|
||||
opacity: 0
|
||||
|
||||
.mailpoet_delete_block_confirm,
|
||||
.mailpoet_delete_block_cancel
|
||||
display: inline-block
|
||||
max-width: 100%
|
||||
opacity: 1
|
||||
|
||||
.mailpoet_delete_block_confirm
|
||||
color: $warning-text-color
|
||||
|
@ -52,6 +52,7 @@ $draggable-widget-z-index = 2
|
||||
padding: 0
|
||||
margin: 0
|
||||
z-index: $draggable-widget-z-index
|
||||
animation-fade-in-and-scale-up()
|
||||
|
||||
.mailpoet_widget_icon
|
||||
padding: 0
|
||||
|
@ -32,7 +32,7 @@ $widget-icon-width = 30px
|
||||
|
||||
.mailpoet_region_content
|
||||
max-height: 2000px
|
||||
transition: max-height 0.2s ease
|
||||
transition: max-height 300ms ease
|
||||
padding: 0 20px
|
||||
margin-top: 12px
|
||||
|
||||
|
@ -18,3 +18,6 @@
|
||||
|
||||
& > .mailpoet_block
|
||||
width: 100%
|
||||
|
||||
.mailpoet_automated_latest_content_display_options
|
||||
animation-slide-open-downwards()
|
||||
|
@ -30,3 +30,8 @@ $block-hover-highlight-color = $primary-active-color
|
||||
|
||||
.mailpoet_content
|
||||
position: relative
|
||||
|
||||
.mailpoet_block_transition_in
|
||||
animation-fade-in-and-scale-up()
|
||||
.mailpoet_block_transition_out
|
||||
animation-fade-out-and-scale-down()
|
||||
|
@ -79,3 +79,4 @@ $three-column-width = ($newsletter-width / 3) - (2 * $column-margin)
|
||||
box-shadow(inset 1px 2px 1px $primary-inactive-color)
|
||||
color: #656565
|
||||
border-radius(3px)
|
||||
animation-background-color()
|
||||
|
@ -15,7 +15,11 @@
|
||||
.mailpoet_posts_categories_and_tags
|
||||
width: 100%
|
||||
|
||||
.mailpoet_settings_posts_show_display_options
|
||||
.mailpoet_settings_posts_display_options
|
||||
.mailpoet_settings_posts_selection
|
||||
animation-slide-open-downwards()
|
||||
|
||||
.mailpoet_settings_posts_show_display_options,
|
||||
.mailpoet_settings_posts_show_post_selection
|
||||
display: block
|
||||
margin-top: 10px
|
||||
|
53
assets/css/src/newsletter_editor/mixins/transitions.styl
Normal file
53
assets/css/src/newsletter_editor/mixins/transitions.styl
Normal file
@ -0,0 +1,53 @@
|
||||
animation-slide-open-downwards()
|
||||
transition: all 300ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
||||
max-height: 2000px
|
||||
opacity: 1
|
||||
|
||||
&.mailpoet_closed
|
||||
max-height: 0
|
||||
opacity: 0
|
||||
overflow-y: hidden
|
||||
|
||||
animation-background-color()
|
||||
transition: background 300ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
||||
|
||||
animation-fade-in-and-scale-up()
|
||||
animation-name: fadeInAndScaleUp
|
||||
animation-duration: 500ms
|
||||
animation-fill-mode: forwards
|
||||
|
||||
animation-fade-out-and-scale-down()
|
||||
animation-name: fadeOutAndScaleDown
|
||||
animation-duration: 500ms
|
||||
animation-fill-mode: forwards
|
||||
|
||||
animation-fade-in-and-scale-horizontally()
|
||||
transition: all 300ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
||||
|
||||
@keyframes fadeInAndScaleUp {
|
||||
0% {
|
||||
opacity: 0.3
|
||||
max-height: 0
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1
|
||||
max-height: 5000px
|
||||
overflow: hidden
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeOutAndScaleDown {
|
||||
0% {
|
||||
opacity: 1
|
||||
max-height: 5000px
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0.3
|
||||
max-height: 0
|
||||
overflow: hidden
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
@require 'mixins/border-radius'
|
||||
@require 'mixins/box-shadow'
|
||||
@require 'mixins/filter-shadow'
|
||||
@require 'mixins/transitions'
|
||||
|
||||
@require 'variables'
|
||||
@require 'common'
|
||||
|
29
assets/css/src/progress_bar.styl
Normal file
29
assets/css/src/progress_bar.styl
Normal file
@ -0,0 +1,29 @@
|
||||
.mailpoet_progress
|
||||
background-color: #efefef
|
||||
height: 25px
|
||||
padding: 0
|
||||
width: 100%
|
||||
margin: 0
|
||||
border-radius: 5px
|
||||
position: relative
|
||||
|
||||
.mailpoet_progress_label
|
||||
position: absolute
|
||||
width: 100%
|
||||
text-align: center
|
||||
display: inline-block
|
||||
margin: 2px 0 0 0
|
||||
|
||||
.mailpoet_progress_bar
|
||||
position: absolute
|
||||
display: inline-block
|
||||
height: 100%
|
||||
border-radius: 3px
|
||||
box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset
|
||||
background-color: #34c2e3
|
||||
background-image: linear-gradient(top, #34c2e3, darken(#34c2e3, 20%))
|
||||
|
||||
.mailpoet_progress_complete
|
||||
.mailpoet_progress_bar
|
||||
background-color: #fecf23
|
||||
background-image: linear-gradient(top, #fecf23, #fd9215)
|
Binary file not shown.
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
98
assets/js/src/cron.jsx
Normal file
98
assets/js/src/cron.jsx
Normal file
@ -0,0 +1,98 @@
|
||||
define(
|
||||
[
|
||||
'react',
|
||||
'react-dom',
|
||||
'mailpoet'
|
||||
],
|
||||
function (
|
||||
React,
|
||||
ReactDOM,
|
||||
MailPoet
|
||||
) {
|
||||
var CronControl = React.createClass({
|
||||
getInitialState: function () {
|
||||
return (cronDaemon) ? cronDaemon : null;
|
||||
},
|
||||
getDaemonData: function () {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'cron',
|
||||
action: 'getDaemonStatus'
|
||||
}).done(function (response) {
|
||||
jQuery('.button-primary').removeClass('disabled');
|
||||
if (!response) {
|
||||
this.replaceState();
|
||||
} else {
|
||||
this.setState(response);
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
componentDidMount: function componentDidMount() {
|
||||
if (this.isMounted()) {
|
||||
this.getDaemonData;
|
||||
setInterval(this.getDaemonData, 5000);
|
||||
}
|
||||
},
|
||||
controlDaemon: function (action) {
|
||||
jQuery('.button-primary').addClass('disabled');
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'cron',
|
||||
action: 'controlDaemon',
|
||||
data: {'action': action}
|
||||
}).done(function (response) {
|
||||
if (!response) {
|
||||
this.replaceState();
|
||||
} else {
|
||||
this.setState(response);
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
render: function () {
|
||||
if (!this.state) {
|
||||
return
|
||||
<div>
|
||||
Woops, daemon is not running ;\
|
||||
</div>
|
||||
}
|
||||
switch (this.state.status) {
|
||||
case 'started':
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
Cron daemon is running.
|
||||
<br/>
|
||||
<br/>
|
||||
It was started
|
||||
<strong> {this.state.timeSinceStart} </strong> and last executed
|
||||
<strong> {this.state.timeSinceUpdate} </strong> for a total of
|
||||
<strong> {this.state.counter} </strong> times (once every 30 seconds, unless it was interrupted and restarted).
|
||||
<br />
|
||||
<br />
|
||||
<a href="#" className="button-primary" onClick={this.controlDaemon.bind(null, 'stop')}>Stop</a>
|
||||
<a href="#" className="button-primary" onClick={this.controlDaemon.bind(null, 'pause')}>Pause</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
break;
|
||||
case 'paused':
|
||||
case 'stopped':
|
||||
return (
|
||||
<div>
|
||||
Daemon is {this.state.status}
|
||||
<br />
|
||||
<br />
|
||||
<a href="#" className="button-primary" onClick={this.controlDaemon.bind(null, 'start')}>Start</a>
|
||||
</div>
|
||||
)
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
let container = document.getElementById('cron_container');
|
||||
if (container) {
|
||||
ReactDOM.render(
|
||||
<CronControl />,
|
||||
document.getElementById('cron_status')
|
||||
)
|
||||
}
|
||||
}
|
||||
);
|
@ -23,7 +23,9 @@ function(
|
||||
name={ this.props.field.name }
|
||||
id={ 'field_'+this.props.field.name }
|
||||
value={ this.props.item[this.props.field.name] }
|
||||
onChange={ this.props.onValueChange }>
|
||||
onChange={ this.props.onValueChange }
|
||||
{...this.props.field.validation}
|
||||
>
|
||||
{options}
|
||||
</select>
|
||||
);
|
||||
|
@ -25,13 +25,10 @@ function(
|
||||
(this.props.item !== undefined && prevProps.item !== undefined)
|
||||
&& (this.props.item.id !== prevProps.item.id)
|
||||
) {
|
||||
jQuery('#'+this.refs.select.id).select2(
|
||||
'val',
|
||||
this.props.item[this.props.field.name]
|
||||
);
|
||||
jQuery('#'+this.refs.select.id)
|
||||
.val(this.props.item[this.props.field.name])
|
||||
.trigger('change');
|
||||
}
|
||||
|
||||
this.setupSelect2();
|
||||
},
|
||||
setupSelect2: function() {
|
||||
if(
|
||||
@ -53,7 +50,19 @@ function(
|
||||
}
|
||||
});
|
||||
|
||||
var hasRemoved = false;
|
||||
select2.on('select2:unselecting', function(e) {
|
||||
hasRemoved = true;
|
||||
});
|
||||
select2.on('select2:opening', function(e) {
|
||||
if(hasRemoved === true) {
|
||||
hasRemoved = false;
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
select2.on('change', this.handleChange);
|
||||
|
||||
select2.select2(
|
||||
'val',
|
||||
this.props.item[this.props.field.name]
|
||||
@ -77,7 +86,7 @@ function(
|
||||
handleChange: function(e) {
|
||||
if(this.props.onValueChange !== undefined) {
|
||||
if(this.props.field.multiple) {
|
||||
value = jQuery('#'+this.refs.select.id).select2('val');
|
||||
value = jQuery('#'+this.refs.select.id).val();
|
||||
} else {
|
||||
value = e.target.value;
|
||||
}
|
||||
@ -88,7 +97,6 @@ function(
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
},
|
||||
render: function() {
|
||||
var options = this.state.items.map(function(item, index) {
|
||||
@ -114,8 +122,8 @@ function(
|
||||
ref="select"
|
||||
placeholder={ this.props.field.placeholder }
|
||||
multiple={ this.props.field.multiple }
|
||||
onChange={ this.handleChange }
|
||||
defaultValue={ default_value }
|
||||
{...this.props.field.validation}
|
||||
>{ options }</select>
|
||||
);
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ function(
|
||||
) {
|
||||
var FormFieldText = React.createClass({
|
||||
render: function() {
|
||||
var value = this.props.item[this.props.field.name];
|
||||
if(!value) { value = null; }
|
||||
return (
|
||||
<input
|
||||
type="text"
|
||||
@ -17,10 +19,12 @@ function(
|
||||
}
|
||||
name={ this.props.field.name }
|
||||
id={ 'field_'+this.props.field.name }
|
||||
value={ this.props.item[this.props.field.name] }
|
||||
value={ value }
|
||||
placeholder={ this.props.field.placeholder }
|
||||
defaultValue={ this.props.field.defaultValue }
|
||||
onChange={ this.props.onValueChange } />
|
||||
onChange={ this.props.onValueChange }
|
||||
{...this.props.field.validation}
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -15,7 +15,9 @@ function(
|
||||
value={ this.props.item[this.props.field.name] }
|
||||
placeholder={ this.props.field.placeholder }
|
||||
defaultValue={ this.props.field.defaultValue }
|
||||
onChange={ this.props.onValueChange } />
|
||||
onChange={ this.props.onValueChange }
|
||||
{...this.props.field.validation}
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -68,12 +68,25 @@ define(
|
||||
handleSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// handle validation
|
||||
if(this.props.isValid !== undefined) {
|
||||
if(this.props.isValid() === false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({ loading: true });
|
||||
|
||||
// only get values from displayed fields
|
||||
item = {};
|
||||
var item = {};
|
||||
this.props.fields.map(function(field) {
|
||||
item[field.name] = this.state.item[field.name];
|
||||
if(field['fields'] !== undefined) {
|
||||
field.fields.map(function(subfield) {
|
||||
item[subfield.name] = this.state.item[subfield.name];
|
||||
}.bind(this));
|
||||
} else {
|
||||
item[field.name] = this.state.item[field.name];
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
// set id if specified
|
||||
|
@ -397,6 +397,12 @@ define(
|
||||
if(this.isMounted()) {
|
||||
const params = this.props.params || {}
|
||||
this.initWithParams(params)
|
||||
|
||||
if(this.props.auto_refresh) {
|
||||
jQuery(document).on('heartbeat-tick.mailpoet', function(e, data) {
|
||||
this.getItems();
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
},
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
|
@ -226,11 +226,11 @@ define([
|
||||
toggleDisplayOptions: function(event) {
|
||||
var el = this.$('.mailpoet_automated_latest_content_display_options'),
|
||||
showControl = this.$('.mailpoet_automated_latest_content_show_display_options');
|
||||
if (el.hasClass('mailpoet_hidden')) {
|
||||
el.removeClass('mailpoet_hidden');
|
||||
if (el.hasClass('mailpoet_closed')) {
|
||||
el.removeClass('mailpoet_closed');
|
||||
showControl.addClass('mailpoet_hidden');
|
||||
} else {
|
||||
el.addClass('mailpoet_hidden');
|
||||
el.addClass('mailpoet_closed');
|
||||
showControl.removeClass('mailpoet_hidden');
|
||||
}
|
||||
},
|
||||
|
@ -48,6 +48,7 @@ define([
|
||||
},
|
||||
modelEvents: {
|
||||
'change': 'render',
|
||||
'delete': 'deleteBlock',
|
||||
},
|
||||
events: {
|
||||
"mouseenter": "showTools",
|
||||
@ -88,7 +89,9 @@ define([
|
||||
this.$el.addClass('mailpoet_editor_view_' + this.cid);
|
||||
},
|
||||
initialize: function() {
|
||||
this.on('showSettings', this.showSettings);
|
||||
this.on('showSettings', this.showSettings, this);
|
||||
this.on('dom:refresh', this.showBlock, this);
|
||||
this._isFirstRender = true;
|
||||
},
|
||||
showTools: function(_event) {
|
||||
if (!this.showingToolsDisabled) {
|
||||
@ -121,6 +124,34 @@ define([
|
||||
return newModel;
|
||||
};
|
||||
},
|
||||
showBlock: function() {
|
||||
if (this._isFirstRender) {
|
||||
this.transitionIn();
|
||||
this._isFirstRender = false;
|
||||
}
|
||||
},
|
||||
deleteBlock: function() {
|
||||
this.transitionOut().done(function() {
|
||||
this.model.destroy();
|
||||
}.bind(this));
|
||||
},
|
||||
transitionIn: function() {
|
||||
return this._transition('mailpoet_block_transition_in');
|
||||
},
|
||||
transitionOut: function() {
|
||||
return this._transition('mailpoet_block_transition_out');
|
||||
},
|
||||
_transition: function(className) {
|
||||
var that = this,
|
||||
promise = jQuery.Deferred();
|
||||
|
||||
this.$el.addClass(className);
|
||||
this.$el.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd animationend', function() {
|
||||
that.$el.removeClass('mailpoet_block_transition_out');
|
||||
promise.resolve();
|
||||
});
|
||||
return promise;
|
||||
},
|
||||
});
|
||||
|
||||
Module.BlockToolsView = AugmentedView.extend({
|
||||
@ -168,9 +199,9 @@ define([
|
||||
},
|
||||
deleteBlock: function(event) {
|
||||
event.preventDefault();
|
||||
this.model.destroy();
|
||||
this.model.trigger('delete');
|
||||
return false;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Module.BlockSettingsView = Marionette.LayoutView.extend({
|
||||
|
@ -42,16 +42,12 @@ define([
|
||||
Module.ButtonBlockView = base.BlockView.extend({
|
||||
className: "mailpoet_block mailpoet_button_block mailpoet_droppable_block",
|
||||
getTemplate: function() { return templates.buttonBlock; },
|
||||
modelEvents: {
|
||||
'change': 'render',
|
||||
},
|
||||
onDragSubstituteBy: function() { return Module.ButtonWidgetView; },
|
||||
initialize: function() {
|
||||
base.BlockView.prototype.initialize.apply(this, arguments);
|
||||
var that = this;
|
||||
|
||||
// Listen for attempts to change all dividers in one go
|
||||
this._replaceButtonStylesHandler = function(data) { that.model.set(data); };
|
||||
this._replaceButtonStylesHandler = function(data) { this.model.set(data); }.bind(this);
|
||||
App.getChannel().on('replaceAllButtonStyles', this._replaceButtonStylesHandler);
|
||||
},
|
||||
onRender: function() {
|
||||
|
@ -75,7 +75,8 @@ define([
|
||||
getEmptyView: function() { return Module.ContainerBlockEmptyView; },
|
||||
emptyViewOptions: function() { return { renderOptions: this.renderOptions }; },
|
||||
modelEvents: {
|
||||
'change': 'render'
|
||||
'change': 'render',
|
||||
'delete': 'deleteBlock',
|
||||
},
|
||||
events: {
|
||||
"mouseenter": "showTools",
|
||||
@ -136,6 +137,8 @@ define([
|
||||
},
|
||||
initialize: function(options) {
|
||||
this.renderOptions = _.defaults(options.renderOptions || {}, {});
|
||||
this.on('dom:refresh', this.showBlock, this);
|
||||
this._isFirstRender = true;
|
||||
},
|
||||
// Determines which view type should be used for a child
|
||||
getChildView: function(model) {
|
||||
@ -236,6 +239,34 @@ define([
|
||||
return newModel;
|
||||
};
|
||||
},
|
||||
showBlock: function() {
|
||||
if (this._isFirstRender) {
|
||||
this.transitionIn();
|
||||
this._isFirstRender = false;
|
||||
}
|
||||
},
|
||||
deleteBlock: function() {
|
||||
this.transitionOut().done(function() {
|
||||
this.model.destroy();
|
||||
}.bind(this));
|
||||
},
|
||||
transitionIn: function() {
|
||||
return this._transition('mailpoet_block_transition_in');
|
||||
},
|
||||
transitionOut: function() {
|
||||
return this._transition('mailpoet_block_transition_out');
|
||||
},
|
||||
_transition: function(className) {
|
||||
var that = this,
|
||||
promise = jQuery.Deferred();
|
||||
|
||||
this.$el.addClass(className);
|
||||
this.$el.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd animationend', function() {
|
||||
that.$el.removeClass('mailpoet_block_transition_out');
|
||||
promise.resolve();
|
||||
});
|
||||
return promise;
|
||||
},
|
||||
});
|
||||
|
||||
Module.ContainerBlockEmptyView = Marionette.ItemView.extend({
|
||||
|
@ -222,8 +222,8 @@ define([
|
||||
},
|
||||
switchToDisplayOptions: function() {
|
||||
// Switch content view
|
||||
this.$('.mailpoet_settings_posts_selection').addClass('mailpoet_hidden');
|
||||
this.$('.mailpoet_settings_posts_display_options').removeClass('mailpoet_hidden');
|
||||
this.$('.mailpoet_settings_posts_selection').addClass('mailpoet_closed');
|
||||
this.$('.mailpoet_settings_posts_display_options').removeClass('mailpoet_closed');
|
||||
|
||||
// Switch controls
|
||||
this.$('.mailpoet_settings_posts_show_display_options').addClass('mailpoet_hidden');
|
||||
@ -231,8 +231,8 @@ define([
|
||||
},
|
||||
switchToPostSelection: function() {
|
||||
// Switch content view
|
||||
this.$('.mailpoet_settings_posts_display_options').addClass('mailpoet_hidden');
|
||||
this.$('.mailpoet_settings_posts_selection').removeClass('mailpoet_hidden');
|
||||
this.$('.mailpoet_settings_posts_display_options').addClass('mailpoet_closed');
|
||||
this.$('.mailpoet_settings_posts_selection').removeClass('mailpoet_closed');
|
||||
|
||||
// Switch controls
|
||||
this.$('.mailpoet_settings_posts_show_post_selection').addClass('mailpoet_hidden');
|
||||
|
@ -103,7 +103,8 @@ define([
|
||||
getTemplate: function() { return templates.socialBlock; },
|
||||
childViewContainer: '.mailpoet_social',
|
||||
modelEvents: {
|
||||
'change': 'render'
|
||||
'change': 'render',
|
||||
'delete': 'deleteBlock',
|
||||
},
|
||||
events: {
|
||||
"mouseover": "showTools",
|
||||
@ -145,6 +146,10 @@ define([
|
||||
arguments[0].collection = arguments[0].model.get('icons');
|
||||
Marionette.CompositeView.apply(this, arguments);
|
||||
},
|
||||
initialize: function() {
|
||||
this.on('dom:refresh', this.showBlock, this);
|
||||
this._isFirstRender = true;
|
||||
},
|
||||
// Determines which view type should be used for a child
|
||||
childView: SocialIconView,
|
||||
templateHelpers: function() {
|
||||
@ -194,6 +199,34 @@ define([
|
||||
this.regionManager.destroy();
|
||||
_.extend(this, this._buildRegions(this.regions));
|
||||
},
|
||||
showBlock: function() {
|
||||
if (this._isFirstRender) {
|
||||
this.transitionIn();
|
||||
this._isFirstRender = false;
|
||||
}
|
||||
},
|
||||
deleteBlock: function() {
|
||||
this.transitionOut().done(function() {
|
||||
this.model.destroy();
|
||||
}.bind(this));
|
||||
},
|
||||
transitionIn: function() {
|
||||
return this._transition('mailpoet_block_transition_in');
|
||||
},
|
||||
transitionOut: function() {
|
||||
return this._transition('mailpoet_block_transition_out');
|
||||
},
|
||||
_transition: function(className) {
|
||||
var that = this,
|
||||
promise = jQuery.Deferred();
|
||||
|
||||
this.$el.addClass(className);
|
||||
this.$el.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd animationend', function() {
|
||||
that.$el.removeClass('mailpoet_block_transition_out');
|
||||
promise.resolve();
|
||||
});
|
||||
return promise;
|
||||
},
|
||||
});
|
||||
|
||||
Module.SocialBlockToolsView = base.BlockToolsView.extend({
|
||||
|
@ -47,20 +47,36 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
Module.saveTemplate = function(options) {
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'newsletterTemplates',
|
||||
action: 'save',
|
||||
data: _.extend(options || {}, {
|
||||
body: App.getBody(),
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
Module.getThumbnail = function(element, options) {
|
||||
return html2canvas(element, options || {});
|
||||
};
|
||||
|
||||
Module.saveTemplate = function(options) {
|
||||
var that = this,
|
||||
promise = jQuery.Deferred();
|
||||
|
||||
promise.then(function(thumbnail) {
|
||||
var data = _.extend(options || {}, {
|
||||
thumbnail: thumbnail.toDataURL('image/jpeg'),
|
||||
body: App.getBody(),
|
||||
});
|
||||
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'newsletterTemplates',
|
||||
action: 'save',
|
||||
data: data,
|
||||
});
|
||||
});
|
||||
|
||||
Module.getThumbnail(
|
||||
jQuery('#mailpoet_editor_content > .mailpoet_block').get(0)
|
||||
).then(function(thumbnail) {
|
||||
promise.resolve(thumbnail);
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
Module.exportTemplate = function(options) {
|
||||
var that = this;
|
||||
return Module.getThumbnail(
|
||||
|
@ -21,6 +21,10 @@ define(
|
||||
label: 'Subject',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: 'status',
|
||||
label: 'Status'
|
||||
},
|
||||
{
|
||||
name: 'segments',
|
||||
label: 'Lists'
|
||||
@ -119,8 +123,94 @@ define(
|
||||
];
|
||||
|
||||
var NewsletterList = React.createClass({
|
||||
renderItem: function(newsletter, actions) {
|
||||
pauseSending: function(item) {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'sendingQueue',
|
||||
action: 'pause',
|
||||
data: item.id
|
||||
}).done(function() {
|
||||
jQuery('#resume_'+item.id).show();
|
||||
jQuery('#pause_'+item.id).hide();
|
||||
});
|
||||
},
|
||||
resumeSending: function(item) {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'sendingQueue',
|
||||
action: 'resume',
|
||||
data: item.id
|
||||
}).done(function() {
|
||||
jQuery('#pause_'+item.id).show();
|
||||
jQuery('#resume_'+item.id).hide();
|
||||
});
|
||||
},
|
||||
renderStatus: function(item) {
|
||||
if(item.queue === null) {
|
||||
return (
|
||||
<span>Not sent yet.</span>
|
||||
);
|
||||
} else {
|
||||
var progressClasses = classNames(
|
||||
'mailpoet_progress',
|
||||
{ 'mailpoet_progress_complete': item.queue.status === 'completed'}
|
||||
);
|
||||
|
||||
// calculate percentage done
|
||||
var percentage = Math.round(
|
||||
(item.queue.count_processed * 100) / (item.queue.count_total)
|
||||
);
|
||||
|
||||
var label = false;
|
||||
|
||||
if(item.queue.status === 'completed') {
|
||||
label = (
|
||||
<span>
|
||||
Sent to {
|
||||
item.queue.count_processed - item.queue.count_failed
|
||||
} out of { item.queue.count_total }.
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
label = (
|
||||
<span>
|
||||
{ item.queue.count_processed } / { item.queue.count_total }
|
||||
|
||||
<a
|
||||
id={ 'resume_'+item.id }
|
||||
className="button"
|
||||
style={{ display: (item.queue.status === 'paused') ? 'inline-block': 'none' }}
|
||||
href="javascript:;"
|
||||
onClick={ this.resumeSending.bind(null, item) }
|
||||
>Resume</a>
|
||||
<a
|
||||
id={ 'pause_'+item.id }
|
||||
className="button mailpoet_pause"
|
||||
style={{ display: (item.queue.status === null) ? 'inline-block': 'none' }}
|
||||
href="javascript:;"
|
||||
onClick={ this.pauseSending.bind(null, item) }
|
||||
>Pause</a>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={ progressClasses }>
|
||||
<span
|
||||
className="mailpoet_progress_bar"
|
||||
style={ { width: percentage + "%"} }
|
||||
></span>
|
||||
<span className="mailpoet_progress_label">
|
||||
{ percentage + "%" }
|
||||
</span>
|
||||
</div>
|
||||
<p style={{ textAlign:'center' }}>
|
||||
{ label }
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
renderItem: function(newsletter, actions) {
|
||||
var rowClasses = classNames(
|
||||
'manage-column',
|
||||
'column-primary',
|
||||
@ -141,6 +231,9 @@ define(
|
||||
</strong>
|
||||
{ actions }
|
||||
</td>
|
||||
<td className="column" data-colname="Lists">
|
||||
{ this.renderStatus(newsletter) }
|
||||
</td>
|
||||
<td className="column" data-colname="Lists">
|
||||
{ segments }
|
||||
</td>
|
||||
@ -167,7 +260,8 @@ define(
|
||||
columns={columns}
|
||||
bulk_actions={ bulk_actions }
|
||||
item_actions={ item_actions }
|
||||
messages={ messages } />
|
||||
messages={ messages }
|
||||
auto_refresh={ true } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -37,6 +37,9 @@ define(
|
||||
multiple: true,
|
||||
filter: function(segment) {
|
||||
return !!(!segment.deleted_at);
|
||||
},
|
||||
validation: {
|
||||
'data-parsley-required': true
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -45,17 +48,24 @@ define(
|
||||
tip: "Name & email of yourself or your company.",
|
||||
fields: [
|
||||
{
|
||||
name: 'from_name',
|
||||
name: 'sender_name',
|
||||
type: 'text',
|
||||
placeholder: 'John Doe',
|
||||
defaultValue: settings.from_name
|
||||
defaultValue: (settings.sender !== undefined) ? settings.sender.name : '',
|
||||
validation: {
|
||||
'data-parsley-required': true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'from_email',
|
||||
name: 'sender_address',
|
||||
type: 'text',
|
||||
placeholder: 'john.doe@email.com',
|
||||
defaultValue: settings.from_address
|
||||
},
|
||||
defaultValue: (settings.sender !== undefined) ? settings.sender.address : '',
|
||||
validation: {
|
||||
'data-parsley-required': true,
|
||||
'data-parsley-type': 'email'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -68,20 +78,25 @@ define(
|
||||
{
|
||||
name: 'reply_to_name',
|
||||
type: 'text',
|
||||
placeholder: 'John Doe'
|
||||
placeholder: 'John Doe',
|
||||
defaultValue: (settings.reply_to !== undefined) ? settings.reply_to.name : '',
|
||||
},
|
||||
{
|
||||
name: 'reply_to_email',
|
||||
name: 'reply_to_address',
|
||||
type: 'text',
|
||||
placeholder: 'john.doe@email.com'
|
||||
placeholder: 'john.doe@email.com',
|
||||
defaultValue: (settings.reply_to !== undefined) ? settings.reply_to.address : ''
|
||||
},
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
var messages = {
|
||||
updated: function() {
|
||||
MailPoet.Notice.success('The newsletter has been updated!');
|
||||
onUpdate: function() {
|
||||
MailPoet.Notice.success('Newsletter successfully updated!');
|
||||
},
|
||||
onCreate: function() {
|
||||
MailPoet.Notice.success('Newsletter successfully added!');
|
||||
}
|
||||
};
|
||||
|
||||
@ -90,34 +105,43 @@ define(
|
||||
Router.History
|
||||
],
|
||||
handleSend: function() {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'send',
|
||||
data: {
|
||||
id: this.props.params.id,
|
||||
newsletter: jQuery('#mailpoet_newsletter').serializeObject(),
|
||||
segments: jQuery('#mailpoet_segments').val()
|
||||
}
|
||||
}).done(function(response) {
|
||||
if(response === true) {
|
||||
this.history.pushState(null, '/');
|
||||
if(jQuery('#mailpoet_newsletter').parsley().validate() === true) {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'sendingQueue',
|
||||
action: 'add',
|
||||
data: {
|
||||
newsletter_id: this.props.params.id,
|
||||
segments: jQuery('#mailpoet_segments').val()
|
||||
}
|
||||
}).done(function(response) {
|
||||
if(response.result === true) {
|
||||
this.history.pushState(null, '/');
|
||||
|
||||
MailPoet.Notice.success(
|
||||
'The newsletter has been sent!'
|
||||
);
|
||||
} else {
|
||||
if(response.errors) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.join("<br />")
|
||||
MailPoet.Notice.success(
|
||||
'The newsletter is being sent...'
|
||||
);
|
||||
} else {
|
||||
MailPoet.Notice.error(
|
||||
'An error occurred while trying to send. '+
|
||||
'<a href="?page=mailpoet-settings">Check your settings.</a>'
|
||||
);
|
||||
if(response.errors) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.join("<br />")
|
||||
);
|
||||
} else {
|
||||
MailPoet.Notice.error(
|
||||
'An error occurred while trying to send. '+
|
||||
'<a href="?page=mailpoet-settings">Check your settings.</a>'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
componentDidMount: function() {
|
||||
if(this.isMounted()) {
|
||||
jQuery('#mailpoet_newsletter').parsley();
|
||||
}
|
||||
},
|
||||
isValid: function() {
|
||||
return (jQuery('#mailpoet_newsletter').parsley().validate());
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
@ -131,7 +155,8 @@ define(
|
||||
endpoint="newsletters"
|
||||
fields={ fields }
|
||||
params={ this.props.params }
|
||||
messages={ messages }>
|
||||
messages={ messages }
|
||||
isValid={ this.isValid }>
|
||||
|
||||
<p className="submit">
|
||||
<input
|
||||
|
@ -99,7 +99,7 @@ define(
|
||||
"MailPoet's Guide",
|
||||
description:
|
||||
"This is the standard template that comes with MailPoet.",
|
||||
readonly: true
|
||||
readonly: "1"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -210,7 +210,7 @@ define(
|
||||
Preview
|
||||
</a>
|
||||
</div>
|
||||
{ (template.readonly) ? false : deleteLink }
|
||||
{ (template.readonly === "1") ? false : deleteLink }
|
||||
</li>
|
||||
);
|
||||
}.bind(this));
|
||||
|
@ -1,75 +0,0 @@
|
||||
define(
|
||||
[
|
||||
'react',
|
||||
'react-dom',
|
||||
'mailpoet',
|
||||
'classnames'
|
||||
],
|
||||
function (
|
||||
React,
|
||||
ReactDOM,
|
||||
MailPoet,
|
||||
classNames
|
||||
) {
|
||||
var QueueDaemonControl = React.createClass({
|
||||
getInitialState: function () {
|
||||
return (queueDaemon) ? {
|
||||
status: queueDaemon.status,
|
||||
timeSinceStart: queueDaemon.time_since_start,
|
||||
timeSinceUpdate: queueDaemon.time_since_update,
|
||||
counter: queueDaemon.counter
|
||||
} : null;
|
||||
},
|
||||
getDaemonData: function () {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'queue',
|
||||
action: 'getQueueStatus'
|
||||
}).done(function (response) {
|
||||
this.setState({
|
||||
status: response.status,
|
||||
timeSinceStart: response.time_since_start,
|
||||
timeSinceUpdate: response.time_since_update,
|
||||
counter: response.counter,
|
||||
});
|
||||
}.bind(this));
|
||||
},
|
||||
componentDidMount: function () {
|
||||
this.getDaemonData;
|
||||
setInterval(this.getDaemonData, 5000);
|
||||
},
|
||||
render: function () {
|
||||
if (!this.state) {
|
||||
return (
|
||||
<div className="QueueControl">
|
||||
Woops, daemon is not running ;\
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
Queue is currently <b>{this.state.status}</b>.
|
||||
<br/>
|
||||
<br/>
|
||||
It was started
|
||||
<b> {this.state.timeSinceStart} </b> and was last executed
|
||||
<b> {this.state.timeSinceUpdate} </b> for a total of
|
||||
<b> {this.state.counter} </b> times (once every 30 seconds, unless it was interrupted and restarted).
|
||||
<br />
|
||||
</div>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
let container = document.getElementById('queue_container');
|
||||
if (container) {
|
||||
ReactDOM.render(
|
||||
<QueueDaemonControl />,
|
||||
container
|
||||
)
|
||||
}
|
||||
}
|
||||
);
|
@ -131,10 +131,12 @@ const item_actions = [
|
||||
label: 'Update',
|
||||
className: 'update',
|
||||
onClick: function(item, refresh) {
|
||||
return MailPoet.Ajax.post({
|
||||
MailPoet.Modal.loading(true);
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'segments',
|
||||
action: 'synchronize'
|
||||
}).done(function(response) {
|
||||
MailPoet.Modal.loading(false);
|
||||
if(response === true) {
|
||||
MailPoet.Notice.success(
|
||||
('List "%$1s" has been synchronized.').replace('%$1s', item.name)
|
||||
|
@ -15,10 +15,10 @@ define(
|
||||
|
||||
MailPoet.Router = new (Backbone.Router.extend({
|
||||
routes: {
|
||||
'mta(/:method)': 'sendingMethod',
|
||||
'mta(/:group)': 'sendingMethodGroup',
|
||||
'(:tab)': 'tabs',
|
||||
},
|
||||
sendingMethod: function(method) {
|
||||
sendingMethodGroup: function(group) {
|
||||
// display mta tab
|
||||
this.tabs('mta');
|
||||
|
||||
@ -30,13 +30,13 @@ define(
|
||||
// hide "save settings" button
|
||||
jQuery('.mailpoet_settings_submit').hide();
|
||||
|
||||
if(method === null) {
|
||||
if(group === null) {
|
||||
// show sending methods
|
||||
jQuery('.mailpoet_sending_methods').fadeIn();
|
||||
} else {
|
||||
// hide DKIM option when using MailPoet's API
|
||||
jQuery('#mailpoet_mta_dkim')[
|
||||
(method === 'mailpoet')
|
||||
(group === 'mailpoet')
|
||||
? 'hide'
|
||||
: 'show'
|
||||
]();
|
||||
@ -45,7 +45,7 @@ define(
|
||||
jQuery('.mailpoet_sending_methods').hide();
|
||||
|
||||
// display selected sending method's settings
|
||||
jQuery('.mailpoet_sending_method[data-method="'+ method +'"]').show();
|
||||
jQuery('.mailpoet_sending_method[data-group="'+ group +'"]').show();
|
||||
jQuery('#mailpoet_sending_method_setup').fadeIn();
|
||||
}
|
||||
},
|
||||
|
468
composer.lock
generated
468
composer.lock
generated
@ -4,8 +4,8 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "7d7ef94b6e40ac2b2d594e5832d7e16d",
|
||||
"content-hash": "2e70c335edf7429df0794ebf49e2f210",
|
||||
"hash": "4720dce62e4a6a7bf4d3ba3944b9c2b9",
|
||||
"content-hash": "748470f0803c52a798a4ecd1bb8a93b9",
|
||||
"packages": [
|
||||
{
|
||||
"name": "cerdic/css-tidy",
|
||||
@ -158,6 +158,97 @@
|
||||
],
|
||||
"time": "2014-09-23 10:49:36"
|
||||
},
|
||||
{
|
||||
"name": "mtdowling/cron-expression",
|
||||
"version": "v1.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mtdowling/cron-expression.git",
|
||||
"reference": "fd92e883195e5dfa77720b1868cf084b08be4412"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/mtdowling/cron-expression/zipball/fd92e883195e5dfa77720b1868cf084b08be4412",
|
||||
"reference": "fd92e883195e5dfa77720b1868cf084b08be4412",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "4.*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Cron": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
}
|
||||
],
|
||||
"description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due",
|
||||
"keywords": [
|
||||
"cron",
|
||||
"schedule"
|
||||
],
|
||||
"time": "2015-01-11 23:07:46"
|
||||
},
|
||||
{
|
||||
"name": "nesbot/carbon",
|
||||
"version": "1.21.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/briannesbitt/Carbon.git",
|
||||
"reference": "7b08ec6f75791e130012f206e3f7b0e76e18e3d7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/7b08ec6f75791e130012f206e3f7b0e76e18e3d7",
|
||||
"reference": "7b08ec6f75791e130012f206e3f7b0e76e18e3d7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0",
|
||||
"symfony/translation": "~2.6|~3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0|~5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Carbon\\": "src/Carbon/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Brian Nesbitt",
|
||||
"email": "brian@nesbot.com",
|
||||
"homepage": "http://nesbot.com"
|
||||
}
|
||||
],
|
||||
"description": "A simple API extension for DateTime.",
|
||||
"homepage": "http://carbon.nesbot.com",
|
||||
"keywords": [
|
||||
"date",
|
||||
"datetime",
|
||||
"time"
|
||||
],
|
||||
"time": "2015-11-04 20:07:17"
|
||||
},
|
||||
{
|
||||
"name": "phpmailer/phpmailer",
|
||||
"version": "v5.2.14",
|
||||
@ -403,6 +494,69 @@
|
||||
],
|
||||
"time": "2015-06-06 14:19:39"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
"version": "v2.7.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation.git",
|
||||
"reference": "e4ecb9c3ba1304eaf24de15c2d7a428101c1982f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/e4ecb9c3ba1304eaf24de15c2d7a428101c1982f",
|
||||
"reference": "e4ecb9c3ba1304eaf24de15c2d7a428101c1982f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.9"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/config": "<2.7"
|
||||
},
|
||||
"require-dev": {
|
||||
"psr/log": "~1.0",
|
||||
"symfony/config": "~2.7",
|
||||
"symfony/intl": "~2.4",
|
||||
"symfony/yaml": "~2.2"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/log": "To use logging capability in translator",
|
||||
"symfony/config": "",
|
||||
"symfony/yaml": ""
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.7-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Translation\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Translation Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-11-18 13:41:01"
|
||||
},
|
||||
{
|
||||
"name": "tburry/pquery",
|
||||
"version": "v1.1.0",
|
||||
@ -783,16 +937,16 @@
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "6.1.0",
|
||||
"version": "6.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/guzzle.git",
|
||||
"reference": "66fd14b4d0b8f2389eaf37c5458608c7cb793a81"
|
||||
"reference": "c6851d6e48f63b69357cbfa55bca116448140e0c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/66fd14b4d0b8f2389eaf37c5458608c7cb793a81",
|
||||
"reference": "66fd14b4d0b8f2389eaf37c5458608c7cb793a81",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/c6851d6e48f63b69357cbfa55bca116448140e0c",
|
||||
"reference": "c6851d6e48f63b69357cbfa55bca116448140e0c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -841,7 +995,7 @@
|
||||
"rest",
|
||||
"web service"
|
||||
],
|
||||
"time": "2015-09-08 17:36:26"
|
||||
"time": "2015-11-23 00:47:50"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/promises",
|
||||
@ -1961,16 +2115,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/browser-kit",
|
||||
"version": "v2.7.6",
|
||||
"version": "v2.7.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/browser-kit.git",
|
||||
"reference": "07d664a052572ccc28eb2ab7dbbe82155b1ad367"
|
||||
"reference": "bd28847ea2193916074c7b11d4fdd78570049694"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/07d664a052572ccc28eb2ab7dbbe82155b1ad367",
|
||||
"reference": "07d664a052572ccc28eb2ab7dbbe82155b1ad367",
|
||||
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/bd28847ea2193916074c7b11d4fdd78570049694",
|
||||
"reference": "bd28847ea2193916074c7b11d4fdd78570049694",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1993,7 +2147,10 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\BrowserKit\\": ""
|
||||
}
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@ -2011,20 +2168,20 @@
|
||||
],
|
||||
"description": "Symfony BrowserKit Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-10-23 14:47:27"
|
||||
"time": "2015-11-02 20:20:53"
|
||||
},
|
||||
{
|
||||
"name": "symfony/config",
|
||||
"version": "v2.7.6",
|
||||
"version": "v2.7.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/config.git",
|
||||
"reference": "831f88908b51b9ce945f5e6f402931d1ac544423"
|
||||
"reference": "61973327bfb054f6f470de7be033a28b76c1dc20"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/config/zipball/831f88908b51b9ce945f5e6f402931d1ac544423",
|
||||
"reference": "831f88908b51b9ce945f5e6f402931d1ac544423",
|
||||
"url": "https://api.github.com/repos/symfony/config/zipball/61973327bfb054f6f470de7be033a28b76c1dc20",
|
||||
"reference": "61973327bfb054f6f470de7be033a28b76c1dc20",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2040,7 +2197,10 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Config\\": ""
|
||||
}
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@ -2058,20 +2218,20 @@
|
||||
],
|
||||
"description": "Symfony Config Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-10-11 09:39:48"
|
||||
"time": "2015-11-02 20:20:53"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v2.7.6",
|
||||
"version": "v2.7.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "5efd632294c8320ea52492db22292ff853a43766"
|
||||
"reference": "16bb1cb86df43c90931df65f529e7ebd79636750"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/5efd632294c8320ea52492db22292ff853a43766",
|
||||
"reference": "5efd632294c8320ea52492db22292ff853a43766",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/16bb1cb86df43c90931df65f529e7ebd79636750",
|
||||
"reference": "16bb1cb86df43c90931df65f529e7ebd79636750",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2096,7 +2256,10 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Console\\": ""
|
||||
}
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@ -2114,20 +2277,20 @@
|
||||
],
|
||||
"description": "Symfony Console Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-10-20 14:38:46"
|
||||
"time": "2015-11-18 09:54:26"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
"version": "v2.7.6",
|
||||
"version": "v2.7.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/css-selector.git",
|
||||
"reference": "e1b865b26be4a56d22a8dee398375044a80c865b"
|
||||
"reference": "abb47717fb88aebd9437da2fc8bb01a50a36679f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/e1b865b26be4a56d22a8dee398375044a80c865b",
|
||||
"reference": "e1b865b26be4a56d22a8dee398375044a80c865b",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/abb47717fb88aebd9437da2fc8bb01a50a36679f",
|
||||
"reference": "abb47717fb88aebd9437da2fc8bb01a50a36679f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2142,7 +2305,10 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\CssSelector\\": ""
|
||||
}
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@ -2164,20 +2330,20 @@
|
||||
],
|
||||
"description": "Symfony CssSelector Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-10-11 09:39:48"
|
||||
"time": "2015-10-30 20:10:21"
|
||||
},
|
||||
{
|
||||
"name": "symfony/dom-crawler",
|
||||
"version": "v2.7.6",
|
||||
"version": "v2.7.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/dom-crawler.git",
|
||||
"reference": "5fef7d8b80d8f9992df99d8ee283f420484c9612"
|
||||
"reference": "b33593cbfe1d81b50d48353f338aca76a08658d8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/5fef7d8b80d8f9992df99d8ee283f420484c9612",
|
||||
"reference": "5fef7d8b80d8f9992df99d8ee283f420484c9612",
|
||||
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/b33593cbfe1d81b50d48353f338aca76a08658d8",
|
||||
"reference": "b33593cbfe1d81b50d48353f338aca76a08658d8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2198,7 +2364,10 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\DomCrawler\\": ""
|
||||
}
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@ -2216,20 +2385,20 @@
|
||||
],
|
||||
"description": "Symfony DomCrawler Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-10-11 09:39:48"
|
||||
"time": "2015-11-02 20:20:53"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"version": "v2.7.6",
|
||||
"version": "v2.7.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||
"reference": "87a5db5ea887763fa3a31a5471b512ff1596d9b8"
|
||||
"reference": "7e2f9c31645680026c2372edf66f863fc7757af5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/87a5db5ea887763fa3a31a5471b512ff1596d9b8",
|
||||
"reference": "87a5db5ea887763fa3a31a5471b512ff1596d9b8",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7e2f9c31645680026c2372edf66f863fc7757af5",
|
||||
"reference": "7e2f9c31645680026c2372edf66f863fc7757af5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2255,7 +2424,10 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\EventDispatcher\\": ""
|
||||
}
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@ -2273,20 +2445,20 @@
|
||||
],
|
||||
"description": "Symfony EventDispatcher Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-10-11 09:39:48"
|
||||
"time": "2015-10-30 20:10:21"
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v2.7.6",
|
||||
"version": "v2.7.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "56fd6df73be859323ff97418d97edc1d756df6df"
|
||||
"reference": "8e173509d7fdbbba3cf34d6d072f2073c0210c1d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/56fd6df73be859323ff97418d97edc1d756df6df",
|
||||
"reference": "56fd6df73be859323ff97418d97edc1d756df6df",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/8e173509d7fdbbba3cf34d6d072f2073c0210c1d",
|
||||
"reference": "8e173509d7fdbbba3cf34d6d072f2073c0210c1d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2301,7 +2473,10 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Filesystem\\": ""
|
||||
}
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@ -2319,20 +2494,20 @@
|
||||
],
|
||||
"description": "Symfony Filesystem Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-10-18 20:23:18"
|
||||
"time": "2015-11-18 13:41:01"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v2.7.6",
|
||||
"version": "v2.7.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/finder.git",
|
||||
"reference": "2ffb4e9598db3c48eb6d0ae73b04bbf09280c59d"
|
||||
"reference": "a06a0c0ff7db3736a50d530c908cca547bf13da9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/2ffb4e9598db3c48eb6d0ae73b04bbf09280c59d",
|
||||
"reference": "2ffb4e9598db3c48eb6d0ae73b04bbf09280c59d",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/a06a0c0ff7db3736a50d530c908cca547bf13da9",
|
||||
"reference": "a06a0c0ff7db3736a50d530c908cca547bf13da9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2347,7 +2522,10 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Finder\\": ""
|
||||
}
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@ -2365,20 +2543,20 @@
|
||||
],
|
||||
"description": "Symfony Finder Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-10-11 09:39:48"
|
||||
"time": "2015-10-30 20:10:21"
|
||||
},
|
||||
{
|
||||
"name": "symfony/form",
|
||||
"version": "v2.7.6",
|
||||
"version": "v2.7.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/form.git",
|
||||
"reference": "b93fcb816bec2b8470ea9d54e4b6658b2461b83c"
|
||||
"reference": "0a2c2ce0d4bd3c50bb0ae4e75ac27e5274c25e81"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/form/zipball/b93fcb816bec2b8470ea9d54e4b6658b2461b83c",
|
||||
"reference": "b93fcb816bec2b8470ea9d54e4b6658b2461b83c",
|
||||
"url": "https://api.github.com/repos/symfony/form/zipball/0a2c2ce0d4bd3c50bb0ae4e75ac27e5274c25e81",
|
||||
"reference": "0a2c2ce0d4bd3c50bb0ae4e75ac27e5274c25e81",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2416,7 +2594,10 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Form\\": ""
|
||||
}
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@ -2434,20 +2615,20 @@
|
||||
],
|
||||
"description": "Symfony Form Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-10-27 15:38:06"
|
||||
"time": "2015-11-23 10:34:14"
|
||||
},
|
||||
{
|
||||
"name": "symfony/intl",
|
||||
"version": "v2.7.6",
|
||||
"version": "v2.7.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/intl.git",
|
||||
"reference": "330f52a996749eb6a2fdc1506c7a4868e070d678"
|
||||
"reference": "6c6c3aa69f68aff72e48a9bfc11f24680e23eb2d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/intl/zipball/330f52a996749eb6a2fdc1506c7a4868e070d678",
|
||||
"reference": "330f52a996749eb6a2fdc1506c7a4868e070d678",
|
||||
"url": "https://api.github.com/repos/symfony/intl/zipball/6c6c3aa69f68aff72e48a9bfc11f24680e23eb2d",
|
||||
"reference": "6c6c3aa69f68aff72e48a9bfc11f24680e23eb2d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2474,6 +2655,9 @@
|
||||
],
|
||||
"files": [
|
||||
"Resources/stubs/functions.php"
|
||||
],
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
@ -2508,20 +2692,20 @@
|
||||
"l10n",
|
||||
"localization"
|
||||
],
|
||||
"time": "2015-10-11 09:39:48"
|
||||
"time": "2015-11-18 13:41:01"
|
||||
},
|
||||
{
|
||||
"name": "symfony/options-resolver",
|
||||
"version": "v2.7.6",
|
||||
"version": "v2.7.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/options-resolver.git",
|
||||
"reference": "85fd10e551677d3c9a4632def78b8ec4670b247d"
|
||||
"reference": "d6b7d3452b4cfff89b642993e02fea7cc254530e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/85fd10e551677d3c9a4632def78b8ec4670b247d",
|
||||
"reference": "85fd10e551677d3c9a4632def78b8ec4670b247d",
|
||||
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/d6b7d3452b4cfff89b642993e02fea7cc254530e",
|
||||
"reference": "d6b7d3452b4cfff89b642993e02fea7cc254530e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2536,7 +2720,10 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\OptionsResolver\\": ""
|
||||
}
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@ -2559,20 +2746,20 @@
|
||||
"configuration",
|
||||
"options"
|
||||
],
|
||||
"time": "2015-10-11 09:39:48"
|
||||
"time": "2015-11-18 13:41:01"
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v2.7.6",
|
||||
"version": "v2.7.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "4a959dd4e19c2c5d7512689413921e0a74386ec7"
|
||||
"reference": "f6290983c8725d0afa29bdc3e5295879de3e58f5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/4a959dd4e19c2c5d7512689413921e0a74386ec7",
|
||||
"reference": "4a959dd4e19c2c5d7512689413921e0a74386ec7",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/f6290983c8725d0afa29bdc3e5295879de3e58f5",
|
||||
"reference": "f6290983c8725d0afa29bdc3e5295879de3e58f5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2587,7 +2774,10 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Process\\": ""
|
||||
}
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@ -2605,20 +2795,20 @@
|
||||
],
|
||||
"description": "Symfony Process Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-10-23 14:47:27"
|
||||
"time": "2015-11-19 16:11:24"
|
||||
},
|
||||
{
|
||||
"name": "symfony/property-access",
|
||||
"version": "v2.7.6",
|
||||
"version": "v2.7.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/property-access.git",
|
||||
"reference": "368b784738fa932e6d86866038312b03e073a824"
|
||||
"reference": "49d76463a54d8b3005fa58f3b8df41d0ae206eaa"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/property-access/zipball/368b784738fa932e6d86866038312b03e073a824",
|
||||
"reference": "368b784738fa932e6d86866038312b03e073a824",
|
||||
"url": "https://api.github.com/repos/symfony/property-access/zipball/49d76463a54d8b3005fa58f3b8df41d0ae206eaa",
|
||||
"reference": "49d76463a54d8b3005fa58f3b8df41d0ae206eaa",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2633,7 +2823,10 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\PropertyAccess\\": ""
|
||||
}
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@ -2662,20 +2855,20 @@
|
||||
"property path",
|
||||
"reflection"
|
||||
],
|
||||
"time": "2015-10-23 14:47:27"
|
||||
"time": "2015-11-18 13:41:01"
|
||||
},
|
||||
{
|
||||
"name": "symfony/routing",
|
||||
"version": "v2.7.6",
|
||||
"version": "v2.7.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/routing.git",
|
||||
"reference": "f353e1f588679c3ec987624e6c617646bd01ba38"
|
||||
"reference": "7450f6196711b124fb8b04a12286d01a0401ddfe"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/routing/zipball/f353e1f588679c3ec987624e6c617646bd01ba38",
|
||||
"reference": "f353e1f588679c3ec987624e6c617646bd01ba38",
|
||||
"url": "https://api.github.com/repos/symfony/routing/zipball/7450f6196711b124fb8b04a12286d01a0401ddfe",
|
||||
"reference": "7450f6196711b124fb8b04a12286d01a0401ddfe",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2708,7 +2901,10 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Routing\\": ""
|
||||
}
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@ -2732,85 +2928,25 @@
|
||||
"uri",
|
||||
"url"
|
||||
],
|
||||
"time": "2015-10-27 15:38:06"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
"version": "v2.7.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation.git",
|
||||
"reference": "6ccd9289ec1c71d01a49d83480de3b5293ce30c8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/6ccd9289ec1c71d01a49d83480de3b5293ce30c8",
|
||||
"reference": "6ccd9289ec1c71d01a49d83480de3b5293ce30c8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.9"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/config": "<2.7"
|
||||
},
|
||||
"require-dev": {
|
||||
"psr/log": "~1.0",
|
||||
"symfony/config": "~2.7",
|
||||
"symfony/intl": "~2.4",
|
||||
"symfony/yaml": "~2.2"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/log": "To use logging capability in translator",
|
||||
"symfony/config": "",
|
||||
"symfony/yaml": ""
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.7-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Translation\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Translation Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-10-27 15:38:06"
|
||||
"time": "2015-11-18 13:41:01"
|
||||
},
|
||||
{
|
||||
"name": "symfony/twig-bridge",
|
||||
"version": "v2.7.6",
|
||||
"version": "v2.7.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/twig-bridge.git",
|
||||
"reference": "3dd44937b1e08af8c8f6b14850f4b9c4d1039c6f"
|
||||
"reference": "7c491aa71af4320747f81ab0140eac4f0ad5509b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/twig-bridge/zipball/3dd44937b1e08af8c8f6b14850f4b9c4d1039c6f",
|
||||
"reference": "3dd44937b1e08af8c8f6b14850f4b9c4d1039c6f",
|
||||
"url": "https://api.github.com/repos/symfony/twig-bridge/zipball/7c491aa71af4320747f81ab0140eac4f0ad5509b",
|
||||
"reference": "7c491aa71af4320747f81ab0140eac4f0ad5509b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.9",
|
||||
"twig/twig": "~1.20|~2.0"
|
||||
"twig/twig": "~1.23|~2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/asset": "~2.7",
|
||||
@ -2852,7 +2988,10 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Bridge\\Twig\\": ""
|
||||
}
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@ -2870,20 +3009,20 @@
|
||||
],
|
||||
"description": "Symfony Twig Bridge",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-10-11 09:39:48"
|
||||
"time": "2015-11-02 20:25:31"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v2.7.6",
|
||||
"version": "v2.7.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "eca9019c88fbe250164affd107bc8057771f3f4d"
|
||||
"reference": "4cfcd7a9fceba662b3c036b7d9a91f6197af046c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/eca9019c88fbe250164affd107bc8057771f3f4d",
|
||||
"reference": "eca9019c88fbe250164affd107bc8057771f3f4d",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/4cfcd7a9fceba662b3c036b7d9a91f6197af046c",
|
||||
"reference": "4cfcd7a9fceba662b3c036b7d9a91f6197af046c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2898,7 +3037,10 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Yaml\\": ""
|
||||
}
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@ -2916,7 +3058,7 @@
|
||||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-10-11 09:39:48"
|
||||
"time": "2015-11-18 13:41:01"
|
||||
},
|
||||
{
|
||||
"name": "twig/extensions",
|
||||
|
@ -77,11 +77,16 @@ class Env {
|
||||
|
||||
static function isPluginActivated() {
|
||||
$activatesPlugins = get_option('active_plugins');
|
||||
$isActivated =
|
||||
$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;
|
||||
}
|
||||
}
|
@ -38,5 +38,19 @@ class Hooks {
|
||||
'\MailPoet\Segments\WP::synchronizeUser',
|
||||
1
|
||||
);
|
||||
|
||||
add_filter(
|
||||
'image_size_names_choose',
|
||||
array(
|
||||
$this,
|
||||
'appendImageSizes'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function appendImageSizes($sizes) {
|
||||
return array_merge($sizes, array(
|
||||
'mailpoet_newsletter_max' => __('MailPoet Newsletter'),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
namespace MailPoet\Config;
|
||||
|
||||
use MailPoet\Models;
|
||||
use MailPoet\Queue\Supervisor;
|
||||
use MailPoet\Cron\Supervisor;
|
||||
use MailPoet\Router;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
@ -29,6 +29,7 @@ class Initializer {
|
||||
$this->setupPublicAPI();
|
||||
$this->runQueueSupervisor();
|
||||
$this->setupHooks();
|
||||
$this->setupImages();
|
||||
}
|
||||
|
||||
function setupDB() {
|
||||
@ -55,7 +56,7 @@ class Initializer {
|
||||
$subscriber_custom_field = Env::$db_prefix . 'subscriber_custom_field';
|
||||
$newsletter_option_fields = Env::$db_prefix . 'newsletter_option_fields';
|
||||
$newsletter_option = Env::$db_prefix . 'newsletter_option';
|
||||
$queues = Env::$db_prefix . 'queues';
|
||||
$sending_queues = Env::$db_prefix . 'sending_queues';
|
||||
$newsletter_statistics = Env::$db_prefix . 'newsletter_statistics';
|
||||
|
||||
define('MP_SUBSCRIBERS_TABLE', $subscribers);
|
||||
@ -72,7 +73,7 @@ class Initializer {
|
||||
define('MP_SUBSCRIBER_CUSTOM_FIELD_TABLE', $subscriber_custom_field);
|
||||
define('MP_NEWSLETTER_OPTION_FIELDS_TABLE', $newsletter_option_fields);
|
||||
define('MP_NEWSLETTER_OPTION_TABLE', $newsletter_option);
|
||||
define('MP_QUEUES_TABLE', $queues);
|
||||
define('MP_SENDING_QUEUE_TABLE', $sending_queues);
|
||||
define('MP_NEWSLETTER_STATISTICS_TABLE', $newsletter_statistics);
|
||||
}
|
||||
|
||||
@ -128,7 +129,7 @@ class Initializer {
|
||||
$hooks = new Hooks();
|
||||
$hooks->init();
|
||||
}
|
||||
|
||||
|
||||
function setupPublicAPI() {
|
||||
$publicAPI = new PublicAPI();
|
||||
$publicAPI->init();
|
||||
@ -140,4 +141,8 @@ class Initializer {
|
||||
$supervisor->checkDaemon();
|
||||
} catch (\Exception $e) {}
|
||||
}
|
||||
}
|
||||
|
||||
function setupImages() {
|
||||
add_image_size('mailpoet_newsletter_max', 1320);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ namespace MailPoet\Config;
|
||||
|
||||
use MailPoet\Form\Block;
|
||||
use MailPoet\Form\Renderer as FormRenderer;
|
||||
use MailPoet\Models\CustomField;
|
||||
use MailPoet\Models\Form;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Models\Setting;
|
||||
@ -172,13 +173,13 @@ class Menu {
|
||||
|
||||
add_submenu_page(
|
||||
'mailpoet',
|
||||
__('Queue'),
|
||||
__('Queue'),
|
||||
__('Cron'),
|
||||
__('Cron'),
|
||||
'manage_options',
|
||||
'mailpoet-queue',
|
||||
'mailpoet-cron',
|
||||
array(
|
||||
$this,
|
||||
'queue'
|
||||
'cron'
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -325,17 +326,22 @@ class Menu {
|
||||
$data = array();
|
||||
|
||||
$data['segments'] = Segment::findArray();
|
||||
$settings = Setting::findArray();
|
||||
$data['settings'] = array();
|
||||
foreach ($settings as $setting) {
|
||||
$data['settings'][$setting['name']] = $setting['value'];
|
||||
}
|
||||
$data['settings'] = Setting::getAll();
|
||||
$data['roles'] = $wp_roles->get_names();
|
||||
echo $this->renderer->render('newsletters.html', $data);
|
||||
}
|
||||
|
||||
function newletterEditor() {
|
||||
$data = array();
|
||||
$custom_fields = array_map(function($field) {
|
||||
return array(
|
||||
'text' => $field['name'],
|
||||
'shortcode' => 'field:' . $field['id'],
|
||||
);
|
||||
}, CustomField::findArray());
|
||||
|
||||
$data = array(
|
||||
'customFields' => $custom_fields,
|
||||
);
|
||||
wp_enqueue_media();
|
||||
wp_enqueue_script('tinymce-wplink', includes_url('js/tinymce/plugins/wplink/plugin.js'));
|
||||
wp_enqueue_style('editor', includes_url('css/editor.css'));
|
||||
@ -364,7 +370,7 @@ class Menu {
|
||||
$data = array(
|
||||
'form' => $form,
|
||||
'pages' => Pages::getAll(),
|
||||
'segments' => Segment::getPublished()
|
||||
'segments' => Segment::getPublic()
|
||||
->findArray(),
|
||||
'styles' => FormRenderer::getStyles($form),
|
||||
'date_types' => Block\Date::getDateTypes(),
|
||||
@ -374,9 +380,9 @@ class Menu {
|
||||
echo $this->renderer->render('form/editor.html', $data);
|
||||
}
|
||||
|
||||
function queue() {
|
||||
$daemon = new \MailPoet\Queue\BootStrapMenu();
|
||||
function cron() {
|
||||
$daemon = new \MailPoet\Cron\BootStrapMenu();
|
||||
$data['daemon'] = json_encode($daemon->bootstrap());
|
||||
echo $this->renderer->render('queue.html', $data);
|
||||
echo $this->renderer->render('cron.html', $data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ class Migrator {
|
||||
'subscriber_custom_field',
|
||||
'newsletter_option_fields',
|
||||
'newsletter_option',
|
||||
'queues',
|
||||
'sending_queues',
|
||||
'newsletter_statistics',
|
||||
'forms'
|
||||
);
|
||||
@ -84,6 +84,10 @@ class Migrator {
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'subject varchar(250) NOT NULL,',
|
||||
'type varchar(20) NOT NULL DEFAULT "standard",',
|
||||
'sender_address varchar(150) NOT NULL,',
|
||||
'sender_name varchar(150) NOT NULL,',
|
||||
'reply_to_address varchar(150) NOT NULL,',
|
||||
'reply_to_name varchar(150) NOT NULL,',
|
||||
'preheader varchar(250) NOT NULL,',
|
||||
'body longtext,',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
@ -99,8 +103,9 @@ class Migrator {
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'name varchar(250) NOT NULL,',
|
||||
'description varchar(250) NOT NULL,',
|
||||
'body longtext,',
|
||||
'thumbnail longtext,',
|
||||
'body LONGTEXT,',
|
||||
'thumbnail LONGTEXT,',
|
||||
'readonly TINYINT(1) DEFAULT 0',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'PRIMARY KEY (id)'
|
||||
@ -205,12 +210,12 @@ class Migrator {
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function queues() {
|
||||
function sending_queues() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'newsletter_id mediumint(9) NOT NULL,',
|
||||
'subscribers longtext,',
|
||||
'status varchar(12) NOT NULL,',
|
||||
'status varchar(12) NULL DEFAULT NULL,',
|
||||
'priority mediumint(9) NOT NULL DEFAULT 0,',
|
||||
'count_total mediumint(9) NOT NULL DEFAULT 0,',
|
||||
'count_processed mediumint(9) NOT NULL DEFAULT 0,',
|
||||
@ -265,4 +270,4 @@ class Migrator {
|
||||
|
||||
return implode("\n", $sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,129 +1,166 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
|
||||
use MailPoet\Config\PopulatorData\Templates\SampleTemplate;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
||||
|
||||
class Populator {
|
||||
function __construct() {
|
||||
$this->prefix = Env::$db_prefix;
|
||||
$this->models = array(
|
||||
'newsletter_option_fields',
|
||||
'newsletter_templates',
|
||||
);
|
||||
}
|
||||
|
||||
function up() {
|
||||
global $wpdb;
|
||||
|
||||
$_this = $this;
|
||||
|
||||
$populate = function($model) use($_this, $wpdb) {
|
||||
$fields = $_this->$model();
|
||||
$table = $_this->prefix . $model;
|
||||
|
||||
array_map(function($field) use ($wpdb, $table) {
|
||||
$column_conditions = array_map(function($key) use ($field) {
|
||||
return $key . '=' . $field[$key];
|
||||
}, $field);
|
||||
if ($wpdb->get_var("SELECT COUNT(*) FROM " . $table . " WHERE " . implode(' AND ', $column_conditions)) === 0) {
|
||||
$wpdb->insert(
|
||||
$table,
|
||||
$field
|
||||
);
|
||||
}
|
||||
}, $fields);
|
||||
};
|
||||
|
||||
array_map(array($this, 'populate'), $this->models);
|
||||
}
|
||||
|
||||
function newsletter_option_fields() {
|
||||
return array(
|
||||
array(
|
||||
'name' => 'event',
|
||||
'newsletter_type' => 'welcome',
|
||||
),
|
||||
array(
|
||||
'name' => 'segment',
|
||||
'newsletter_type' => 'welcome',
|
||||
),
|
||||
array(
|
||||
'name' => 'role',
|
||||
'newsletter_type' => 'welcome',
|
||||
),
|
||||
array(
|
||||
'name' => 'afterTimeNumber',
|
||||
'newsletter_type' => 'welcome',
|
||||
),
|
||||
array(
|
||||
'name' => 'afterTimeType',
|
||||
'newsletter_type' => 'welcome',
|
||||
),
|
||||
|
||||
array(
|
||||
'name' => 'intervalType',
|
||||
'newsletter_type' => 'notification',
|
||||
),
|
||||
array(
|
||||
'name' => 'timeOfDay',
|
||||
'newsletter_type' => 'notification',
|
||||
),
|
||||
array(
|
||||
'name' => 'weekDay',
|
||||
'newsletter_type' => 'notification',
|
||||
),
|
||||
array(
|
||||
'name' => 'monthDay',
|
||||
'newsletter_type' => 'notification',
|
||||
),
|
||||
array(
|
||||
'name' => 'nthWeekDay',
|
||||
'newsletter_type' => 'notification',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
private function newsletter_templates() {
|
||||
return array(
|
||||
(new SampleTemplate(Env::$assets_url))->get(),
|
||||
);
|
||||
}
|
||||
|
||||
private function populate($model) {
|
||||
$rows = $this->$model();
|
||||
$table = $this->prefix . $model;
|
||||
$_this = $this;
|
||||
|
||||
array_map(function($row) use ($_this, $table) {
|
||||
if (!$_this->rowExists($table, $row)) {
|
||||
$_this->insertRow($table, $row);
|
||||
}
|
||||
}, $rows);
|
||||
}
|
||||
|
||||
private function rowExists($table, $columns) {
|
||||
global $wpdb;
|
||||
|
||||
$conditions = array_map(function($key) use ($columns) {
|
||||
return $key . '=%s';
|
||||
}, array_keys($columns));
|
||||
|
||||
return $wpdb->get_var($wpdb->prepare(
|
||||
"SELECT COUNT(*) FROM $table WHERE " . implode(' AND ', $conditions),
|
||||
array_values($columns)
|
||||
)) > 0;
|
||||
}
|
||||
|
||||
private function insertRow($table, $row) {
|
||||
global $wpdb;
|
||||
|
||||
return $wpdb->insert(
|
||||
$table,
|
||||
$row
|
||||
);
|
||||
}
|
||||
}
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
|
||||
use MailPoet\Config\PopulatorData\Templates\FranksRoastHouseTemplate;
|
||||
use MailPoet\Config\PopulatorData\Templates\BlankTemplate;
|
||||
use \MailPoet\Models\Segment;
|
||||
use \MailPoet\Segments\WP;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
||||
|
||||
class Populator {
|
||||
function __construct() {
|
||||
$this->prefix = Env::$db_prefix;
|
||||
$this->models = array(
|
||||
'newsletter_option_fields',
|
||||
'newsletter_templates',
|
||||
);
|
||||
}
|
||||
|
||||
function up() {
|
||||
global $wpdb;
|
||||
|
||||
$_this = $this;
|
||||
|
||||
$populate = function($model) use($_this, $wpdb) {
|
||||
$fields = $_this->$model();
|
||||
$table = $_this->prefix . $model;
|
||||
|
||||
array_map(function($field) use ($wpdb, $table) {
|
||||
$column_conditions = array_map(function($key) use ($field) {
|
||||
return $key . '=' . $field[$key];
|
||||
}, $field);
|
||||
if ($wpdb->get_var("SELECT COUNT(*) FROM " . $table . " WHERE " . implode(' AND ', $column_conditions)) === 0) {
|
||||
$wpdb->insert(
|
||||
$table,
|
||||
$field
|
||||
);
|
||||
}
|
||||
}, $fields);
|
||||
};
|
||||
|
||||
array_map(array($this, 'populate'), $this->models);
|
||||
|
||||
$this->createDefaultSegments();
|
||||
}
|
||||
|
||||
private function createDefaultSegments() {
|
||||
// WP Users segment
|
||||
$wp_users_segment = Segment::getWPUsers();
|
||||
|
||||
if($wp_users_segment === false) {
|
||||
// create the wp users list
|
||||
$wp_users_segment = Segment::create();
|
||||
$wp_users_segment->hydrate(array(
|
||||
'name' => __('WordPress Users'),
|
||||
'description' =>
|
||||
__('The list containing all of your WordPress users.'),
|
||||
'type' => 'wp_users'
|
||||
));
|
||||
$wp_users_segment->save();
|
||||
}
|
||||
|
||||
// Synchronize WP Users
|
||||
WP::synchronizeUsers();
|
||||
|
||||
// Default segment
|
||||
if(Segment::where('type', 'default')->count() === 0) {
|
||||
$default_segment = Segment::create();
|
||||
$default_segment->hydrate(array(
|
||||
'name' => __('My First List'),
|
||||
'description' =>
|
||||
__('The list created automatically on install of MailPoet')
|
||||
));
|
||||
$default_segment->save();
|
||||
}
|
||||
}
|
||||
|
||||
function newsletter_option_fields() {
|
||||
return array(
|
||||
array(
|
||||
'name' => 'event',
|
||||
'newsletter_type' => 'welcome',
|
||||
),
|
||||
array(
|
||||
'name' => 'segment',
|
||||
'newsletter_type' => 'welcome',
|
||||
),
|
||||
array(
|
||||
'name' => 'role',
|
||||
'newsletter_type' => 'welcome',
|
||||
),
|
||||
array(
|
||||
'name' => 'afterTimeNumber',
|
||||
'newsletter_type' => 'welcome',
|
||||
),
|
||||
array(
|
||||
'name' => 'afterTimeType',
|
||||
'newsletter_type' => 'welcome',
|
||||
),
|
||||
|
||||
array(
|
||||
'name' => 'intervalType',
|
||||
'newsletter_type' => 'notification',
|
||||
),
|
||||
array(
|
||||
'name' => 'timeOfDay',
|
||||
'newsletter_type' => 'notification',
|
||||
),
|
||||
array(
|
||||
'name' => 'weekDay',
|
||||
'newsletter_type' => 'notification',
|
||||
),
|
||||
array(
|
||||
'name' => 'monthDay',
|
||||
'newsletter_type' => 'notification',
|
||||
),
|
||||
array(
|
||||
'name' => 'nthWeekDay',
|
||||
'newsletter_type' => 'notification',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
private function newsletter_templates() {
|
||||
return array(
|
||||
(new FranksRoastHouseTemplate(Env::$assets_url))->get(),
|
||||
(new BlankTemplate(Env::$assets_url))->get(),
|
||||
);
|
||||
}
|
||||
|
||||
private function populate($model) {
|
||||
$rows = $this->$model();
|
||||
$table = $this->prefix . $model;
|
||||
$_this = $this;
|
||||
|
||||
array_map(function($row) use ($_this, $table) {
|
||||
if (!$_this->rowExists($table, $row)) {
|
||||
$_this->insertRow($table, $row);
|
||||
}
|
||||
}, $rows);
|
||||
}
|
||||
|
||||
private function rowExists($table, $columns) {
|
||||
global $wpdb;
|
||||
|
||||
$conditions = array_map(function($key) use ($columns) {
|
||||
return $key . '=%s';
|
||||
}, array_keys($columns));
|
||||
|
||||
return $wpdb->get_var($wpdb->prepare(
|
||||
"SELECT COUNT(*) FROM $table WHERE " . implode(' AND ', $conditions),
|
||||
array_values($columns)
|
||||
)) > 0;
|
||||
}
|
||||
|
||||
private function insertRow($table, $row) {
|
||||
global $wpdb;
|
||||
|
||||
return $wpdb->insert(
|
||||
$table,
|
||||
$row
|
||||
);
|
||||
}
|
||||
}
|
||||
|
215
lib/Config/PopulatorData/Templates/BlankTemplate.php
Normal file
215
lib/Config/PopulatorData/Templates/BlankTemplate.php
Normal file
File diff suppressed because one or more lines are too long
350
lib/Config/PopulatorData/Templates/FranksRoastHouseTemplate.php
Normal file
350
lib/Config/PopulatorData/Templates/FranksRoastHouseTemplate.php
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
|
||||
use MailPoet\Queue\Daemon;
|
||||
use MailPoet\Cron\Daemon;
|
||||
use MailPoet\Util\Helpers;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
@ -61,19 +61,25 @@ class Widget {
|
||||
}
|
||||
|
||||
function setupAdminDependencies() {
|
||||
wp_enqueue_script('mailpoet_vendor',
|
||||
Env::$assets_url.'/js/vendor.js',
|
||||
array(),
|
||||
Env::$version,
|
||||
true
|
||||
);
|
||||
if(
|
||||
empty($_GET['page'])
|
||||
or
|
||||
isset($_GET['page']) && strpos($_GET['page'], 'mailpoet') === false
|
||||
) {
|
||||
wp_enqueue_script('mailpoet_vendor',
|
||||
Env::$assets_url.'/js/vendor.js',
|
||||
array(),
|
||||
Env::$version,
|
||||
true
|
||||
);
|
||||
|
||||
wp_enqueue_script('mailpoet_admin',
|
||||
Env::$assets_url.'/js/mailpoet.js',
|
||||
array(),
|
||||
Env::$version,
|
||||
true
|
||||
);
|
||||
wp_enqueue_script('mailpoet_admin',
|
||||
Env::$assets_url.'/js/mailpoet.js',
|
||||
array(),
|
||||
Env::$version,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function setupActions() {
|
||||
|
@ -1,33 +1,33 @@
|
||||
<?php
|
||||
namespace MailPoet\Queue;
|
||||
namespace MailPoet\Cron;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use MailPoet\Models\Queue;
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
class BootStrapMenu {
|
||||
function __construct() {
|
||||
$this->daemon = Setting::where('name', 'daemon')
|
||||
$this->daemon = Setting::where('name', 'cron_daemon')
|
||||
->findOne();
|
||||
}
|
||||
|
||||
function bootStrap() {
|
||||
$queues = Queue::findMany();
|
||||
return ($this->daemon) ?
|
||||
array_merge(
|
||||
array(
|
||||
'time_since_start' =>
|
||||
'timeSinceStart' =>
|
||||
Carbon::createFromFormat(
|
||||
'Y-m-d H:i:s',
|
||||
$this->daemon->created_at,
|
||||
'UTC'
|
||||
)->diffForHumans(),
|
||||
'time_since_update' =>
|
||||
)
|
||||
->diffForHumans(),
|
||||
'timeSinceUpdate' =>
|
||||
Carbon::createFromFormat(
|
||||
'Y-m-d H:i:s',
|
||||
$this->daemon->updated_at,
|
||||
'UTC'
|
||||
)->diffForHumans()
|
||||
)
|
||||
->diffForHumans()
|
||||
),
|
||||
json_decode($this->daemon->value, true)
|
||||
) :
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\Queue;
|
||||
namespace MailPoet\Cron;
|
||||
|
||||
use MailPoet\Cron\Workers\SendingQueue;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Util\Security;
|
||||
|
||||
@ -17,7 +18,7 @@ class Daemon {
|
||||
$this->payload = $payload;
|
||||
$this->timer = microtime(true);
|
||||
}
|
||||
|
||||
|
||||
function start() {
|
||||
if(!isset($this->payload['session'])) {
|
||||
$this->abortWithError('missing session ID');
|
||||
@ -27,33 +28,32 @@ class Daemon {
|
||||
$daemonData = $this->daemonData;
|
||||
if(!$daemon) {
|
||||
$daemon = Setting::create();
|
||||
$daemon->name = 'daemon';
|
||||
$daemon->value = json_encode(array('status' => 'stopped'));
|
||||
$daemon->name = 'cron_daemon';
|
||||
$daemonData = array(
|
||||
'status' => null,
|
||||
'counter' => 0
|
||||
);
|
||||
$daemon->value = json_encode($daemonData);
|
||||
$daemon->save();
|
||||
}
|
||||
if($daemonData['status'] !== 'started') {
|
||||
$_SESSION['daemon'] = 'started';
|
||||
$daemonData = array(
|
||||
'status' => 'started',
|
||||
'token' => $this->refreshedToken,
|
||||
'counter' => ($daemonData['status'] === 'paused') ?
|
||||
$daemonData['counter'] :
|
||||
0
|
||||
);
|
||||
$_SESSION['daemon'] = array('result' => true);
|
||||
$_SESSION['cron_daemon'] = 'started';
|
||||
$daemonData['status'] = 'started';
|
||||
$daemonData['token'] = $this->refreshedToken;
|
||||
$_SESSION['cron_daemon'] = array('result' => true);
|
||||
$this->manageSession('end');
|
||||
$daemon->value = json_encode($daemonData);
|
||||
$daemon->save();
|
||||
$this->callSelf();
|
||||
} else {
|
||||
$_SESSION['daemon'] = array(
|
||||
$_SESSION['cron_daemon'] = array(
|
||||
'result' => false,
|
||||
'error' => 'already started'
|
||||
);
|
||||
}
|
||||
$this->manageSession('end');
|
||||
}
|
||||
|
||||
|
||||
function run() {
|
||||
if(!$this->daemon || $this->daemonData['status'] !== 'started') {
|
||||
$this->abortWithError('not running');
|
||||
@ -63,11 +63,15 @@ class Daemon {
|
||||
) {
|
||||
$this->abortWithError('invalid token');
|
||||
}
|
||||
|
||||
$worker = new Worker();
|
||||
$worker->process();
|
||||
|
||||
try {
|
||||
$sendingQueue = new SendingQueue($this->timer);
|
||||
$sendingQueue->process();
|
||||
} catch(Exception $e) {
|
||||
}
|
||||
|
||||
$elapsedTime = microtime(true) - $this->timer;
|
||||
if ($elapsedTime < 30) {
|
||||
if($elapsedTime < 30) {
|
||||
sleep(30 - $elapsedTime);
|
||||
}
|
||||
|
||||
@ -77,11 +81,11 @@ class Daemon {
|
||||
$daemonData['token'] = $this->refreshedToken;
|
||||
$daemon->value = json_encode($daemonData);
|
||||
$daemon->save();
|
||||
$this->callSelf();
|
||||
if($daemonData['status'] === 'strated') $this->callSelf();
|
||||
}
|
||||
|
||||
function getDaemon() {
|
||||
$daemon = Setting::where('name', 'daemon')
|
||||
$daemon = Setting::where('name', 'cron_daemon')
|
||||
->findOne();
|
||||
return array(
|
||||
($daemon) ? $daemon : null,
|
||||
@ -90,11 +94,11 @@ class Daemon {
|
||||
}
|
||||
|
||||
function refreshToken() {
|
||||
return Security::generateRandomString(5);
|
||||
return Security::generateRandomString();
|
||||
}
|
||||
|
||||
function manageSession($action) {
|
||||
switch ($action) {
|
||||
switch($action) {
|
||||
case 'start':
|
||||
if(session_id()) {
|
||||
session_write_close();
|
||||
@ -107,7 +111,7 @@ class Daemon {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function callSelf() {
|
||||
$payload = json_encode(array('token' => $this->refreshedToken));
|
||||
Supervisor::getRemoteUrl(
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace MailPoet\Queue;
|
||||
namespace MailPoet\Cron;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use MailPoet\Config\Env;
|
||||
@ -17,48 +17,43 @@ class Supervisor {
|
||||
}
|
||||
|
||||
function checkDaemon() {
|
||||
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH'])) return;
|
||||
if(!$this->daemon) {
|
||||
return $this->startDaemon();
|
||||
} else {
|
||||
if(!$this->forceStart && ($this->daemonData['status'] === 'paused' ||
|
||||
$this->daemonData['status'] === 'stopped'
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
$currentTime = Carbon::now('UTC');
|
||||
$lastUpdateTime = Carbon::createFromFormat(
|
||||
'Y-m-d H:i:s',
|
||||
$this->daemon->updated_at, 'UTC'
|
||||
);
|
||||
$timeSinceLastStart = $currentTime->diffInSeconds($lastUpdateTime);
|
||||
if($timeSinceLastStart < 50) return;
|
||||
$this->daemonData['status'] = 'paused';
|
||||
$this->daemon->value = json_encode($this->daemonData);
|
||||
$this->daemon->save();
|
||||
return $this->startDaemon();
|
||||
}
|
||||
if(!$this->forceStart && $this->daemonData['status'] === 'stopped') {
|
||||
return;
|
||||
}
|
||||
$currentTime = Carbon::now('UTC');
|
||||
$lastUpdateTime = Carbon::createFromFormat(
|
||||
'Y-m-d H:i:s',
|
||||
$this->daemon->updated_at, 'UTC'
|
||||
);
|
||||
$timeSinceLastStart = $currentTime->diffInSeconds($lastUpdateTime);
|
||||
if($timeSinceLastStart < 40) return;
|
||||
$this->daemonData['status'] = null;
|
||||
$this->daemon->value = json_encode($this->daemonData);
|
||||
$this->daemon->save();
|
||||
return $this->startDaemon();
|
||||
}
|
||||
|
||||
function startDaemon() {
|
||||
if(!session_id()) session_start();
|
||||
$sessionId = session_id();
|
||||
session_write_close();
|
||||
$_SESSION['daemon'] = null;
|
||||
$_SESSION['cron_daemon'] = null;
|
||||
$payload = json_encode(array('session' => $sessionId));
|
||||
self::getRemoteUrl(
|
||||
'/?mailpoet-api§ion=queue&action=start&payload=' . urlencode($payload)
|
||||
);
|
||||
session_start();
|
||||
$daemonStatus = $_SESSION['daemon'];
|
||||
$daemonStatus = $_SESSION['cron_daemon'];
|
||||
unset($_SESSION['daemon']);
|
||||
session_write_close();
|
||||
return $daemonStatus;
|
||||
}
|
||||
|
||||
function getDaemon() {
|
||||
$daemon = Setting::where('name', 'daemon')
|
||||
$daemon = Setting::where('name', 'cron_daemon')
|
||||
->findOne();
|
||||
$daemonData = ($daemon) ? json_decode($daemon->value, true) : false;
|
||||
return array(
|
114
lib/Cron/Workers/SendingQueue.php
Normal file
114
lib/Cron/Workers/SendingQueue.php
Normal file
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
namespace MailPoet\Cron\Workers;
|
||||
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\NewsletterStatistics;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Newsletter\Renderer\Renderer;
|
||||
use MailPoet\Router\Mailer;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class SendingQueue {
|
||||
function __construct($timer = false) {
|
||||
$this->timer = ($timer) ? $timer : microtime(true);
|
||||
}
|
||||
|
||||
function process() {
|
||||
$queues =
|
||||
\MailPoet\Models\SendingQueue::orderByDesc('priority')
|
||||
->whereNull('deleted_at')
|
||||
->whereNull('status')
|
||||
->findResultSet();
|
||||
foreach($queues as $queue) {
|
||||
$newsletter = Newsletter::findOne($queue->newsletter_id);
|
||||
if(!$newsletter) {
|
||||
continue;
|
||||
};
|
||||
$newsletter = $newsletter->asArray();
|
||||
$mailer = new Mailer($httpRequest = false);
|
||||
if(!empty($newsletter['sender_address']) &&
|
||||
!empty($newsletter['sender_name'])
|
||||
) {
|
||||
$mailer->fromName = $newsletter['sender_name'];
|
||||
$mailer->fromEmail = $newsletter['sender_address'];
|
||||
$mailer->fromNameEmail = sprintf(
|
||||
'%s <%s>',
|
||||
$mailer->fromName,
|
||||
$mailer->fromEmail
|
||||
);
|
||||
}
|
||||
if(!empty($newsletter['reply_to_address']) &&
|
||||
!empty($newsletter['reply_to_name'])
|
||||
) {
|
||||
$mailer->replyToName = $newsletter['reply_to_name'];
|
||||
$mailer->replyToEmail = $newsletter['reply_to_address'];
|
||||
$mailer->replyToNameEmail = sprintf(
|
||||
'%s <%s>',
|
||||
$mailer->replyToName,
|
||||
$mailer->replyToEmail
|
||||
);
|
||||
}
|
||||
$mailer->mailer = $mailer->buildMailer();
|
||||
$renderer = new Renderer(json_decode($newsletter['body'], true));
|
||||
$newsletter = array(
|
||||
'subject' => $newsletter['subject'],
|
||||
'id' => $newsletter['id'],
|
||||
'body' => array(
|
||||
'html' => $renderer->renderAll(),
|
||||
'text' => ''
|
||||
// TODO: add text body
|
||||
)
|
||||
);
|
||||
$subscribers = json_decode($queue->subscribers, true);
|
||||
$subscribersToProcess = $subscribers['to_process'];
|
||||
if(!isset($subscribers['failed'])) $subscribers['failed'] = array();
|
||||
if(!isset($subscribers['processed'])) $subscribers['processed'] = array();
|
||||
foreach(array_chunk($subscribersToProcess, 200) as $subscriberIds) {
|
||||
$dbSubscribers = Subscriber::whereIn('id', $subscriberIds)
|
||||
->findArray();
|
||||
foreach($dbSubscribers as $i => $dbSubscriber) {
|
||||
$this->checkExecutionTimer();
|
||||
// TODO: replace shortcodes in the newsletter
|
||||
$result = $mailer->mailer->send(
|
||||
$newsletter,
|
||||
$mailer->transformSubscriber($dbSubscriber)
|
||||
);
|
||||
$newsletterStatistics = NewsletterStatistics::create();
|
||||
$newsletterStatistics->subscriber_id = $dbSubscriber['id'];
|
||||
$newsletterStatistics->newsletter_id = $newsletter['id'];
|
||||
$newsletterStatistics->queue_id = $queue->id;
|
||||
$newsletterStatistics->save();
|
||||
if($result) {
|
||||
$subscribers['processed'][] = $dbSubscriber['id'];
|
||||
} else {
|
||||
$subscribers['failed'][] = $dbSubscriber['id'];
|
||||
}
|
||||
$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 checkExecutionTimer() {
|
||||
$elapsedTime = microtime(true) - $this->timer;
|
||||
if($elapsedTime >= 28) throw new \Exception('Maximum execution time reached.');
|
||||
}
|
||||
}
|
@ -31,16 +31,21 @@ class AmazonSES {
|
||||
}
|
||||
|
||||
function getBody($newsletter, $subscriber) {
|
||||
return array(
|
||||
$body = array(
|
||||
'Action' => 'SendEmail',
|
||||
'Version' => '2010-12-01',
|
||||
'Source' => $this->from,
|
||||
'Destination.ToAddresses.member.1' => $subscriber,
|
||||
'Message.Subject.Data' => $newsletter['subject'],
|
||||
'Message.Body.Html.Data' => $newsletter['body']['html'],
|
||||
'Message.Body.Text.Data' => $newsletter['body']['text'],
|
||||
'ReturnPath' => $this->from
|
||||
);
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
$body['Message.Body.Html.Data'] = $newsletter['body']['html'];
|
||||
}
|
||||
if(!empty($newsletter['body']['text'])) {
|
||||
$body['Message.Body.Text.Data'] = $newsletter['body']['text'];
|
||||
}
|
||||
return $body;
|
||||
}
|
||||
|
||||
function request($newsletter, $subscriber) {
|
||||
|
@ -22,15 +22,20 @@ class ElasticEmail {
|
||||
}
|
||||
|
||||
function getBody($newsletter, $subscriber) {
|
||||
return array(
|
||||
$body = array(
|
||||
'api_key' => $this->apiKey,
|
||||
'from' => $this->fromEmail,
|
||||
'from_name' => $this->fromName,
|
||||
'to' => $subscriber,
|
||||
'subject' => $newsletter['subject'],
|
||||
'body_html' => $newsletter['body']['html'],
|
||||
'body_text' => $newsletter['body']['text']
|
||||
'subject' => $newsletter['subject']
|
||||
);
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
$body['body_html'] = $newsletter['body']['html'];
|
||||
}
|
||||
if(!empty($newsletter['body']['text'])) {
|
||||
$body['body_text'] = $newsletter['body']['text'];
|
||||
}
|
||||
return $body;
|
||||
}
|
||||
|
||||
function request($newsletter, $subscriber) {
|
||||
|
@ -22,13 +22,18 @@ class MailGun {
|
||||
}
|
||||
|
||||
function getBody($newsletter, $subscriber) {
|
||||
return array(
|
||||
$body = array(
|
||||
'from' => $this->from,
|
||||
'to' => $subscriber,
|
||||
'subject' => $newsletter['subject'],
|
||||
'html' => $newsletter['body']['html'],
|
||||
'text' => $newsletter['body']['text']
|
||||
'subject' => $newsletter['subject']
|
||||
);
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
$body['html'] = $newsletter['body']['html'];
|
||||
}
|
||||
if(!empty($newsletter['body']['text'])) {
|
||||
$body['text'] = $newsletter['body']['text'];
|
||||
}
|
||||
return $body;
|
||||
}
|
||||
|
||||
function auth() {
|
||||
|
@ -37,18 +37,23 @@ class Mandrill {
|
||||
}
|
||||
|
||||
function getBody($newsletter, $subscriber) {
|
||||
return array(
|
||||
$body = array(
|
||||
'key' => $this->apiKey,
|
||||
'message' => array(
|
||||
'from_email' => $this->fromEmail,
|
||||
'from_name' => $this->fromName,
|
||||
'to' => array($subscriber),
|
||||
'subject' => $newsletter['subject'],
|
||||
'html' => $newsletter['body']['html'],
|
||||
'text' => $newsletter['body']['text']
|
||||
'subject' => $newsletter['subject']
|
||||
),
|
||||
'async' => false,
|
||||
);
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
$body['message']['html'] = $newsletter['body']['html'];
|
||||
}
|
||||
if(!empty($newsletter['body']['text'])) {
|
||||
$body['message']['text'] = $newsletter['body']['text'];
|
||||
}
|
||||
return $body;
|
||||
}
|
||||
|
||||
function request($newsletter, $subscriber) {
|
||||
|
@ -25,14 +25,19 @@ class SendGrid {
|
||||
}
|
||||
|
||||
function getBody($newsletter, $subscriber) {
|
||||
return array(
|
||||
$body = array(
|
||||
'to' => $subscriber,
|
||||
'from' => $this->fromEmail,
|
||||
'fromname' => $this->fromName,
|
||||
'subject' => $newsletter['subject'],
|
||||
'html' => $newsletter['body']['html'],
|
||||
'text' => $newsletter['body']['text']
|
||||
'subject' => $newsletter['subject']
|
||||
);
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
$body['html'] = $newsletter['body']['html'];
|
||||
}
|
||||
if(!empty($newsletter['body']['text'])) {
|
||||
$body['text'] = $newsletter['body']['text'];
|
||||
}
|
||||
return $body;
|
||||
}
|
||||
|
||||
function auth() {
|
||||
|
@ -36,7 +36,7 @@ class MailPoet {
|
||||
}
|
||||
|
||||
function getBody($newsletter, $subscriber) {
|
||||
return array(
|
||||
$body = array(
|
||||
'to' => (array(
|
||||
'address' => $subscriber['email'],
|
||||
'name' => $subscriber['name']
|
||||
@ -45,10 +45,15 @@ class MailPoet {
|
||||
'address' => $this->fromEmail,
|
||||
'name' => $this->fromName
|
||||
)),
|
||||
'subject' => $newsletter['subject'],
|
||||
'html' => $newsletter['body']['html'],
|
||||
'text' => $newsletter['body']['text']
|
||||
'subject' => $newsletter['subject']
|
||||
);
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
$body['html'] = $newsletter['body']['html'];
|
||||
}
|
||||
if(!empty($newsletter['body']['text'])) {
|
||||
$body['text'] = $newsletter['body']['text'];
|
||||
}
|
||||
return $body;
|
||||
}
|
||||
|
||||
function auth() {
|
||||
|
@ -4,11 +4,13 @@ namespace MailPoet\Mailer;
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class SMTP {
|
||||
function __construct($host, $port, $authentication, $encryption,
|
||||
function __construct($host, $port, $authentication, $login = null, $password = null, $encryption,
|
||||
$fromEmail, $fromName) {
|
||||
$this->host = $host;
|
||||
$this->port = $port;
|
||||
$this->authentication = $authentication;
|
||||
$this->login = $login;
|
||||
$this->password = $password;
|
||||
$this->encryption = $encryption;
|
||||
$this->fromName = $fromName;
|
||||
$this->fromEmail = $fromEmail;
|
||||
@ -19,7 +21,8 @@ class SMTP {
|
||||
try {
|
||||
$message = $this->createMessage($newsletter, $subscriber);
|
||||
$result = $this->mailer->send($message);
|
||||
} catch (\Exception $e) {
|
||||
} catch(\Exception $e) {
|
||||
!d($e->getMessage());exit;
|
||||
$result = false;
|
||||
}
|
||||
return ($result === 1);
|
||||
@ -31,20 +34,25 @@ class SMTP {
|
||||
$transport->setTimeout(10);
|
||||
if($this->authentication) {
|
||||
$transport
|
||||
->setUsername($this->authentication['login'])
|
||||
->setPassword($this->authentication['password']);
|
||||
->setUsername($this->login)
|
||||
->setPassword($this->password);
|
||||
}
|
||||
return \Swift_Mailer::newInstance($transport);
|
||||
}
|
||||
|
||||
|
||||
function createMessage($newsletter, $subscriber) {
|
||||
return \Swift_Message::newInstance()
|
||||
$message = \Swift_Message::newInstance()
|
||||
->setFrom(array($this->fromEmail => $this->fromName))
|
||||
->setTo($this->processSubscriber($subscriber))
|
||||
->setSubject($newsletter['subject'])
|
||||
->setBody($newsletter['body']['html'], 'text/html')
|
||||
->addPart($newsletter['body']['text'], 'text/plain');
|
||||
->setSubject($newsletter['subject']);
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
$message = $message->setBody($newsletter['body']['html'], 'text/html');
|
||||
}
|
||||
if(!empty($newsletter['body']['text'])) {
|
||||
$message = $message->addPart($newsletter['body']['text'], 'text/plain');
|
||||
}
|
||||
return $message;
|
||||
}
|
||||
|
||||
function processSubscriber($subscriber) {
|
||||
|
@ -20,7 +20,7 @@ class WPMail {
|
||||
}
|
||||
|
||||
function addFilters() {
|
||||
foreach ($this->filters as $filter => $method) {
|
||||
foreach($this->filters as $filter => $method) {
|
||||
add_filter($filter, array(
|
||||
$this,
|
||||
$method
|
||||
@ -29,7 +29,7 @@ class WPMail {
|
||||
}
|
||||
|
||||
function removeFilters() {
|
||||
foreach ($this->filters as $filter => $method) {
|
||||
foreach($this->filters as $filter => $method) {
|
||||
remove_filter($filter, array(
|
||||
$this,
|
||||
$method
|
||||
@ -51,7 +51,10 @@ class WPMail {
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
$this->addFilters();
|
||||
$result = wp_mail($subscriber, $newsletter['subject'], $newsletter['body']['html']);
|
||||
$result = wp_mail(
|
||||
$subscriber, $newsletter['subject'],
|
||||
(!empty($newsletter['body']['html'])) ? $newsletter['body']['html'] : $newsletter['body']['text']
|
||||
);
|
||||
$this->removeFilters();
|
||||
return ($result === true);
|
||||
}
|
||||
|
@ -43,6 +43,12 @@ class Newsletter extends Model {
|
||||
)->select_expr(MP_NEWSLETTER_OPTION_TABLE.'.value');
|
||||
}
|
||||
|
||||
function getQueue() {
|
||||
return SendingQueue::where('newsletter_id', $this->id)
|
||||
->orderByDesc('updated_at')
|
||||
->findOne();
|
||||
}
|
||||
|
||||
static function search($orm, $search = '') {
|
||||
return $orm->where_like('subject', '%' . $search . '%');
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
<?php
|
||||
namespace MailPoet\Models;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Queue extends Model {
|
||||
public static $_table = MP_QUEUES_TABLE;
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
}
|
@ -77,20 +77,7 @@ class Segment extends Model {
|
||||
}
|
||||
|
||||
static function getWPUsers() {
|
||||
$segment = self::where('type', 'wp_users')->findOne();
|
||||
|
||||
if($segment === false) {
|
||||
// create the wp users list
|
||||
$segment = self::create();
|
||||
$segment->hydrate(array(
|
||||
'name' => __('WordPress Users'),
|
||||
'type' => 'wp_users'
|
||||
));
|
||||
$segment->save();
|
||||
return self::findOne($segment->id());
|
||||
}
|
||||
|
||||
return $segment;
|
||||
return self::where('type', 'wp_users')->findOne();
|
||||
}
|
||||
|
||||
static function search($orm, $search = '') {
|
||||
@ -120,7 +107,7 @@ class Segment extends Model {
|
||||
}
|
||||
}
|
||||
|
||||
static function getSegmentsForImport() {
|
||||
static function getSegmentsWithSubscriberCount() {
|
||||
return self::selectMany(array(self::$_table.'.id', self::$_table.'.name'))
|
||||
->select_expr(
|
||||
'COUNT('.MP_SUBSCRIBER_SEGMENT_TABLE.'.subscriber_id)', 'subscribers'
|
||||
|
35
lib/Models/SendingQueue.php
Normal file
35
lib/Models/SendingQueue.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
namespace MailPoet\Models;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class SendingQueue extends Model {
|
||||
public static $_table = MP_SENDING_QUEUE_TABLE;
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
function pause() {
|
||||
if($this->count_processed === $this->count_total) {
|
||||
return false;
|
||||
} else {
|
||||
$this->set('status', 'paused');
|
||||
return $this->save();
|
||||
}
|
||||
}
|
||||
|
||||
function resume() {
|
||||
if($this->count_processed === $this->count_total) {
|
||||
return $this->complete();
|
||||
} else {
|
||||
$this->set_expr('status', 'NULL');
|
||||
return $this->save();
|
||||
}
|
||||
}
|
||||
|
||||
function complete() {
|
||||
$this->set('status', 'completed');
|
||||
return $this->save();
|
||||
}
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
<?php
|
||||
namespace MailPoet\Queue;
|
||||
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\NewsletterStatistics;
|
||||
use MailPoet\Models\Queue;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Worker {
|
||||
function __construct($timer = false) {
|
||||
$this->timer = $timer;
|
||||
$this->timer = microtime(true);
|
||||
}
|
||||
|
||||
function process() {
|
||||
$queues =
|
||||
Queue::orderByDesc('priority')
|
||||
->whereNotIn('status', array(
|
||||
'paused',
|
||||
'completed'
|
||||
))
|
||||
->findResultSet();
|
||||
foreach ($queues as $queue) {
|
||||
$newsletter = Newsletter::findOne($queue->newsletter_id)
|
||||
->asArray();
|
||||
$subscribers = json_decode($queue->subscribers, true);
|
||||
if(!isset($subscribers['failed'])) $subscribers['failed'] = array();
|
||||
if(!isset($subscribers['processed'])) $subscribers['processed'] = array();
|
||||
$subscribersToProcess = $subscribers['to_process'];
|
||||
foreach ($subscribersToProcess as $subscriber) {
|
||||
$elapsedTime = microtime(true) - $this->timer;
|
||||
if($elapsedTime >= 28) break;
|
||||
// TODO: hook up to mailer
|
||||
sleep(1);
|
||||
$newsletterStatistics = NewsletterStatistics::create();
|
||||
$newsletterStatistics->subscriber_id = $subscriber;
|
||||
$newsletterStatistics->newsletter_id = $newsletter['id'];
|
||||
$newsletterStatistics->queue_id = $queue->id;
|
||||
$newsletterStatistics->save();
|
||||
$subscribers['processed'][] = $subscriber;
|
||||
$subscribers['to_process'] = array_values(
|
||||
array_diff(
|
||||
$subscribers['to_process'],
|
||||
$subscribers['processed']
|
||||
)
|
||||
);
|
||||
$queue->count_processed = count($subscribers['processed']);
|
||||
$queue->count_to_process = count($subscribers['to_process']);
|
||||
$queue->count_failed = count($subscribers['failed']);
|
||||
$queue->count_total =
|
||||
$queue->count_processed + $queue->count_to_process + $queue->count_failed;
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
194
lib/Router/Cron.php
Normal file
194
lib/Router/Cron.php
Normal file
@ -0,0 +1,194 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Models\SendingQueue;
|
||||
use MailPoet\Util\Helpers;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Cron {
|
||||
function controlDaemon($data) {
|
||||
switch($data['action']) {
|
||||
case 'start':
|
||||
$supervisor = new Supervisor($forceStart = true);
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => $supervisor->checkDaemon() ?
|
||||
true :
|
||||
false
|
||||
)
|
||||
);
|
||||
break;
|
||||
case 'stop':
|
||||
$status = 'stopped';
|
||||
break;
|
||||
default:
|
||||
$status = 'paused';
|
||||
break;
|
||||
}
|
||||
$daemon = new Daemon();
|
||||
if(!$daemon->daemon || $daemon->daemonData['status'] !== 'started') {
|
||||
$result = false;
|
||||
} else {
|
||||
$daemon->daemonData['status'] = $status;
|
||||
$daemon->daemon->value = json_encode($daemon->daemonData);
|
||||
$result = $daemon->daemon->save();
|
||||
}
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => $result
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function getDaemonStatus() {
|
||||
$daemon = new \MailPoet\Cron\BootStrapMenu();
|
||||
wp_send_json($daemon->bootStrap());
|
||||
}
|
||||
|
||||
function addQueue($data) {
|
||||
$queue = SendingQueue::where('newsletter_id', $data['newsletter_id'])
|
||||
->whereNull('status')
|
||||
->findArray();
|
||||
|
||||
!d($queue);
|
||||
exit;
|
||||
$queue = SendingQueue::create();
|
||||
|
||||
$queue->newsletter_id = $data['newsletter_id'];
|
||||
|
||||
|
||||
$subscriber_ids = array();
|
||||
$segments = Segment::whereIn('id', $data['segments'])
|
||||
->findMany();
|
||||
foreach($segments as $segment) {
|
||||
$subscriber_ids = array_merge($subscriber_ids, Helpers::arrayColumn(
|
||||
$segment->subscribers()
|
||||
->findArray(),
|
||||
'id'
|
||||
));
|
||||
}
|
||||
|
||||
$subscriber_ids = array_unique($subscriber_ids);
|
||||
$queue->subscribers = json_encode(
|
||||
array(
|
||||
'to_process' => $subscriber_ids
|
||||
)
|
||||
);
|
||||
|
||||
$queue->count_total = $queue->count_to_process = count($subscriber_ids);
|
||||
$queue->save();
|
||||
wp_send_json(
|
||||
!$queue->save() ?
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => 'Queue could not be created.'
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => array($queue->id)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function addQueues($data) {
|
||||
$result = array_map(function ($queueData) {
|
||||
$queue = 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,
|
||||
'error' => __('Some queues could not be created.'),
|
||||
'data' => $result
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => $result
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function deleteQueue($data) {
|
||||
$queue = SendingQueue::whereNull('deleted_at')
|
||||
->findOne($data['queue_id']);
|
||||
if(!$queue) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('Queue not found.')
|
||||
)
|
||||
);
|
||||
}
|
||||
$queue->deleted_at = 'Y-m-d H:i:s';
|
||||
$queue->save();
|
||||
wp_send_json(array('result' => true));
|
||||
}
|
||||
|
||||
function deleteQueues($data) {
|
||||
$queues = SendingQueue::whereNull('deleted_at')
|
||||
->whereIn('id', $data['queue_ids'])
|
||||
->findResultSet();
|
||||
if(!$queues->count()) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('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 = SendingQueue::whereNull('deleted_at')
|
||||
->findOne($data['queue_id'])
|
||||
->asArray();
|
||||
wp_send_json(
|
||||
!$queue ?
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('Queue not found.')
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => $queue
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function getQueuesStatus($data) {
|
||||
$queues = SendingQueue::whereNull('deleted_at')
|
||||
->whereIn('id', $data['queue_ids'])
|
||||
->findArray();
|
||||
wp_send_json(
|
||||
!$queues ?
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('Queue not found.')
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => $queues
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -1,80 +1,159 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Mailer {
|
||||
function __construct() {
|
||||
$this->fromName = $this->getSetting('from_name');
|
||||
$this->fromEmail = $this->getSetting('from_address');
|
||||
$this->mailer = $this->getSetting('mailer');
|
||||
$this->from = sprintf('%s <%s>', $this->fromName, $this->fromEmail);
|
||||
}
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
$subscriber = $this->transformSubscriber($subscriber);
|
||||
$mailer = $this->buildMailer();
|
||||
return wp_send_json($mailer->send($newsletter, $subscriber));
|
||||
}
|
||||
|
||||
function buildMailer() {
|
||||
switch ($this->mailer['name']) {
|
||||
case 'AmazonSES':
|
||||
$mailer = new $this->mailer['class'](
|
||||
$this->mailer['region'],
|
||||
$this->mailer['access_key'],
|
||||
$this->mailer['secret_key'],
|
||||
$this->from
|
||||
);
|
||||
break;
|
||||
case 'ElasticEmail':
|
||||
$mailer = new $this->mailer['class'](
|
||||
$this->mailer['api_key'],
|
||||
$this->fromEmail, $this->fromName
|
||||
);
|
||||
break;
|
||||
case 'MailGun':
|
||||
$mailer = new $this->mailer['class'](
|
||||
$this->mailer['domain'],
|
||||
$this->mailer['api_key'],
|
||||
$this->from
|
||||
);
|
||||
break;
|
||||
case 'MailPoet':
|
||||
$mailer = new $this->mailer['class'](
|
||||
$this->mailer['api_key'],
|
||||
$this->fromEmail,
|
||||
$this->fromName
|
||||
);
|
||||
break;
|
||||
case 'Mandrill':
|
||||
$mailer = new $this->mailer['class'](
|
||||
$this->mailer['api_key'],
|
||||
$this->fromEmail, $this->fromName
|
||||
);
|
||||
break;
|
||||
case 'SendGrid':
|
||||
$mailer = new $this->mailer['class'](
|
||||
$this->mailer['api_key'],
|
||||
$this->fromEmail,
|
||||
$this->fromName
|
||||
);
|
||||
break;
|
||||
case 'SMTP':
|
||||
$mailer = new $this->mailer['class'](
|
||||
$this->mailer['host'],
|
||||
$this->mailer['port'],
|
||||
$this->mailer['authentication'],
|
||||
$this->mailer['encryption'],
|
||||
$this->fromEmail,
|
||||
$this->fromName);
|
||||
break;
|
||||
function __construct($httpRequest = true) {
|
||||
$this->mailerType = array(
|
||||
'AmazonSES' => 'API',
|
||||
'ElasticEmail' => 'API',
|
||||
'MailGun' => 'API',
|
||||
'Mandrill' => 'API',
|
||||
'SendGrid' => 'API',
|
||||
'MailPoet' => null,
|
||||
'SMTP' => null,
|
||||
'WPMail' => null
|
||||
);
|
||||
if(!$httpRequest) {
|
||||
list($this->fromName, $this->fromEmail, $this->fromNameEmail)
|
||||
= $this->getSetting('sender');
|
||||
$this->mailer = $this->getSetting('mailer');
|
||||
}
|
||||
return $mailer;
|
||||
}
|
||||
|
||||
function send($data) {
|
||||
$subscriber = $this->transformSubscriber($data['subscriber']);
|
||||
list($fromName, $fromEmail, $fromNameEmail)
|
||||
= $this->getSetting('sender');
|
||||
if(!$fromName && !$fromEmail) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Please configure your name and e-mail address.'))
|
||||
)
|
||||
);
|
||||
}
|
||||
$data['mailer']['class'] = 'MailPoet\\Mailer\\' .
|
||||
(($this->mailerType[$data['mailer']['method']]) ?
|
||||
$this->mailerType[$data['mailer']['method']] . '\\' . $data['mailer']['method'] :
|
||||
$data['mailer']['method']
|
||||
);
|
||||
$mailer = $this->buildMailer(
|
||||
$data['mailer'],
|
||||
$fromName,
|
||||
$fromEmail,
|
||||
$fromNameEmail
|
||||
);
|
||||
if(!empty($newsletter['sender_address']) &&
|
||||
!empty($newsletter['sender_name'])
|
||||
) {
|
||||
$mailer->fromName = $newsletter['sender_name'];
|
||||
$mailer->fromEmail = $newsletter['sender_address'];
|
||||
$mailer->fromNameEmail = sprintf(
|
||||
'%s <%s>',
|
||||
$mailer->fromName,
|
||||
$mailer->fromEmail
|
||||
);
|
||||
}
|
||||
if(!empty($newsletter['reply_to_address']) &&
|
||||
!empty($newsletter['reply_to_name'])
|
||||
) {
|
||||
$mailer->replyToName = $newsletter['reply_to_name'];
|
||||
$mailer->replyToEmail = $newsletter['reply_to_address'];
|
||||
$mailer->replyToNameEmail = sprintf(
|
||||
'%s <%s>',
|
||||
$mailer->replyToName,
|
||||
$mailer->replyToEmail
|
||||
);
|
||||
}
|
||||
$result = $mailer->send($data['newsletter'], $subscriber);
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => ($result) ? true : false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function buildMailer($mailer = false, $fromName = false, $fromEmail = false, $fromNameEmail = false) {
|
||||
if(!$mailer) $mailer = $this->mailer;
|
||||
if(!$fromName) $fromName = $this->fromName;
|
||||
if(!$fromEmail) $fromEmail = $this->fromEmail;
|
||||
if(!$fromNameEmail) $fromNameEmail = $this->fromNameEmail;
|
||||
switch($mailer['method']) {
|
||||
case 'AmazonSES':
|
||||
$mailerInstance = new $mailer['class'](
|
||||
$mailer['region'],
|
||||
$mailer['access_key'],
|
||||
$mailer['secret_key'],
|
||||
$fromNameEmail
|
||||
);
|
||||
break;
|
||||
case 'ElasticEmail':
|
||||
$mailerInstance = new $mailer['class'](
|
||||
$mailer['api_key'],
|
||||
$fromEmail, $fromName
|
||||
);
|
||||
break;
|
||||
case 'MailGun':
|
||||
$mailerInstance = new $mailer['class'](
|
||||
$mailer['domain'],
|
||||
$mailer['api_key'],
|
||||
$fromNameEmail
|
||||
);
|
||||
break;
|
||||
case 'MailPoet':
|
||||
$mailerInstance = new $mailer['class'](
|
||||
$mailer['mailpoet_api_key'],
|
||||
$fromEmail,
|
||||
$fromName
|
||||
);
|
||||
break;
|
||||
case 'Mandrill':
|
||||
$mailerInstance = new $mailer['class'](
|
||||
$mailer['api_key'],
|
||||
$fromEmail, $fromName
|
||||
);
|
||||
break;
|
||||
case 'SendGrid':
|
||||
$mailerInstance = new $mailer['class'](
|
||||
$mailer['api_key'],
|
||||
$fromEmail,
|
||||
$fromName
|
||||
);
|
||||
break;
|
||||
case 'WPMail':
|
||||
$mailerInstance = new $mailer['class'](
|
||||
$fromEmail,
|
||||
$fromName
|
||||
);
|
||||
break;
|
||||
case 'SMTP':
|
||||
$mailerInstance = new $mailer['class'](
|
||||
$mailer['host'],
|
||||
$mailer['port'],
|
||||
$mailer['authentication'],
|
||||
$mailer['login'],
|
||||
$mailer['password'],
|
||||
$mailer['encryption'],
|
||||
$fromEmail,
|
||||
$fromName
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new \Exception('Mailing method does not exist.');
|
||||
break;
|
||||
}
|
||||
return $mailerInstance;
|
||||
}
|
||||
|
||||
function transformSubscriber($subscriber) {
|
||||
if(!is_array($subscriber)) return $subscriber;
|
||||
if(isset($subscriber['address'])) $subscriber['email'] = $subscriber['address'];
|
||||
$first_name = (isset($subscriber['first_name'])) ? $subscriber['first_name'] : '';
|
||||
$last_name = (isset($subscriber['last_name'])) ? $subscriber['last_name'] : '';
|
||||
if(!$first_name && !$last_name) return $subscriber['email'];
|
||||
@ -84,65 +163,29 @@ class Mailer {
|
||||
}
|
||||
|
||||
function getSetting($setting) {
|
||||
if($setting === 'mailer') {
|
||||
$mailers = array(
|
||||
array(
|
||||
'name' => 'AmazonSES',
|
||||
'type' => 'API',
|
||||
'access_key' => 'AKIAJM6Y5HMGXBLDNSRA',
|
||||
'secret_key' => 'P3EbTbVx7U0LXKQ9nTm2eIrP+9aPiLyvaRDsFxXh',
|
||||
'region' => 'us-east-1'
|
||||
),
|
||||
array(
|
||||
'name' => 'ElasticEmail',
|
||||
'type' => 'API',
|
||||
'api_key' => '997f1f7f-41de-4d7f-a8cb-86c8481370fa'
|
||||
),
|
||||
array(
|
||||
'name' => 'MailGun',
|
||||
'type' => 'API',
|
||||
'api_key' => 'key-6cf5g5qjzenk-7nodj44gdt8phe6vam2',
|
||||
'domain' => 'mrcasual.com'
|
||||
),
|
||||
array(
|
||||
'name' => 'MailPoet',
|
||||
'api_key' => 'dhNSqj1XHkVltIliyQDvMiKzQShOA5rs0m_DdRUVZHU'
|
||||
),
|
||||
array(
|
||||
'name' => 'Mandrill',
|
||||
'type' => 'API',
|
||||
'api_key' => '692ys1B7REEoZN7R-dYwNA'
|
||||
),
|
||||
array(
|
||||
'name' => 'SendGrid',
|
||||
'type' => 'API',
|
||||
'api_key' => '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'
|
||||
),
|
||||
array(
|
||||
'name' => 'SMTP',
|
||||
'host' => 'email-smtp.us-west-2.amazonaws.com',
|
||||
'port' => 587,
|
||||
'authentication' => array(
|
||||
'login' => 'AKIAIGPBLH6JWG5VCBQQ',
|
||||
'password' => 'AudVHXHaYkvr54veCzqiqOxDiMMyfQW3/V6F1tYzGXY3'
|
||||
),
|
||||
'encryption' => 'tls'
|
||||
),
|
||||
array(
|
||||
'name' => 'WPMail'
|
||||
)
|
||||
);
|
||||
$mailer = $mailers[array_rand($mailers)];
|
||||
$mailer['class'] = 'MailPoet\\Mailer\\' .
|
||||
((isset($mailer['type'])) ?
|
||||
$mailer['type'] . '\\' . $mailer['name'] :
|
||||
$mailer['name']
|
||||
switch($setting) {
|
||||
case 'mailer':
|
||||
$mailer = Setting::getValue('mta', null);
|
||||
if(!$mailer || !isset($mailer['method'])) throw new \Exception('Mailing method is not configured.');
|
||||
$mailer['class'] = 'MailPoet\\Mailer\\' .
|
||||
(($this->mailerType[$mailer['method']]) ?
|
||||
$this->mailerType[$mailer['method']] . '\\' . $mailer['method'] :
|
||||
$mailer['method']
|
||||
);
|
||||
return $mailer;
|
||||
break;
|
||||
case 'sender':
|
||||
$sender = Setting::getValue($setting, null);
|
||||
if(!$sender) throw new \Exception('Sender name and email are not configured.');
|
||||
return array(
|
||||
$sender['name'],
|
||||
$sender['address'],
|
||||
sprintf('%s <%s>', $sender['name'], $sender['address'])
|
||||
);
|
||||
return $mailer;
|
||||
break;
|
||||
default:
|
||||
return Setting::getValue($setting, null);
|
||||
break;
|
||||
}
|
||||
if($setting === 'from_name') return 'Sender';
|
||||
if($setting === 'from_address') return 'staff@mailpoet.com';
|
||||
return Setting::where('name', $setting)
|
||||
->findOne()->value;
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ use MailPoet\Models\NewsletterSegment;
|
||||
use MailPoet\Models\NewsletterOptionField;
|
||||
use MailPoet\Models\NewsletterOption;
|
||||
use MailPoet\Newsletter\Renderer\Renderer;
|
||||
use MailPoet\Models\SendingQueue;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
@ -219,14 +220,20 @@ class Newsletters {
|
||||
|
||||
$listing_data = $listing->get();
|
||||
|
||||
// fetch segments relations for each returned item
|
||||
foreach($listing_data['items'] as &$item) {
|
||||
// get segments
|
||||
$segments = NewsletterSegment::select('segment_id')
|
||||
->where('newsletter_id', $item['id'])
|
||||
->findMany();
|
||||
$item['segments'] = array_map(function($relation) {
|
||||
return $relation->segment_id;
|
||||
}, $segments);
|
||||
|
||||
// get queue
|
||||
$queue = SendingQueue::where('newsletter_id', $item['id'])
|
||||
->orderByDesc('updated_at')
|
||||
->findOne();
|
||||
$item['queue'] = ($queue !== false) ? $queue->asArray() : null;
|
||||
}
|
||||
|
||||
wp_send_json($listing_data);
|
||||
|
@ -1,26 +1,25 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Queue\Daemon;
|
||||
use MailPoet\Queue\Supervisor;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Models\SendingQueue;
|
||||
use MailPoet\Util\Helpers;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Queue {
|
||||
function start() {
|
||||
$supervisor = new Supervisor();
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => ($supervisor->checkDaemon($forceStart = true)) ?
|
||||
true :
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function update($data) {
|
||||
switch ($data['action']) {
|
||||
function controlDaemon($data) {
|
||||
switch($data['action']) {
|
||||
case 'start':
|
||||
$supervisor = new Supervisor($forceStart = true);
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => $supervisor->checkDaemon() ?
|
||||
true :
|
||||
false
|
||||
)
|
||||
);
|
||||
break;
|
||||
case 'stop':
|
||||
$status = 'stopped';
|
||||
break;
|
||||
@ -43,9 +42,155 @@ class Queue {
|
||||
);
|
||||
}
|
||||
|
||||
function getQueueStatus() {
|
||||
$daemon = new \MailPoet\Queue\BootStrapMenu();
|
||||
function getDaemonStatus() {
|
||||
$daemon = new \MailPoet\Cron\BootStrapMenu();
|
||||
wp_send_json($daemon->bootStrap());
|
||||
}
|
||||
|
||||
function addQueue($data) {
|
||||
$queue = SendingQueue::where('newsletter_id', $data['newsletter_id'])
|
||||
->whereNull('status')
|
||||
->findArray();
|
||||
|
||||
!d($queue);
|
||||
exit;
|
||||
$queue = SendingQueue::create();
|
||||
|
||||
$queue->newsletter_id = $data['newsletter_id'];
|
||||
|
||||
|
||||
$subscriber_ids = array();
|
||||
$segments = Segment::whereIn('id', $data['segments'])
|
||||
->findMany();
|
||||
foreach($segments as $segment) {
|
||||
$subscriber_ids = array_merge($subscriber_ids, Helpers::arrayColumn(
|
||||
$segment->subscribers()
|
||||
->findArray(),
|
||||
'id'
|
||||
));
|
||||
}
|
||||
|
||||
$subscriber_ids = array_unique($subscriber_ids);
|
||||
$queue->subscribers = json_encode(
|
||||
array(
|
||||
'to_process' => $subscriber_ids
|
||||
)
|
||||
);
|
||||
|
||||
$queue->count_total = $queue->count_to_process = count($subscriber_ids);
|
||||
$queue->save();
|
||||
wp_send_json(
|
||||
!$queue->save() ?
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => 'Queue could not be created.'
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => array($queue->id)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function addQueues($data) {
|
||||
$result = array_map(function ($queueData) {
|
||||
$queue = 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,
|
||||
'error' => __('Some queues could not be created.'),
|
||||
'data' => $result
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => $result
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function deleteQueue($data) {
|
||||
$queue = SendingQueue::whereNull('deleted_at')
|
||||
->findOne($data['queue_id']);
|
||||
if(!$queue) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('Queue not found.')
|
||||
)
|
||||
);
|
||||
}
|
||||
$queue->deleted_at = 'Y-m-d H:i:s';
|
||||
$queue->save();
|
||||
wp_send_json(array('result' => true));
|
||||
}
|
||||
|
||||
function deleteQueues($data) {
|
||||
$queues = SendingQueue::whereNull('deleted_at')
|
||||
->whereIn('id', $data['queue_ids'])
|
||||
->findResultSet();
|
||||
if(!$queues->count()) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('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 = SendingQueue::whereNull('deleted_at')
|
||||
->findOne($data['queue_id'])
|
||||
->asArray();
|
||||
wp_send_json(
|
||||
!$queue ?
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('Queue not found.')
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => $queue
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function getQueuesStatus($data) {
|
||||
$queues = SendingQueue::whereNull('deleted_at')
|
||||
->whereIn('id', $data['queue_ids'])
|
||||
->findArray();
|
||||
wp_send_json(
|
||||
!$queues ?
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('Queue not found.')
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => $queues
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
211
lib/Router/SendingQueue.php
Normal file
211
lib/Router/SendingQueue.php
Normal file
@ -0,0 +1,211 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Util\Helpers;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class SendingQueue {
|
||||
function add($data) {
|
||||
$queue = \MailPoet\Models\SendingQueue::where('newsletter_id', $data['newsletter_id'])
|
||||
->whereNull('status')
|
||||
->findArray();
|
||||
if(count($queue)) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Send operation is already in progress.'))
|
||||
)
|
||||
);
|
||||
exit;
|
||||
}
|
||||
$queue = \MailPoet\Models\SendingQueue::create();
|
||||
$queue->newsletter_id = $data['newsletter_id'];
|
||||
$subscriber_ids = array();
|
||||
$segments = Segment::whereIn('id', $data['segments'])
|
||||
->findMany();
|
||||
|
||||
foreach($segments as $segment) {
|
||||
$subscriber_ids = array_merge($subscriber_ids, Helpers::arrayColumn(
|
||||
$segment->subscribers()
|
||||
->findArray(),
|
||||
'id'
|
||||
));
|
||||
}
|
||||
$subscriber_ids = array_unique($subscriber_ids);
|
||||
$queue->subscribers = json_encode(
|
||||
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
|
||||
)
|
||||
);
|
||||
} else {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => array($queue->id)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function pause($newsletter_id) {
|
||||
$newsletter = Newsletter::findOne($newsletter_id);
|
||||
$result = false;
|
||||
|
||||
if($newsletter !== false) {
|
||||
$queue = $newsletter->getQueue();
|
||||
if($queue !== false && $queue->id() > 0) {
|
||||
$result = $queue->pause();
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json(array(
|
||||
'result' => $result
|
||||
));
|
||||
}
|
||||
|
||||
function resume($newsletter_id) {
|
||||
$newsletter = Newsletter::findOne($newsletter_id);
|
||||
$result = false;
|
||||
|
||||
if($newsletter !== false) {
|
||||
$queue = $newsletter->getQueue();
|
||||
if($queue !== false && $queue->id() > 0) {
|
||||
$result = $queue->resume();
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json(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
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -6,7 +6,9 @@ use \MailPoet\Models\Segment;
|
||||
class WP {
|
||||
static function synchronizeUser($wp_user_id) {
|
||||
$wpUser = \get_userdata($wp_user_id);
|
||||
if($wpUser === false) return;
|
||||
$segment = Segment::getWPUsers();
|
||||
|
||||
if($wpUser === false or $segment === false) return;
|
||||
|
||||
$subscriber = Subscriber::where('wp_user_id', $wpUser->ID)
|
||||
->findOne();
|
||||
@ -46,8 +48,9 @@ class WP {
|
||||
$subscriber = Subscriber::createOrUpdate($data);
|
||||
|
||||
if($subscriber !== false && $subscriber->id()) {
|
||||
$segment = Segment::getWPUsers();
|
||||
$segment->addSubscriber($subscriber->id());
|
||||
if($segment !== false) {
|
||||
$segment->addSubscriber($subscriber->id());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3,29 +3,45 @@ namespace MailPoet\Settings;
|
||||
|
||||
class Hosts {
|
||||
private static $_smtp = array(
|
||||
'amazon' => array(
|
||||
'AmazonSES' => array(
|
||||
'name' => 'Amazon SES',
|
||||
'api' => false,
|
||||
'emails' => 100,
|
||||
'interval' => 5
|
||||
'interval' => 5,
|
||||
'fields' => array(
|
||||
'region',
|
||||
'access_key',
|
||||
'secret_key'
|
||||
),
|
||||
'regions' => array(
|
||||
'US East (N. Virginia)' => 'us-east-1.amazonaws.com',
|
||||
'US West (Oregon)' => 'us-west-2.amazonaws.com',
|
||||
'EU (Ireland)' => 'eu-west-1.amazonaws.com'
|
||||
)
|
||||
),
|
||||
'elasticemail' => array(
|
||||
'ElasticEmail' => array(
|
||||
'name' => 'ElasticEmail',
|
||||
'api' => true,
|
||||
'emails' => 100,
|
||||
'interval' => 5
|
||||
'interval' => 5,
|
||||
'fields' => array(
|
||||
'api_key'
|
||||
)
|
||||
),
|
||||
'mailgun' => array(
|
||||
'MailGun' => array(
|
||||
'name' => 'MailGun',
|
||||
'api' => false,
|
||||
'emails' => 100,
|
||||
'interval' => 5
|
||||
'interval' => 5,
|
||||
'fields' => array(
|
||||
'domain',
|
||||
'api_key'
|
||||
)
|
||||
),
|
||||
'sendgrid' => array(
|
||||
'SendGrid' => array(
|
||||
'name' => 'SendGrid',
|
||||
'api' => true,
|
||||
'emails' => 100,
|
||||
'interval' => 5
|
||||
'interval' => 5,
|
||||
'fields' => array(
|
||||
'api_key'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -12,7 +12,7 @@ class BootStrapMenu {
|
||||
|
||||
function getSegments($withConfirmedSubscribers = false) {
|
||||
$segments = ($this->action === 'import') ?
|
||||
Segment::getSegmentsForImport() :
|
||||
Segment::getSegmentsWithSubscriberCount() :
|
||||
Segment::getSegmentsForExport($withConfirmedSubscribers);
|
||||
return array_map(function ($segment) {
|
||||
return array(
|
||||
|
@ -63,7 +63,7 @@ class Import {
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (\PDOException $e) {
|
||||
} catch(\PDOException $e) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'error' => $e->getMessage()
|
||||
@ -145,7 +145,7 @@ class Import {
|
||||
);
|
||||
if(!$existingTrashedRecords) return;
|
||||
$existingTrashedRecords = Helpers::flattenArray($existingTrashedRecords);
|
||||
foreach (array_chunk($existingTrashedRecords, 200) as $subscriberIds) {
|
||||
foreach(array_chunk($existingTrashedRecords, 200) as $subscriberIds) {
|
||||
Subscriber::whereIn('id', $subscriberIds)
|
||||
->deleteMany();
|
||||
SubscriberSegment::whereIn('subscriber_id', $subscriberIds)
|
||||
@ -247,7 +247,7 @@ class Import {
|
||||
}, $subscriberFields);
|
||||
}, range(0, $subscribersCount));
|
||||
$currentTime = ($action === 'update') ? date('Y-m-d H:i:s') : $this->currentTime;
|
||||
foreach (array_chunk($subscribers, 200) as $data) {
|
||||
foreach(array_chunk($subscribers, 100) as $data) {
|
||||
if($action == 'create') {
|
||||
Subscriber::createMultiple(
|
||||
$subscriberFields,
|
||||
@ -310,7 +310,7 @@ class Import {
|
||||
);
|
||||
}, $count, $subscribersData[$column]);
|
||||
}, $subscriberCustomFields)[0];
|
||||
foreach (array_chunk($subscribers, 200) as $data) {
|
||||
foreach(array_chunk($subscribers, 200) as $data) {
|
||||
if($action === 'create') {
|
||||
SubscriberCustomField::createMultiple(
|
||||
$data
|
||||
@ -325,7 +325,7 @@ class Import {
|
||||
}
|
||||
|
||||
function addSubscribersToSegments($subscribers, $segments) {
|
||||
foreach (array_chunk($subscribers, 200) as $data) {
|
||||
foreach(array_chunk($subscribers, 200) as $data) {
|
||||
SubscriberSegment::createMultiple($segments, $data);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,14 @@ class Security {
|
||||
return wp_create_nonce('mailpoet_token');
|
||||
}
|
||||
|
||||
static function generateRandomString($length) {
|
||||
return substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, $length);
|
||||
static function generateRandomString($length = 5) {
|
||||
// non-cryptographically strong random generator
|
||||
return substr(
|
||||
md5(
|
||||
uniqid(
|
||||
mt_rand(), true)
|
||||
),
|
||||
0,
|
||||
(!is_int($length) || $length <= 5 || $length >= 32) ? 5 : $length);
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ if (!defined('ABSPATH')) exit;
|
||||
|
||||
/*
|
||||
* Plugin Name: MailPoet
|
||||
* Version: 0.0.5
|
||||
* Version: 0.0.6
|
||||
* Plugin URI: http://www.mailpoet.com
|
||||
* Description: MailPoet Newsletters.
|
||||
* Author: MailPoet
|
||||
@ -18,12 +18,12 @@ if (!defined('ABSPATH')) exit;
|
||||
*
|
||||
* @package WordPress
|
||||
* @author MailPoet
|
||||
* @since 0.0.5
|
||||
* @since 0.0.6
|
||||
*/
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
define('MAILPOET_VERSION', '0.0.5');
|
||||
define('MAILPOET_VERSION', '0.0.6');
|
||||
|
||||
$initializer = new Initializer(array(
|
||||
'file' => __FILE__,
|
||||
|
@ -10,7 +10,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"backbone": "1.2.3",
|
||||
"backbone.marionette": "2.4.3",
|
||||
"backbone.marionette": "2.4.4",
|
||||
"backbone.radio": "0.9.0",
|
||||
"backbone.supermodel": "1.2.0",
|
||||
"c3": "~0.4.10",
|
||||
@ -24,7 +24,7 @@
|
||||
"moment": "^2.10.3",
|
||||
"napa": "^1.2.0",
|
||||
"papaparse": "4.1.1",
|
||||
"parsley": "^0.1.0",
|
||||
"parsleyjs": "^2.1.2",
|
||||
"react": "^0.14.1",
|
||||
"react-checkbox-group": "0.2.2",
|
||||
"react-dom": "^0.14.1",
|
||||
|
@ -96,7 +96,13 @@ define([
|
||||
});
|
||||
|
||||
it('triggers template saving when clicked on save as template button', function() {
|
||||
var mock = sinon.mock({ post: function() {} }).expects('post').once().returns(jQuery.Deferred());
|
||||
var mock = sinon.mock({ post: function() {} }).expects('post').once().returns(jQuery.Deferred()),
|
||||
html2canvasMock = jQuery.Deferred();
|
||||
|
||||
html2canvasMock.resolve({
|
||||
toDataURL: function() { return 'somedataurl'; },
|
||||
});
|
||||
|
||||
EditorApplication.getBody = sinon.stub();
|
||||
var module = SaveInjector({
|
||||
'mailpoet': {
|
||||
@ -105,6 +111,7 @@ define([
|
||||
}
|
||||
},
|
||||
'newsletter_editor/App': EditorApplication,
|
||||
'html2canvas': function() { return html2canvasMock; },
|
||||
});
|
||||
var view = new (module.SaveView)();
|
||||
view.render();
|
||||
|
@ -5,7 +5,7 @@ use MailPoet\Mailer\API\AmazonSES;
|
||||
class AmazonSESCest {
|
||||
function _before() {
|
||||
$this->settings = array(
|
||||
'name' => 'AmazonSES',
|
||||
'method' => 'AmazonSES',
|
||||
'type' => 'API',
|
||||
'access_key' => 'AKIAJM6Y5HMGXBLDNSRA',
|
||||
'secret_key' => 'P3EbTbVx7U0LXKQ9nTm2eIrP+9aPiLyvaRDsFxXh',
|
||||
|
@ -5,7 +5,7 @@ use MailPoet\Mailer\API\ElasticEmail;
|
||||
class ElasticEmailCest {
|
||||
function _before() {
|
||||
$this->settings = array(
|
||||
'name' => 'ElasticEmail',
|
||||
'method' => 'ElasticEmail',
|
||||
'type' => 'API',
|
||||
'api_key' => '997f1f7f-41de-4d7f-a8cb-86c8481370fa'
|
||||
);
|
||||
|
@ -5,7 +5,7 @@ use MailPoet\Mailer\API\MailGun;
|
||||
class MailGunCest {
|
||||
function _before() {
|
||||
$this->settings = array(
|
||||
'name' => 'MailGun',
|
||||
'method' => 'MailGun',
|
||||
'type' => 'API',
|
||||
'api_key' => 'key-6cf5g5qjzenk-7nodj44gdt8phe6vam2',
|
||||
'domain' => 'mrcasual.com'
|
||||
|
@ -5,7 +5,7 @@ use MailPoet\Mailer\API\Mandrill;
|
||||
class MandrillCest {
|
||||
function _before() {
|
||||
$this->settings = array(
|
||||
'name' => 'Mandrill',
|
||||
'method' => 'Mandrill',
|
||||
'type' => 'API',
|
||||
'api_key' => '692ys1B7REEoZN7R-dYwNA'
|
||||
);
|
||||
|
@ -5,7 +5,7 @@ use MailPoet\Mailer\API\SendGrid;
|
||||
class SendGridCest {
|
||||
function _before() {
|
||||
$this->settings = array(
|
||||
'name' => 'SendGrid',
|
||||
'method' => 'SendGrid',
|
||||
'type' => 'API',
|
||||
'api_key' => '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'
|
||||
);
|
||||
|
@ -5,7 +5,7 @@ use MailPoet\Mailer\MailPoet;
|
||||
class MailPoetCest {
|
||||
function _before() {
|
||||
$this->settings = array(
|
||||
'name' => 'MailPoet',
|
||||
'method' => 'MailPoet',
|
||||
'api_key' => 'dhNSqj1XHkVltIliyQDvMiKzQShOA5rs0m_DdRUVZHU'
|
||||
);
|
||||
$this->fromEmail = 'staff@mailpoet.com';
|
||||
|
@ -5,7 +5,7 @@ use MailPoet\Mailer\SMTP;
|
||||
class SMTPCest {
|
||||
function _before() {
|
||||
$this->settings = array(
|
||||
'name' => 'SMTP',
|
||||
'method' => 'SMTP',
|
||||
'host' => 'email-smtp.us-west-2.amazonaws.com',
|
||||
'port' => 587,
|
||||
'authentication' => array(
|
||||
|
@ -5,7 +5,7 @@ use MailPoet\Mailer\WPMail;
|
||||
class WPMailCest {
|
||||
function _before() {
|
||||
$this->settings = array(
|
||||
'name' => 'WPMail'
|
||||
'method' => 'WPMail'
|
||||
);
|
||||
$this->fromEmail = 'staff@mailpoet.com';
|
||||
$this->fromName = 'Sender';
|
||||
|
@ -154,7 +154,7 @@ class SegmentCest {
|
||||
expect(count($newsletters))->equals(2);
|
||||
}
|
||||
|
||||
function itCanGetSegmentsForImport() {
|
||||
function itCanGetSegmentsWithSubscriberCount() {
|
||||
foreach ($this->subscribersData as $subscriberData) {
|
||||
$subscriber = Subscriber::create();
|
||||
$subscriber->hydrate($subscriberData);
|
||||
@ -164,7 +164,7 @@ class SegmentCest {
|
||||
$association->segment_id = $this->segment->id;
|
||||
$association->save();
|
||||
}
|
||||
$segment = Segment::getSegmentsForImport();
|
||||
$segment = Segment::getSegmentsWithSubscriberCount();
|
||||
expect($segment[0]['subscribers'])->equals(2);
|
||||
}
|
||||
|
||||
|
@ -43,8 +43,8 @@ class MailerCest {
|
||||
$mailer = $this->router->buildMailer();
|
||||
$class = 'Mailpoet\\Mailer\\' .
|
||||
((isset($this->router->mailer['type'])) ?
|
||||
$this->router->mailer['type'] . '\\' . $this->router->mailer['name'] :
|
||||
$this->router->mailer['name']
|
||||
$this->router->mailer['type'] . '\\' . $this->router->mailer['method'] :
|
||||
$this->router->mailer['method']
|
||||
);
|
||||
expect($mailer instanceof $class)->true();
|
||||
expect(method_exists($mailer, 'send'))->true();
|
||||
@ -52,7 +52,7 @@ class MailerCest {
|
||||
|
||||
function itCanSend() {
|
||||
$newsletter = array(
|
||||
'subject' => 'testing Mailer router with ' . $this->router->mailer['name'],
|
||||
'subject' => 'testing Mailer router with ' . $this->router->mailer['method'],
|
||||
'body' => array(
|
||||
'html' => 'HTML body',
|
||||
'text' => 'TEXT body'
|
||||
|
@ -43,7 +43,7 @@ class BootStrapMenuCest {
|
||||
$this->bootStrapExportMenu = new BootStrapMenu('export');
|
||||
}
|
||||
|
||||
function itCanGetSegmentsForImport() {
|
||||
function itCanGetSegmentsWithSubscriberCount() {
|
||||
$this->_createSegmentsAndSubscribers();
|
||||
$segments = $this->bootStrapImportMenu->getSegments();
|
||||
expect(count($segments))->equals(2);
|
||||
|
10
views/cron.html
Normal file
10
views/cron.html
Normal file
@ -0,0 +1,10 @@
|
||||
<% extends 'layout.html' %>
|
||||
|
||||
<% block content %>
|
||||
<div id="cron_container">
|
||||
<div id="cron_status"></div>
|
||||
</div>
|
||||
<script>
|
||||
var cronDaemon = <%= daemon|raw %>
|
||||
</script>
|
||||
<% endblock %>
|
@ -30,4 +30,12 @@
|
||||
'vendor.js',
|
||||
'mailpoet.js',
|
||||
'admin.js'
|
||||
)%>
|
||||
)%>
|
||||
|
||||
<script>
|
||||
HS.beacon.config({
|
||||
icon: 'message',
|
||||
zIndex: 50000,
|
||||
instructions: '<%= __('Want to give feedback to the MailPoet team? Write them right here with as much information as possible.') %>',
|
||||
});
|
||||
</script>
|
||||
|
@ -1230,12 +1230,9 @@
|
||||
shortcode: 'global:browser',
|
||||
}
|
||||
],
|
||||
'<%= __('Custom fields') %>': [
|
||||
{
|
||||
text: '<%= __('Temporary sample custom field') %>',
|
||||
shortcode: 'custom:samplefield',
|
||||
}
|
||||
]
|
||||
<% if customFields %>
|
||||
'<%= __('Custom fields') %>': <%= json_encode(customFields) %>,
|
||||
<% endif %>
|
||||
},
|
||||
translations: {
|
||||
customFieldsWindowTitle:
|
||||
|
@ -41,7 +41,7 @@
|
||||
<div class="mailpoet_form_field">
|
||||
<a href="javascript:;" class="mailpoet_automated_latest_content_show_display_options"><%= __('Display options') %></a>
|
||||
</div>
|
||||
<div class="mailpoet_automated_latest_content_display_options mailpoet_hidden">
|
||||
<div class="mailpoet_automated_latest_content_display_options mailpoet_closed">
|
||||
<div class="mailpoet_form_field">
|
||||
<a href="javascript:;" class="mailpoet_automated_latest_content_hide_display_options"><%= __('Hide display options') %></a>
|
||||
</div>
|
||||
|
@ -2,12 +2,6 @@
|
||||
<%= source('newsletter/templates/svg/block-tools/settings-column.svg') %>
|
||||
</a>{{/if}}{{#if tools.settings}}<a href="javascript:;" class="mailpoet_tool mailpoet_edit_block" title="<%= __('Edit settings') %>">
|
||||
<%= source('newsletter/templates/svg/block-tools/settings.svg') %>
|
||||
</a>{{/if}}{{#if tools.delete}}<div class="mailpoet_delete_block">
|
||||
<a href="javascript:;" class="mailpoet_tool mailpoet_delete_block_activate" title="<%= __('Delete') %>">
|
||||
<%= source('newsletter/templates/svg/block-tools/trash.svg') %>
|
||||
</a>
|
||||
<a href="javascript:;" class="mailpoet_delete_block_confirm" title="<%= __('Confirm deletion') %>"><%= __('Delete') %></a>
|
||||
<a href="javascript:;" class="mailpoet_delete_block_cancel" title="<%= __('Cancel deletion') %>"><%= __('Cancel') %></a>
|
||||
</div>{{/if}}{{#if tools.move}}<a href="javascript:;" class="mailpoet_tool mailpoet_move_block" title="<%= __('Drag to move') %>">
|
||||
</a>{{/if}}{{#if tools.delete}}<div class="mailpoet_delete_block"><a href="javascript:;" class="mailpoet_tool mailpoet_delete_block_activate" title="<%= __('Delete') %>"><%= source('newsletter/templates/svg/block-tools/trash.svg') %></a><a href="javascript:;" class="mailpoet_delete_block_confirm" title="<%= __('Confirm deletion') %>"><%= __('Delete') %></a><a href="javascript:;" class="mailpoet_delete_block_cancel" title="<%= __('Cancel deletion') %>"><%= __('Cancel') %></a></div>{{/if}}{{#if tools.move}}<a href="javascript:;" class="mailpoet_tool mailpoet_move_block" title="<%= __('Drag to move') %>">
|
||||
<%= source('newsletter/templates/svg/block-tools/move.svg') %>
|
||||
</a>{{/if}}<div class="clearfix"></div>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<h3><%= __('Post selection') %></h3>
|
||||
<div class="mailpoet_settings_posts_selection"></div>
|
||||
<div class="mailpoet_settings_posts_display_options mailpoet_hidden"></div>
|
||||
<div class="mailpoet_settings_posts_display_options mailpoet_closed"></div>
|
||||
<div class="mailpoet_settings_posts_controls">
|
||||
<div class="mailpoet_form_field">
|
||||
<a href="javascript:;" class="mailpoet_settings_posts_show_post_selection mailpoet_hidden"><%= __('Back to selection') %></a>
|
||||
|
@ -1,10 +0,0 @@
|
||||
<% extends 'layout.html' %>
|
||||
|
||||
<% block content %>
|
||||
<div id="queue_container"></div>
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
<script>
|
||||
var queueDaemon = <%= daemon|raw %>
|
||||
</script>
|
||||
<% endblock %>
|
@ -67,13 +67,13 @@
|
||||
<label for="settings[notification_reply_name]"><%= __('Reply-to') %></label>
|
||||
<input type="text"
|
||||
id="settings[notification_reply_name]"
|
||||
name="notification[reply_to][name]"
|
||||
value="<%= settings.notification.reply_to.name %>"
|
||||
name="reply_to[name]"
|
||||
value="<%= settings.reply_to.name %>"
|
||||
placeholder="<%= __('Your name') %>" />
|
||||
<input type="text"
|
||||
id="settings[notification_reply_email]"
|
||||
name="notification[reply_to][address]"
|
||||
value="<%= settings.notification.reply_to.address %>"
|
||||
name="reply_to[address]"
|
||||
value="<%= settings.reply_to.address %>"
|
||||
placeholder="info@mydomain.com" />
|
||||
</p>
|
||||
</td>
|
||||
|
@ -10,13 +10,21 @@
|
||||
}
|
||||
} %>
|
||||
|
||||
<!-- smtp: method -->
|
||||
<!-- mta: group -->
|
||||
<input
|
||||
type="hidden"
|
||||
id="mta_group"
|
||||
name="mta_group"
|
||||
value="<%= settings.mta_group %>"
|
||||
/>
|
||||
<!-- mta: method -->
|
||||
<input
|
||||
type="hidden"
|
||||
id="mta_method"
|
||||
name="mta[method]"
|
||||
value="<%= settings.mta.method %>"
|
||||
/>
|
||||
|
||||
<!-- mta: sending frequency -->
|
||||
<input
|
||||
type="hidden"
|
||||
@ -51,8 +59,8 @@
|
||||
<!-- smtp: available sending methods -->
|
||||
<ul class="mailpoet_sending_methods clearfix">
|
||||
<li
|
||||
data-method="mailpoet"
|
||||
<% if(settings.mta.method == 'mailpoet') %>class="mailpoet_active"<% endif %>
|
||||
data-group="mailpoet"
|
||||
<% if(settings.mta_group == 'mailpoet') %>class="mailpoet_active"<% endif %>
|
||||
>
|
||||
<h3>
|
||||
<img
|
||||
@ -80,8 +88,8 @@
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
data-method="website"
|
||||
<% if(settings.mta.method == 'website') %>class="mailpoet_active"<% endif %>
|
||||
data-group="website"
|
||||
<% if(settings.mta_group == 'website') %>class="mailpoet_active"<% endif %>
|
||||
>
|
||||
<h3><%= __('Your own website') %></h3>
|
||||
|
||||
@ -100,8 +108,8 @@
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
data-method="smtp"
|
||||
<% if(settings.mta.method == 'smtp') %>class="mailpoet_active"<% endif %>
|
||||
data-group="smtp"
|
||||
<% if(settings.mta_group == 'smtp') %>class="mailpoet_active"<% endif %>
|
||||
>
|
||||
<h3><%= __('Third party') %></h3>
|
||||
|
||||
@ -125,7 +133,7 @@
|
||||
<!-- Sending Method: MailPoet -->
|
||||
<div
|
||||
class="mailpoet_sending_method"
|
||||
data-method="mailpoet"
|
||||
data-group="mailpoet"
|
||||
style="display:none;"
|
||||
>
|
||||
<h3><%= __('Open a free account with MailPoet, and get:') %></h3>
|
||||
@ -163,10 +171,10 @@
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
class="regular-text"
|
||||
id="mailpoet_api_key"
|
||||
size="40"
|
||||
name="api_key"
|
||||
value="<%= settings.api_key %>"
|
||||
name="mta[mailpoet_api_key]"
|
||||
value="<%=- settings.mta.mailpoet_api_key -%>"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@ -177,60 +185,11 @@
|
||||
<!-- Sending Method: Website -->
|
||||
<div
|
||||
class="mailpoet_sending_method"
|
||||
data-method="website"
|
||||
data-group="website"
|
||||
style="display:none;"
|
||||
>
|
||||
<table class="form-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="mailpoet_mta_local_method">
|
||||
<%= __('Delivery method') %>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<!-- local sending method: mail / sendmail / wp_mail -->
|
||||
<p>
|
||||
<label>
|
||||
<input type="radio"
|
||||
name="mta[local_method]"
|
||||
value="mail"
|
||||
<%
|
||||
if not(settings.mta.local_method)
|
||||
or (settings.mta.local_method == 'mail')
|
||||
%>checked="checked"<% endif %>
|
||||
/>PHP Mail
|
||||
</label>
|
||||
</p>
|
||||
<p class="description"><%= __('This email engine works on 95% of servers.') %></p>
|
||||
|
||||
<p>
|
||||
<label>
|
||||
<input type="radio"
|
||||
name="mta[local_method]"
|
||||
value="sendmail"
|
||||
<%
|
||||
if(settings.mta.local_method == 'sendmail')
|
||||
%>checked="checked"<% endif %>
|
||||
/>Sendmail
|
||||
</label>
|
||||
</p>
|
||||
<p class="description"><%= __('This method works on 5% of servers.') %></p>
|
||||
|
||||
<p>
|
||||
<label>
|
||||
<input type="radio"
|
||||
name="mta[local_method]"
|
||||
value="wp_mail"
|
||||
<%
|
||||
if(settings.mta.local_method == 'wp_mail')
|
||||
%>checked="checked"<% endif %>
|
||||
/>WP Mail
|
||||
</label>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="mailpoet_web_host">
|
||||
<%= __('Sending frequency') %>
|
||||
@ -327,7 +286,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Sending Method: SMTP -->
|
||||
<div class="mailpoet_sending_method" data-method="smtp" style="display:none;">
|
||||
<div class="mailpoet_sending_method" data-group="smtp" style="display:none;">
|
||||
<table class="form-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
@ -352,6 +311,7 @@
|
||||
value="<%= host_key %>"
|
||||
data-emails="<%= host.emails %>"
|
||||
data-interval="<%= host.interval %>"
|
||||
data-fields="<%= host.fields | join(',') %>"
|
||||
<% if(settings.smtp_provider == host_key) %>
|
||||
selected="selected"
|
||||
<% endif %>
|
||||
@ -413,9 +373,9 @@
|
||||
</td>
|
||||
</tr>
|
||||
<!-- smtp: host -->
|
||||
<tr class="mailpoet_smtp_field">
|
||||
<tr class="mailpoet_smtp_field" data-field="host">
|
||||
<th scope="row">
|
||||
<label for="settings[mta_smtp_host]">
|
||||
<label for="settings[mta_host]">
|
||||
<%= __('SMTP Hostname') %>
|
||||
<p class="description">
|
||||
<%= __('e.g.:smtp.mydomain.com') %>
|
||||
@ -425,78 +385,190 @@
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
id="settings[mta_smtp_host]"
|
||||
name="mta[smtp][host]"
|
||||
value="<%= settings.mta.smtp.host %>" />
|
||||
class="regular-text"
|
||||
id="settings[mta_host]"
|
||||
name="mta[host]"
|
||||
value="<%= settings.mta.host %>" />
|
||||
</td>
|
||||
</tr>
|
||||
<!-- smtp: login -->
|
||||
<tr id="mta_smtp_login" class="mailpoet_smtp_field">
|
||||
<!-- smtp: port -->
|
||||
<tr class="mailpoet_smtp_field" data-field="port">
|
||||
<th scope="row">
|
||||
<label for="settings[mta_smtp_login]">
|
||||
<label for="settings[mta_port]">
|
||||
<%= __('SMTP Port') %>
|
||||
<p class="description">
|
||||
</p>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input
|
||||
type="number"
|
||||
max="65535"
|
||||
min="1"
|
||||
maxlength="5"
|
||||
style="width:5em;"
|
||||
id="settings[mta_port]"
|
||||
name="mta[port]"
|
||||
value="<%= settings.mta.port %>"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- smtp: amazon region -->
|
||||
<tr class="mailpoet_smtp_field" data-field="region">
|
||||
<th scope="row">
|
||||
<label for="settings[mta_region]">
|
||||
<%= __('Region') %>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<select
|
||||
id="settings[mta_region]"
|
||||
name="mta[region]"
|
||||
value="<% if(settings.mta_group == 'smtp') %>
|
||||
<%=- settings.mta.region -%>
|
||||
<% endif %>"
|
||||
>
|
||||
<% for region, server in hosts.smtp.AmazonSES.regions %>
|
||||
<option value="<%= server %>"><%= region %></option>
|
||||
<% endfor %>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- smtp: amazon access_key -->
|
||||
<tr class="mailpoet_smtp_field" data-field="access_key">
|
||||
<th scope="row">
|
||||
<label for="settings[mta_access_key]">
|
||||
<%= __('Access Key') %>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
class="regular-text"
|
||||
id="settings[mta_access_key]"
|
||||
|
||||
name="mta[access_key]"
|
||||
value="<% if(settings.mta_group == 'smtp') %>
|
||||
<%=- settings.mta.access_key -%>
|
||||
<% endif %>"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- smtp: amazon secret_key -->
|
||||
<tr class="mailpoet_smtp_field" data-field="secret_key">
|
||||
<th scope="row">
|
||||
<label for="settings[mta_secret_key]">
|
||||
<%= __('Secret Key') %>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
class="regular-text"
|
||||
id="settings[mta_secret_key]"
|
||||
|
||||
name="mta[secret_key]"
|
||||
value="<% if(settings.mta_group == 'smtp') %>
|
||||
<%=- settings.mta.secret_key -%>
|
||||
<% endif %>"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- smtp: domain -->
|
||||
<tr class="mailpoet_smtp_field" data-field="domain">
|
||||
<th scope="row">
|
||||
<label for="settings[mta_domain]">
|
||||
<%= __('Domain') %>
|
||||
<p class="description">
|
||||
<%= __('e.g.:smtp.mydomain.com') %>
|
||||
</p>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
class="regular-text"
|
||||
id="settings[mta_host]"
|
||||
name="mta[host]"
|
||||
value="<%= settings.mta.host %>" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- smtp: api key -->
|
||||
<tr class="mailpoet_smtp_field" data-field="api_key">
|
||||
<th scope="row">
|
||||
<label for="settings[mta_api_key]">
|
||||
<%= __('API Key') %>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
class="regular-text"
|
||||
id="settings[mta_api_key]"
|
||||
name="mta[api_key]"
|
||||
value="<%=- settings.mta.api_key -%>"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- smtp: login -->
|
||||
<tr id="mta_login" class="mailpoet_smtp_field" data-field="login">
|
||||
<th scope="row">
|
||||
<label for="settings[mta_login]">
|
||||
<%= __('Login') %>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
id="settings[mta_smtp_login]"
|
||||
name="mta[smtp][login]"
|
||||
value="<%= settings.mta.smtp.login %>"
|
||||
class="regular-text"
|
||||
id="settings[mta_login]"
|
||||
name="mta[login]"
|
||||
value="<%= settings.mta.login %>"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- smtp: password -->
|
||||
<tr id="mta_smtp_password" class="mailpoet_smtp_field">
|
||||
<tr id="mta_password" class="mailpoet_smtp_field" data-field="password">
|
||||
<th scope="row">
|
||||
<label for="settings[mta_smtp_password]">
|
||||
<%= __('Password / API key') %>
|
||||
<label for="settings[mta_password]">
|
||||
<%= __('Password') %>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input
|
||||
type="password"
|
||||
id="settings[mta_smtp_password]"
|
||||
name="mta[smtp][password]"
|
||||
value="<%= settings.mta.smtp.password %>"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- smtp: port -->
|
||||
<tr class="mailpoet_smtp_field">
|
||||
<th scope="row">
|
||||
<label for="settings[mta_smtp_port]">
|
||||
<%= __('SMTP Port') %>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
id="settings[mta_smtp_port]"
|
||||
name="mta[smtp][port]"
|
||||
value="<%= settings.mta.smtp.port %>"
|
||||
class="regular-text"
|
||||
id="settings[mta_password]"
|
||||
name="mta[password]"
|
||||
value="<%= settings.mta.password %>"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- smtp: security protocol -->
|
||||
<tr class="mailpoet_smtp_field">
|
||||
<tr class="mailpoet_smtp_field" data-field="encryption">
|
||||
<th scope="row">
|
||||
<label for="settings[mta_smtp_secure]">
|
||||
<label for="settings[mta_encryption]">
|
||||
<%= __('Secure connection') %>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<select id="settings[mta_smtp_secure]" name="mta[smtp][secure]">
|
||||
<select id="settings[mta_encryption]" name="mta[encryption]">
|
||||
<option value=""><%= __('No') %></option>
|
||||
<option
|
||||
value="ssl"
|
||||
<% if(settings.mta.smtp.secure == 'ssl') %>
|
||||
<% if(settings.mta.encryption == 'ssl') %>
|
||||
selected="selected"
|
||||
<% endif %>
|
||||
>SSL</option>
|
||||
<option
|
||||
value="tls"
|
||||
<% if(settings.mta.smtp.secure == 'tls') %>
|
||||
<% if(settings.mta.encryption == 'tls') %>
|
||||
selected="selected"
|
||||
<% endif %>
|
||||
>TLS</option>
|
||||
@ -504,7 +576,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<!-- smtp: authentication -->
|
||||
<tr class="mailpoet_smtp_field">
|
||||
<tr class="mailpoet_smtp_field" data-field="authentication">
|
||||
<th scope="row">
|
||||
<label>
|
||||
<%= __('Authentication') %>
|
||||
@ -518,8 +590,10 @@
|
||||
<input
|
||||
type="radio"
|
||||
value="1"
|
||||
name="mta[smtp][authenticate]"
|
||||
<% if(settings.mta.smtp.authenticate) %>
|
||||
name="mta[authentication]"
|
||||
<%
|
||||
if not(settings.mta.authentication)
|
||||
or (settings.mta.authentication == "1") %>
|
||||
checked="checked"
|
||||
<% endif %>
|
||||
/><%= __('Yes') %>
|
||||
@ -528,9 +602,9 @@
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
value=""
|
||||
name="mta[smtp][authenticate]"
|
||||
<% if not(settings.mta.smtp.authenticate) %>
|
||||
value="-1"
|
||||
name="mta[authentication]"
|
||||
<% if(settings.mta.authentication == "-1") %>
|
||||
checked="checked"
|
||||
<% endif %>
|
||||
/><%= __('No') %>
|
||||
@ -583,6 +657,7 @@
|
||||
<%= __('Key') %>
|
||||
<input
|
||||
type="text"
|
||||
class="regular-text"
|
||||
onClick="this.focus();this.select();"
|
||||
readonly="readonly"
|
||||
value="wys._domainkey"
|
||||
@ -594,7 +669,8 @@
|
||||
<%= __('Value') %>
|
||||
<input
|
||||
type="text"
|
||||
size="40"
|
||||
class="regular-text"
|
||||
|
||||
onClick="this.focus();this.select();"
|
||||
readonly="readonly"
|
||||
value="v=DKIM1;s=email;t=s;p=<%= settings.dkim.public_key %>"
|
||||
@ -660,17 +736,39 @@
|
||||
var data = $('#mailpoet_settings_form').serializeObject();
|
||||
// get test email and include it in data
|
||||
var recipient = $('#mailpoet_mta_test_email').val();
|
||||
// get currently selected method
|
||||
var mta_method = (
|
||||
$('.mailpoet_sending_method:visible').data('method') !== undefined
|
||||
)
|
||||
? $('.mailpoet_sending_method:visible').data('method')
|
||||
: $('#mta_method').val();
|
||||
|
||||
alert(
|
||||
'Sending a test email to: '+recipient+
|
||||
' using sending method: '+mta_method
|
||||
var settings = jQuery('#mailpoet_settings_form').serializeObject();
|
||||
var mailer = settings.mta;
|
||||
mailer.method = getMethodFromGroup(
|
||||
($('.mailpoet_sending_method:visible').data('group') !== undefined)
|
||||
? $('.mailpoet_sending_method:visible').data('group')
|
||||
: $('#mta_group').val()
|
||||
);
|
||||
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'mailer',
|
||||
action: 'send',
|
||||
data: {
|
||||
mailer: mailer,
|
||||
newsletter: {
|
||||
subject: "<%= __('Sending method test.') %>",
|
||||
body: {
|
||||
text: "<%= __('Yup, it works. You can start blasting away emails to the moon.') %>"
|
||||
}
|
||||
},
|
||||
subscriber: {
|
||||
first_name: "<%= current_user.display_name %>",
|
||||
last_name: "",
|
||||
email: recipient
|
||||
}
|
||||
}
|
||||
}).done(function(response) {
|
||||
if(response.result === true) {
|
||||
MailPoet.Notice.success("The email has been sent! Check your inbox.");
|
||||
} else {
|
||||
MailPoet.Notice.error("The email could not be sent. Please check your settings.");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// sending frequency update based on selected provider
|
||||
@ -695,18 +793,18 @@
|
||||
// save configuration of a sending method
|
||||
$('.mailpoet_mta_setup_save').on('click', function() {
|
||||
// get selected method
|
||||
var method = $('.mailpoet_sending_method:visible').data('method'),
|
||||
emails = $('#'+method+'_frequency_emails').val(),
|
||||
interval = $('#'+method+'_frequency_interval').val();
|
||||
var group = $('.mailpoet_sending_method:visible').data('group'),
|
||||
emails = $('#'+group+'_frequency_emails').val(),
|
||||
interval = $('#'+group+'_frequency_interval').val();
|
||||
|
||||
// set sending method
|
||||
if(method === undefined) {
|
||||
if(group === undefined) {
|
||||
MailPoet.Notice.error(
|
||||
"<%= __('You have selected an invalid sending method.') %>"
|
||||
);
|
||||
} else {
|
||||
if(
|
||||
method === 'mailpoet'
|
||||
group === 'mailpoet'
|
||||
&& $('#mailpoet_api_key').val().trim().length === 0
|
||||
) {
|
||||
MailPoet.Notice.error(
|
||||
@ -716,7 +814,7 @@
|
||||
}
|
||||
|
||||
// set new sending method active
|
||||
setSendingMethod(method);
|
||||
setSendingMethodGroup(group);
|
||||
|
||||
// update sending frequency values
|
||||
$('#mta_frequency_emails').val(emails);
|
||||
@ -730,19 +828,42 @@
|
||||
}
|
||||
});
|
||||
|
||||
function setSendingMethod(method) {
|
||||
function setSendingMethodGroup(group) {
|
||||
// deactivate other sending methods
|
||||
$('.mailpoet_sending_methods .mailpoet_active')
|
||||
.removeClass('mailpoet_active');
|
||||
|
||||
// set active sending method
|
||||
$('.mailpoet_sending_methods li[data-method="'+method+'"]')
|
||||
$('.mailpoet_sending_methods li[data-group="'+group+'"]')
|
||||
.addClass('mailpoet_active');
|
||||
|
||||
// set smtp method value
|
||||
$('#mta_group').val(group);
|
||||
|
||||
var method = getMethodFromGroup(group);
|
||||
|
||||
$('#mta_method').val(method);
|
||||
}
|
||||
|
||||
function getMethodFromGroup(group) {
|
||||
var group = group || 'website';
|
||||
switch(group) {
|
||||
case 'mailpoet':
|
||||
return 'MailPoet';
|
||||
break;
|
||||
case 'website':
|
||||
return 'WPMail';
|
||||
break;
|
||||
case 'smtp':
|
||||
var method = $('#mailpoet_smtp_provider').val();
|
||||
if(method === 'manual') {
|
||||
return 'SMTP';
|
||||
}
|
||||
return method;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// cancel configuration of a sending method
|
||||
$('.mailpoet_mta_setup_cancel').on('click', function() {
|
||||
// back to selection of sending methods
|
||||
@ -757,20 +878,27 @@
|
||||
function setProviderForm() {
|
||||
// check provider
|
||||
var provider = $(this).find('option:selected').first();
|
||||
var fields = provider.data('fields');
|
||||
|
||||
if(provider.val() === 'sendgrid') {
|
||||
$('.mailpoet_smtp_field').hide();
|
||||
// show only login & password fields
|
||||
$('#mta_smtp_login, #mta_smtp_password').show();
|
||||
} else if(provider.val() === 'elasticemail') {
|
||||
$('.mailpoet_smtp_field').hide();
|
||||
// show only password field
|
||||
$('#mta_smtp_password').show();
|
||||
if(fields === undefined) {
|
||||
fields = [
|
||||
'host',
|
||||
'port',
|
||||
'login',
|
||||
'password',
|
||||
'authentication',
|
||||
'encryption'
|
||||
];
|
||||
} else {
|
||||
// display all fields
|
||||
$('.mailpoet_smtp_field').show();
|
||||
fields = fields.split(',');
|
||||
}
|
||||
|
||||
$('.mailpoet_smtp_field').hide();
|
||||
|
||||
fields.map(function(field) {
|
||||
$('.mailpoet_smtp_field[data-field="'+field+'"]').show();
|
||||
});
|
||||
|
||||
// update sending frequency
|
||||
renderSMTPSendingFrequency(provider);
|
||||
}
|
||||
@ -791,6 +919,8 @@
|
||||
host.data('emails') || <%= default_frequency.website.emails %>;
|
||||
var interval =
|
||||
host.data('interval') || <%= default_frequency.website.interval %>;
|
||||
var fields =
|
||||
host.data('fields') || '';
|
||||
|
||||
if(host.val() === 'manual' ) {
|
||||
// hide sending frequency
|
||||
|
@ -77,7 +77,7 @@ baseConfig = {
|
||||
{
|
||||
include: /html2canvas.js$/,
|
||||
loader: 'expose-loader?html2canvas',
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
@ -92,7 +92,8 @@ config.push(_.extend({}, baseConfig, {
|
||||
'ajax',
|
||||
'modal',
|
||||
'notice',
|
||||
'jquery.serialize_object'
|
||||
'jquery.serialize_object',
|
||||
'parsleyjs'
|
||||
],
|
||||
admin: [
|
||||
'subscribers/subscribers.jsx',
|
||||
@ -103,7 +104,7 @@ config.push(_.extend({}, baseConfig, {
|
||||
'subscribers/importExport/import.js',
|
||||
'subscribers/importExport/export.js',
|
||||
'helpscout',
|
||||
'queue.jsx'
|
||||
'cron.jsx'
|
||||
],
|
||||
form_editor: [
|
||||
'form_editor/form_editor.js',
|
||||
|
Reference in New Issue
Block a user