Compare commits
94 Commits
3.0.0-beta
...
3.0.0-beta
Author | SHA1 | Date | |
---|---|---|---|
e126278e32 | |||
9d2651083d | |||
1e1ae4c3cf | |||
385f5ab535 | |||
dc371d76ca | |||
be0c9b71d8 | |||
6e250d9317 | |||
afeaa00fc7 | |||
6575d1579d | |||
282199d362 | |||
3e5c46e8f3 | |||
71515f3ff0 | |||
934a8d5bf8 | |||
6be2464c86 | |||
ace8a52262 | |||
7d37d279cd | |||
5525a959a8 | |||
a421dbd674 | |||
bedfc4f80c | |||
af2a6b2559 | |||
cb8c32e171 | |||
8abec208fc | |||
5264cb1cf4 | |||
47e0e1a836 | |||
e602612cd6 | |||
9f7ae122e3 | |||
22caba31e3 | |||
82ab4acb8d | |||
9466be4793 | |||
a2e2090cbb | |||
d100d61403 | |||
d781ef6d01 | |||
1dafc4da04 | |||
063c271e40 | |||
a53007e30b | |||
c616b3299a | |||
86eab0d8f8 | |||
bfd35b1cdc | |||
461203279b | |||
b9c45b46ba | |||
1a42ae4cca | |||
f2ad7ee34c | |||
37017ef69d | |||
157725c300 | |||
98d6f55a6e | |||
425d45a862 | |||
438b4fb1ec | |||
1f91d40def | |||
c5e1def2f9 | |||
65ba834742 | |||
19dc048858 | |||
938279bf8f | |||
dd2df429ef | |||
c4e05912ff | |||
bb34e8477f | |||
32f7d7771f | |||
e77717c4c2 | |||
d27d5ae5dd | |||
168263f0ea | |||
f1ced11809 | |||
c2546e8aed | |||
b7ef191641 | |||
2220a13399 | |||
31ec7475c8 | |||
bfdc13a8d1 | |||
9a3c4ff7de | |||
25410eb09c | |||
122f88668a | |||
9c35eb9723 | |||
fa528ed1ff | |||
1a7623bc4a | |||
3a4a37e1af | |||
888a566dda | |||
3567779faf | |||
cb5b0bd753 | |||
88d0511adb | |||
a4a654cfd5 | |||
4d3c90ce0d | |||
f51aba4dbd | |||
f651c06cb9 | |||
940328c608 | |||
ce85600753 | |||
5666116645 | |||
815461a851 | |||
1102467e39 | |||
a5ee865271 | |||
59bda6cf6c | |||
a4d9d55b09 | |||
8cf918013d | |||
7789a10026 | |||
ce0ad33c32 | |||
63d1fe17a9 | |||
da92795635 | |||
915f8b5865 |
@ -15,7 +15,7 @@
|
||||
padding 15px 15px 0 15px
|
||||
margin 0 25px 25px 0
|
||||
width 300px
|
||||
height 250px
|
||||
height 300px
|
||||
border 1px solid #dedede
|
||||
background-color #fff
|
||||
h3
|
||||
|
@ -77,7 +77,7 @@ const messages = {
|
||||
const bulk_actions = [
|
||||
{
|
||||
name: 'trash',
|
||||
label: MailPoet.I18n.t('trash'),
|
||||
label: MailPoet.I18n.t('moveToTrash'),
|
||||
onSuccess: messages.onTrash
|
||||
}
|
||||
];
|
||||
|
@ -82,7 +82,7 @@ const ListingItem = React.createClass({
|
||||
null,
|
||||
this.props.item.id
|
||||
) }>
|
||||
{MailPoet.I18n.t('trash')}
|
||||
{MailPoet.I18n.t('moveToTrash')}
|
||||
</a>
|
||||
</span>
|
||||
);
|
||||
@ -873,4 +873,4 @@ const Listing = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Listing;
|
||||
module.exports = Listing;
|
||||
|
@ -98,7 +98,7 @@ const columns = [
|
||||
const bulk_actions = [
|
||||
{
|
||||
name: 'trash',
|
||||
label: MailPoet.I18n.t('trash'),
|
||||
label: MailPoet.I18n.t('moveToTrash'),
|
||||
onSuccess: messages.onTrash
|
||||
}
|
||||
];
|
||||
@ -340,4 +340,4 @@ const NewsletterListNotification = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = NewsletterListNotification;
|
||||
module.exports = NewsletterListNotification;
|
||||
|
@ -93,7 +93,7 @@ const columns = [
|
||||
const bulk_actions = [
|
||||
{
|
||||
name: 'trash',
|
||||
label: MailPoet.I18n.t('trash'),
|
||||
label: MailPoet.I18n.t('moveToTrash'),
|
||||
onSuccess: messages.onTrash
|
||||
}
|
||||
];
|
||||
@ -223,4 +223,4 @@ const NewsletterListStandard = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = NewsletterListStandard;
|
||||
module.exports = NewsletterListStandard;
|
||||
|
@ -95,7 +95,7 @@ const columns = [
|
||||
const bulk_actions = [
|
||||
{
|
||||
name: 'trash',
|
||||
label: MailPoet.I18n.t('trash'),
|
||||
label: MailPoet.I18n.t('moveToTrash'),
|
||||
onSuccess: messages.onTrash
|
||||
}
|
||||
];
|
||||
@ -369,4 +369,4 @@ const NewsletterListWelcome = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = NewsletterListWelcome;
|
||||
module.exports = NewsletterListWelcome;
|
||||
|
@ -90,7 +90,7 @@ const messages = {
|
||||
const bulk_actions = [
|
||||
{
|
||||
name: 'trash',
|
||||
label: MailPoet.I18n.t('trash'),
|
||||
label: MailPoet.I18n.t('moveToTrash'),
|
||||
onSuccess: messages.onTrash
|
||||
}
|
||||
];
|
||||
|
@ -200,7 +200,7 @@ const bulk_actions = [
|
||||
},
|
||||
{
|
||||
name: 'trash',
|
||||
label: MailPoet.I18n.t('trash'),
|
||||
label: MailPoet.I18n.t('moveToTrash'),
|
||||
onSuccess: messages.onTrash
|
||||
}
|
||||
];
|
||||
|
3
build.sh
3
build.sh
@ -50,17 +50,20 @@ rm -rf $plugin_name/vendor/soundasleep/html2text/tests
|
||||
rm -rf $plugin_name/vendor/mtdowling/cron-expression/tests
|
||||
rm -rf $plugin_name/vendor/swiftmailer/swiftmailer/tests
|
||||
rm -rf $plugin_name/vendor/cerdic/css-tidy/testing
|
||||
rm -rf $plugin_name/vendor/sabberworm/php-css-parser/tests
|
||||
|
||||
# Remove risky files from 3rd party extensions
|
||||
echo '[BUILD] Removing risky and demo files from vendor libraries'
|
||||
rm -f $plugin_name/vendor/j4mie/idiorm/demo.php
|
||||
rm -f $plugin_name/vendor/cerdic/css-tidy/css_optimiser.php
|
||||
rm -f $plugin_name/assets/js/lib/tinymce/package.json
|
||||
|
||||
# Copy release files.
|
||||
echo '[BUILD] Copying release files'
|
||||
cp license.txt $plugin_name
|
||||
cp index.php $plugin_name
|
||||
cp $plugin_name.php $plugin_name
|
||||
cp mailpoet_initializer.php $plugin_name
|
||||
cp readme.txt $plugin_name
|
||||
cp uninstall.php $plugin_name
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
namespace MailPoet\API;
|
||||
use \MailPoet\Util\Security;
|
||||
use MailPoet\Util\Security;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
@ -38,7 +38,7 @@ class API {
|
||||
if($this->checkToken() === false) {
|
||||
$error_response = new ErrorResponse(
|
||||
array(
|
||||
Error::UNAUTHORIZED => __('Invalid request.', 'mailpoet')
|
||||
Error::UNAUTHORIZED => __('Invalid request', 'mailpoet')
|
||||
),
|
||||
array(),
|
||||
Response::STATUS_UNAUTHORIZED
|
||||
@ -64,7 +64,7 @@ class API {
|
||||
// throw exception bad request
|
||||
$error_response = new ErrorResponse(
|
||||
array(
|
||||
Error::BAD_REQUEST => __('Invalid request.', 'mailpoet')
|
||||
Error::BAD_REQUEST => __('Invalid request', 'mailpoet')
|
||||
),
|
||||
array(),
|
||||
Response::STATUS_BAD_REQUEST
|
||||
@ -149,4 +149,4 @@ class API {
|
||||
$global .= '</script>';
|
||||
echo $global;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,9 +27,9 @@ abstract class Endpoint {
|
||||
function badRequest($errors = array(), $meta = array()) {
|
||||
if(empty($errors)) {
|
||||
$errors = array(
|
||||
Error::BAD_REQUEST => __('Invalid request parameters.', 'mailpoet')
|
||||
Error::BAD_REQUEST => __('Invalid request parameters', 'mailpoet')
|
||||
);
|
||||
}
|
||||
return new ErrorResponse($errors, $meta, Response::STATUS_BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
use MailPoet\API\Endpoint as APIEndpoint;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
use \MailPoet\Models\CustomField;
|
||||
use MailPoet\API\Endpoint as APIEndpoint;
|
||||
use MailPoet\API\Error as APIError;
|
||||
use MailPoet\Models\CustomField;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
|
@ -3,11 +3,11 @@ namespace MailPoet\API\Endpoints;
|
||||
use MailPoet\API\Endpoint as APIEndpoint;
|
||||
use MailPoet\API\Error as APIError;
|
||||
|
||||
use \MailPoet\Models\Form;
|
||||
use \MailPoet\Models\StatisticsForms;
|
||||
use \MailPoet\Form\Renderer as FormRenderer;
|
||||
use \MailPoet\Listing;
|
||||
use \MailPoet\Form\Util;
|
||||
use MailPoet\Models\Form;
|
||||
use MailPoet\Models\StatisticsForms;
|
||||
use MailPoet\Form\Renderer as FormRenderer;
|
||||
use MailPoet\Listing;
|
||||
use MailPoet\Form\Util;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
|
@ -1,10 +1,8 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
use MailPoet\API\Endpoint as APIEndpoint;
|
||||
|
||||
use MailPoet\Subscribers\ImportExport\Import\MailChimp;
|
||||
use MailPoet\Models\CustomField;
|
||||
use MailPoet\Models\Segment;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
use MailPoet\API\Endpoint as APIEndpoint;
|
||||
use MailPoet\API\Error as APIError;
|
||||
|
||||
use MailPoet\Models\NewsletterTemplate;
|
||||
|
||||
|
@ -340,11 +340,10 @@ class Newsletters extends APIEndpoint {
|
||||
}
|
||||
|
||||
// get preview url
|
||||
$subscriber = Subscriber::getCurrentWPUser();
|
||||
$newsletter->preview_url = NewsletterUrl::getViewInBrowserUrl(
|
||||
NewsletterUrl::TYPE_LISTING_EDITOR,
|
||||
$newsletter,
|
||||
$subscriber,
|
||||
$subscriber = null,
|
||||
$queue
|
||||
);
|
||||
|
||||
@ -435,4 +434,4 @@ class Newsletters extends APIEndpoint {
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +1,11 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
use MailPoet\API\Endpoint as APIEndpoint;
|
||||
use MailPoet\API\Error as APIError;
|
||||
|
||||
use \MailPoet\Models\Segment;
|
||||
use \MailPoet\Models\SubscriberSegment;
|
||||
use \MailPoet\Models\SegmentFilter;
|
||||
use \MailPoet\Listing;
|
||||
use \MailPoet\Segments\WP;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Listing;
|
||||
use MailPoet\Segments\WP;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
|
@ -5,11 +5,7 @@ use MailPoet\API\Error as APIError;
|
||||
|
||||
use MailPoet\Mailer\Mailer;
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\NewsletterOption;
|
||||
use MailPoet\Models\NewsletterOptionField;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Models\SubscriberSegment;
|
||||
use MailPoet\Newsletter\Scheduler\Scheduler;
|
||||
use MailPoet\Models\SendingQueue as SendingQueueModel;
|
||||
use MailPoet\Util\Helpers;
|
||||
|
67
lib/API/Endpoints/Services.php
Normal file
67
lib/API/Endpoints/Services.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use MailPoet\API\Endpoint as APIEndpoint;
|
||||
use MailPoet\API\Error as APIError;
|
||||
use MailPoet\Services\Bridge;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Services extends APIEndpoint {
|
||||
public $bridge;
|
||||
|
||||
function __construct() {
|
||||
$this->bridge = new Bridge();
|
||||
}
|
||||
|
||||
function verifyMailPoetKey($data = array()) {
|
||||
$key = isset($data['key']) ? trim($data['key']) : null;
|
||||
|
||||
if(!$key) {
|
||||
return $this->badRequest(array(
|
||||
APIError::BAD_REQUEST => __('Please specify a key.', 'mailpoet')
|
||||
));
|
||||
}
|
||||
|
||||
try {
|
||||
$result = $this->bridge->checkKey($key);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
|
||||
$state = !empty($result['state']) ? $result['state'] : null;
|
||||
|
||||
$success_message = null;
|
||||
if($state == Bridge::MAILPOET_KEY_VALID) {
|
||||
$success_message = __('Your MailPoet API key is valid!', 'mailpoet');
|
||||
} elseif($state == Bridge::MAILPOET_KEY_EXPIRING) {
|
||||
$success_message = sprintf(
|
||||
__('Your MailPoet key expires on %s!', 'mailpoet'),
|
||||
Carbon::createFromTimestamp(strtotime($result['data']['expire_at']))
|
||||
->format('Y-m-d')
|
||||
);
|
||||
}
|
||||
|
||||
if($success_message) {
|
||||
return $this->successResponse(array('message' => $success_message));
|
||||
}
|
||||
|
||||
switch($state) {
|
||||
case Bridge::MAILPOET_KEY_INVALID:
|
||||
$error = __('Your MailPoet key is invalid!', 'mailpoet');
|
||||
break;
|
||||
default:
|
||||
$code = !empty($result['code']) ? $result['code'] : Bridge::CHECK_ERROR_UNKNOWN;
|
||||
$error = sprintf(
|
||||
__('Error validating API key, please try again later (code: %s)', 'mailpoet'),
|
||||
$code
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->errorResponse(array(APIError::BAD_REQUEST => $error));
|
||||
}
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
use \MailPoet\Models\Setting;
|
||||
use MailPoet\API\Endpoint as APIEndpoint;
|
||||
use MailPoet\API\Error as APIError;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Services\Bridge;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
@ -21,6 +22,13 @@ class Settings extends APIEndpoint {
|
||||
foreach($settings as $name => $value) {
|
||||
Setting::setValue($name, $value);
|
||||
}
|
||||
if(!empty($settings['mta']['mailpoet_api_key'])
|
||||
&& Bridge::isMPSendingServiceEnabled()
|
||||
) {
|
||||
$bridge = new Bridge();
|
||||
$result = $bridge->checkKey($settings['mta']['mailpoet_api_key']);
|
||||
$bridge->updateSubscriberCount($result);
|
||||
}
|
||||
return $this->successResponse(Setting::getAll());
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\Config\Activator;
|
||||
use MailPoet\API\Endpoint as APIEndpoint;
|
||||
use MailPoet\Config\Activator;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
|
@ -1,15 +1,11 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
use \MailPoet\API\Access as APIAccess;
|
||||
use MailPoet\API\Endpoint as APIEndpoint;
|
||||
use MailPoet\API\Error as APIError;
|
||||
use MailPoet\API\Access as APIAccess;
|
||||
|
||||
use MailPoet\Listing;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Models\SubscriberSegment;
|
||||
use MailPoet\Models\SubscriberCustomField;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Models\Form;
|
||||
use MailPoet\Models\StatisticsForms;
|
||||
|
||||
@ -65,10 +61,17 @@ class Subscribers extends APIEndpoint {
|
||||
$form = Form::findOne($form_id);
|
||||
unset($data['form_id']);
|
||||
|
||||
if(!$form) {
|
||||
return $this->badRequest(array(
|
||||
APIError::BAD_REQUEST => __('Please specify a valid form ID.', 'mailpoet')
|
||||
));
|
||||
}
|
||||
|
||||
$segment_ids = (!empty($data['segments'])
|
||||
? (array)$data['segments']
|
||||
: array()
|
||||
);
|
||||
$segment_ids = $form->filterSegments($segment_ids);
|
||||
unset($data['segments']);
|
||||
|
||||
if(empty($segment_ids)) {
|
||||
@ -77,6 +80,10 @@ class Subscribers extends APIEndpoint {
|
||||
));
|
||||
}
|
||||
|
||||
// only accept fields defined in the form
|
||||
$form_fields = $form->getFieldList();
|
||||
$data = array_intersect_key($data, array_flip($form_fields));
|
||||
|
||||
$subscriber = Subscriber::subscribe($data, $segment_ids);
|
||||
$errors = $subscriber->getErrors();
|
||||
|
||||
@ -91,11 +98,13 @@ class Subscribers extends APIEndpoint {
|
||||
|
||||
$form = $form->asArray();
|
||||
|
||||
if($form['settings']['on_success'] === 'page') {
|
||||
// redirect to a page on a success, pass the page url in the meta
|
||||
$meta['redirect_url'] = get_permalink($form['settings']['success_page']);
|
||||
} else if($form['settings']['on_success'] === 'url') {
|
||||
$meta['redirect_url'] = $form['settings']['success_url'];
|
||||
if(!empty($form['settings']['on_success'])) {
|
||||
if($form['settings']['on_success'] === 'page') {
|
||||
// redirect to a page on a success, pass the page url in the meta
|
||||
$meta['redirect_url'] = get_permalink($form['settings']['success_page']);
|
||||
} else if($form['settings']['on_success'] === 'url') {
|
||||
$meta['redirect_url'] = $form['settings']['success_url'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,6 +116,9 @@ class Subscribers extends APIEndpoint {
|
||||
}
|
||||
|
||||
function save($data = array()) {
|
||||
if(empty($data['segments'])) {
|
||||
$data['segments'] = array();
|
||||
}
|
||||
$subscriber = Subscriber::createOrUpdate($data);
|
||||
$errors = $subscriber->getErrors();
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
use \MailPoet\Analytics\Reporter;
|
||||
use \MailPoet\Models\Setting;
|
||||
use MailPoet\Analytics\Reporter;
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
use \MailPoet\Models\Setting;
|
||||
use \MailPoet\Util\Url;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Util\Url;
|
||||
|
||||
class Changelog {
|
||||
function __construct() {
|
||||
|
@ -1,8 +1,6 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
use MailPoet\Cron\Workers\Scheduler;
|
||||
use MailPoet\Cron\Workers\SendingQueue;
|
||||
use \MailPoet\Models\Setting;
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
class Hooks {
|
||||
function __construct() {
|
||||
|
@ -27,6 +27,7 @@ class Menu {
|
||||
$this->assets_url = $assets_url;
|
||||
$subscribers_feature = new SubscribersFeature();
|
||||
$this->subscribers_over_limit = $subscribers_feature->check();
|
||||
$this->checkMailPoetAPIKey();
|
||||
}
|
||||
|
||||
function init() {
|
||||
@ -302,6 +303,7 @@ class Menu {
|
||||
'settings' => $settings,
|
||||
'segments' => Segment::getSegmentsWithSubscriberCount(),
|
||||
'cron_trigger' => CronTrigger::getAvailableMethods(),
|
||||
'total_subscribers' => Subscriber::getTotalSubscribers(),
|
||||
'pages' => Pages::getAll(),
|
||||
'flags' => $flags,
|
||||
'current_user' => wp_get_current_user(),
|
||||
@ -387,6 +389,9 @@ class Menu {
|
||||
|
||||
function newsletters() {
|
||||
if($this->subscribers_over_limit) return $this->displaySubscriberLimitExceededTemplate();
|
||||
if(isset($this->mp_api_key_valid) && $this->mp_api_key_valid === false) {
|
||||
return $this->displayMailPoetAPIKeyInvalidTemplate();
|
||||
}
|
||||
|
||||
global $wp_roles;
|
||||
|
||||
@ -483,6 +488,39 @@ class Menu {
|
||||
exit;
|
||||
}
|
||||
|
||||
function displayMailPoetAPIKeyInvalidTemplate() {
|
||||
$this->displayPage('invalidkey.html', array(
|
||||
'subscriber_count' => Subscriber::getTotalSubscribers()
|
||||
));
|
||||
exit;
|
||||
}
|
||||
|
||||
static function isOnMailPoetAdminPage(array $exclude = null, $screen_id = null) {
|
||||
if(is_null($screen_id)) {
|
||||
if(empty($_REQUEST['page'])) {
|
||||
return false;
|
||||
}
|
||||
$screen_id = $_REQUEST['page'];
|
||||
}
|
||||
if(!empty($exclude)) {
|
||||
foreach($exclude as $slug) {
|
||||
if(stripos($screen_id, $slug) !== false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (stripos($screen_id, 'mailpoet-') !== false);
|
||||
}
|
||||
|
||||
function checkMailPoetAPIKey(ServicesChecker $checker = null) {
|
||||
if(self::isOnMailPoetAdminPage()) {
|
||||
$show_notices = isset($_REQUEST['page'])
|
||||
&& stripos($_REQUEST['page'], 'mailpoet-newsletters') === false;
|
||||
$checker = $checker ?: new ServicesChecker();
|
||||
$this->mp_api_key_valid = $checker->checkMailPoetAPIKeyValid($show_notices);
|
||||
}
|
||||
}
|
||||
|
||||
private function getLimitPerPage($model = null) {
|
||||
if($model === null) {
|
||||
return Listing\Handler::DEFAULT_LIMIT_PER_PAGE;
|
||||
@ -504,8 +542,4 @@ class Menu {
|
||||
$notice->displayWPNotice();
|
||||
}
|
||||
}
|
||||
|
||||
static function isOnMailPoetAdminPage() {
|
||||
return (!empty($_REQUEST['page']) && stripos($_REQUEST['page'], 'mailpoet-') !== false);
|
||||
}
|
||||
}
|
@ -106,7 +106,7 @@ class Migrator {
|
||||
function sendingQueues() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'type varchar(12) NULL DEFAULT NULL,',
|
||||
'type varchar(90) NULL DEFAULT NULL,',
|
||||
'newsletter_id mediumint(9) NOT NULL,',
|
||||
'newsletter_rendered_body longtext,',
|
||||
'newsletter_rendered_subject varchar(250) NULL DEFAULT NULL,',
|
||||
|
@ -3,11 +3,11 @@ namespace MailPoet\Config;
|
||||
|
||||
use MailPoet\Cron\CronTrigger;
|
||||
use MailPoet\Mailer\MailerLog;
|
||||
use \MailPoet\Models\Segment;
|
||||
use \MailPoet\Segments\WP;
|
||||
use \MailPoet\Models\Setting;
|
||||
use \MailPoet\Settings\Pages;
|
||||
use \MailPoet\Util\Helpers;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Segments\WP;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Settings\Pages;
|
||||
use MailPoet\Util\Helpers;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
@ -138,7 +138,7 @@ class Populator {
|
||||
$default_segment->hydrate(array(
|
||||
'name' => __('My First List', 'mailpoet'),
|
||||
'description' =>
|
||||
__('This list is automatically created when you install MailPoet', 'mailpoet')
|
||||
__('This list is automatically created when you install MailPoet.', 'mailpoet')
|
||||
));
|
||||
$default_segment->save();
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ class NewsletterBlank121Column {
|
||||
"blocks" => array(
|
||||
array(
|
||||
"type" => "header",
|
||||
"text" => __("Display problems? <a href=\"[link:newsletter_view_in_browser_url]\">Open this email in your web browser</a>", 'mailpoet'),
|
||||
"text" => __("Display problems? <a href=\"[link:newsletter_view_in_browser_url]\">Open this email in your web browser.</a>", 'mailpoet'),
|
||||
"styles" => array(
|
||||
"block" => array(
|
||||
"backgroundColor" => "transparent"
|
||||
@ -116,7 +116,7 @@ class NewsletterBlank121Column {
|
||||
),
|
||||
array(
|
||||
"type" => "text",
|
||||
"text" => __("<h1 style=\"text-align: center;\"><strong>Let's Get Started!</strong></h1>\n<p>It's time to design your newsletter! On the right sidebar, you'll find four menu items that will help you customize your newsletter:</p>\n<ol>\n<li>Content</li>\n<li>Layout</li>\n<li>Styles</li>\n<li>Preview</li>\n</ol>", 'mailpoet')
|
||||
"text" => __("<h1 style=\"text-align: center;\"><strong>Let's Get Started!</strong></h1>\n<p>It's time to design your newsletter! In the right sidebar, you'll find four menu items that will help you customize your newsletter:</p>\n<ol>\n<li>Content</li>\n<li>Layout</li>\n<li>Styles</li>\n<li>Preview</li>\n</ol>", 'mailpoet')
|
||||
),
|
||||
array(
|
||||
"type" => "divider",
|
||||
|
@ -52,7 +52,7 @@ class NewsletterBlank12Column {
|
||||
"blocks" => array(
|
||||
array(
|
||||
"type" => "header",
|
||||
"text" => __("Display problems? <a href=\"[link:newsletter_view_in_browser_url]\">Open this email in your web browser</a>", 'mailpoet'),
|
||||
"text" => __("Display problems? <a href=\"[link:newsletter_view_in_browser_url]\">Open this email in your web browser.</a>", 'mailpoet'),
|
||||
"styles" => array(
|
||||
"block" => array(
|
||||
"backgroundColor" => "transparent"
|
||||
|
@ -52,7 +52,7 @@ class NewsletterBlank13Column {
|
||||
"blocks" => array(
|
||||
array(
|
||||
"type" => "header",
|
||||
"text" => __("Display problems? <a href=\"[link:newsletter_view_in_browser_url]\">Open this email in your web browser</a>", 'mailpoet'),
|
||||
"text" => __("Display problems? <a href=\"[link:newsletter_view_in_browser_url]\">Open this email in your web browser.</a>", 'mailpoet'),
|
||||
"styles" => array(
|
||||
"block" => array(
|
||||
"backgroundColor" => "transparent"
|
||||
@ -116,7 +116,7 @@ class NewsletterBlank13Column {
|
||||
),
|
||||
array(
|
||||
"type" => "text",
|
||||
"text" => __("<h1 style=\"text-align: center;\"><strong>Let's Get Started! </strong></h1>\n<p></p>\n<p>It's time to design your newsletter! On the right sidebar, you'll find four menu items that will help you customize your newsletter:</p>\n<ol>\n<li>Content</li>\n<li>Layout</li>\n<li>Styles</li>\n<li>Preview</li>\n</ol>", 'mailpoet')
|
||||
"text" => __("<h1 style=\"text-align: center;\"><strong>Let's Get Started! </strong></h1>\n<p></p>\n<p>It's time to design your newsletter! In the right sidebar, you'll find four menu items that will help you customize your newsletter:</p>\n<ol>\n<li>Content</li>\n<li>Layout</li>\n<li>Styles</li>\n<li>Preview</li>\n</ol>", 'mailpoet')
|
||||
),
|
||||
array(
|
||||
"type" => "divider",
|
||||
|
@ -52,7 +52,7 @@ class NewsletterBlank1Column {
|
||||
"blocks" => array(
|
||||
array(
|
||||
"type" => "header",
|
||||
"text" => __("Display problems? <a href=\"[link:newsletter_view_in_browser_url]\">Open this email in your web browser</a>", 'mailpoet'),
|
||||
"text" => __("Display problems? <a href=\"[link:newsletter_view_in_browser_url]\">Open this email in your web browser.</a>", 'mailpoet'),
|
||||
"styles" => array(
|
||||
"block" => array(
|
||||
"backgroundColor" => "transparent"
|
||||
|
@ -52,7 +52,7 @@ class PostNotificationsBlank1Column {
|
||||
"blocks" => array(
|
||||
array(
|
||||
"type" => "header",
|
||||
"text" => __("Display problems? <a href=\"[link:newsletter_view_in_browser_url]\">Open this email in your web browser</a>", 'mailpoet'),
|
||||
"text" => __("Display problems? <a href=\"[link:newsletter_view_in_browser_url]\">Open this email in your web browser.</a>", 'mailpoet'),
|
||||
"styles" => array(
|
||||
"block" => array(
|
||||
"backgroundColor" => "transparent"
|
||||
@ -116,7 +116,7 @@ class PostNotificationsBlank1Column {
|
||||
),
|
||||
array(
|
||||
"type" => "text",
|
||||
"text" => __("<h1 style=\"text-align: center;\"><strong>Check Out Our New Blog Posts! </strong></h1>\n<p></p>\n<p>MailPoet can <span style=\"line-height: 1.6em; background-color: inherit;\"><em>automatically</em> </span><span style=\"line-height: 1.6em; background-color: inherit;\">send your new blog posts to your subscribers.</span></p>\n<p><span style=\"line-height: 1.6em; background-color: inherit;\"></span></p>\n<p><span style=\"line-height: 1.6em; background-color: inherit;\">Below, you'll find three recent posts, which are displayed automatically, thanks to the <em>Automatic Latest Content</em> widget, which can be found on the right sidebar, under <em>Content</em>.</span></p>\n<p><span style=\"line-height: 1.6em; background-color: inherit;\"></span></p>\n<p><span style=\"line-height: 1.6em; background-color: inherit;\">To edit the settings and styles of your post, simply click on a post below.</span></p>", 'mailpoet')
|
||||
"text" => __("<h1 style=\"text-align: center;\"><strong>Check Out Our New Blog Posts! </strong></h1>\n<p></p>\n<p>MailPoet can <span style=\"line-height: 1.6em; background-color: inherit;\"><em>automatically</em> </span><span style=\"line-height: 1.6em; background-color: inherit;\">send your new blog posts to your subscribers.</span></p>\n<p><span style=\"line-height: 1.6em; background-color: inherit;\"></span></p>\n<p><span style=\"line-height: 1.6em; background-color: inherit;\">Below, you'll find three recent posts, which are displayed automatically, thanks to the <em>Automatic Latest Content</em> widget, which can be found in the right sidebar, under <em>Content</em>.</span></p>\n<p><span style=\"line-height: 1.6em; background-color: inherit;\"></span></p>\n<p><span style=\"line-height: 1.6em; background-color: inherit;\">To edit the settings and styles of your post, simply click on a post below.</span></p>", 'mailpoet')
|
||||
),
|
||||
array(
|
||||
"type" => "divider",
|
||||
|
@ -70,7 +70,7 @@ class StoreDiscount {
|
||||
)
|
||||
), array(
|
||||
"type" => "text",
|
||||
"text" => __("<p></p>\n<p>Hi [subscriber:firstname | default:reader]</p>\n<p class=\"\"></p>\n<p>Fancy 15% off your next order? Use this coupon on all your favourite products from our store until Wednesday. Just enter the code on the payments page and your discount will applied.</p>", 'mailpoet')
|
||||
"text" => __("<p></p>\n<p>Hi [subscriber:firstname | default:reader]</p>\n<p class=\"\"></p>\n<p>Fancy 15% off your next order? Use this coupon on any product in our store. Expires Wednesday! To apply the discount, enter the code on the payments page.</p>", 'mailpoet')
|
||||
), array(
|
||||
"type" => "spacer",
|
||||
"styles" => array(
|
||||
@ -110,7 +110,7 @@ class StoreDiscount {
|
||||
)
|
||||
), array(
|
||||
"type" => "text",
|
||||
"text" => __("<h1 style=\"text-align: center;\"><em><strong>Get 15% discount off your next order</strong></em></h1>", 'mailpoet')
|
||||
"text" => __("<h1 style=\"text-align: center;\"><em><strong>Get a 15% off your next order</strong></em></h1>", 'mailpoet')
|
||||
), array(
|
||||
"type" => "text",
|
||||
"text" => __("<h2 style=\"text-align: center;\"><strong>USE CODE: WELOVEMAILPOET</strong></h2>", 'mailpoet')
|
||||
@ -204,7 +204,7 @@ class StoreDiscount {
|
||||
"type" => "image",
|
||||
"link" => "",
|
||||
"src" => $this->template_image_url . "/red-icycle.jpg",
|
||||
"alt" => __("red-icycle", 'mailpoet'),
|
||||
"alt" => __("red-bicycle", 'mailpoet'),
|
||||
"fullWidth" => false,
|
||||
"width" => "558px",
|
||||
"height" => "399px",
|
||||
|
@ -70,7 +70,7 @@ class TravelEmail {
|
||||
)
|
||||
), array(
|
||||
"type" => "text",
|
||||
"text" => __("<h1 style=\"text-align: center;\">Hi [subscriber:firstname | default:reader]!</h1>\n<p></p>\n<p>Greetings from New Zealand, we're here enjoying the sights and sounds (and bad smells!) of Rotarua. Yesterday we took advantage of the local amenities and visited the hot springs! </p>\n<p>Don't forget to stay up-to-date via twitter!</p>", 'mailpoet')
|
||||
"text" => __("<h1 style=\"text-align: center;\">Hi [subscriber:firstname | default:reader]!</h1>\n<p></p>\n<p>Greetings from New Zealand! We're here enjoying the sights, sounds, and smells of Rotarua! Yesterday, we visited the local hot springs, and today, we're going swimming.</p>\n<p>Don't forget to stay updated with Twitter!</p>", 'mailpoet')
|
||||
), array(
|
||||
"type" => "social",
|
||||
"iconSet" => "circles",
|
||||
@ -324,7 +324,7 @@ class TravelEmail {
|
||||
"type" => "image",
|
||||
"link" => "",
|
||||
"src" => $this->template_image_url . "/glow-worms.jpg",
|
||||
"alt" => __("Glow worms, Waitomo Caves", 'mailpoet'),
|
||||
"alt" => __("Glowworms, Waitomo Caves", 'mailpoet'),
|
||||
"fullWidth" => true,
|
||||
"width" => "640px",
|
||||
"height" => "428px",
|
||||
@ -335,7 +335,7 @@ class TravelEmail {
|
||||
)
|
||||
), array(
|
||||
"type" => "text",
|
||||
"text" => __("<p><em><a href=\"http://www.waitomo.com/Waitomo-Glowworm-Caves/Pages/default.aspx\"><strong>Waitomo Glow Worm Caves</strong></a></em></p>", 'mailpoet')
|
||||
"text" => __("<p><em><a href=\"http://www.waitomo.com/Waitomo-Glowworm-Caves/Pages/default.aspx\"><strong>Waitomo GlowWorm Caves</strong></a></em></p>", 'mailpoet')
|
||||
))
|
||||
), array(
|
||||
"type" => "container",
|
||||
@ -446,7 +446,7 @@ class TravelEmail {
|
||||
)
|
||||
), array(
|
||||
"type" => "header",
|
||||
"text" => ("Display problems? <a href=\"[link:newsletter_view_in_browser_url]\">Open this email in your web browser</a>"),
|
||||
"text" => ("Display problems? <a href=\"[link:newsletter_view_in_browser_url]\">Open this email in your web browser.</a>"),
|
||||
"styles" => array(
|
||||
"block" => array(
|
||||
"backgroundColor" => "transparent"
|
||||
|
@ -52,7 +52,7 @@ class WelcomeBlank12Column {
|
||||
"blocks" => array(
|
||||
array(
|
||||
"type" => "header",
|
||||
"text" => __("Display problems? <a href=\"[link:newsletter_view_in_browser_url]\">Open this email in your web browser</a>", 'mailpoet'),
|
||||
"text" => __("Display problems? <a href=\"[link:newsletter_view_in_browser_url]\">Open this email in your web browser.</a>", 'mailpoet'),
|
||||
"styles" => array(
|
||||
"block" => array(
|
||||
"backgroundColor" => "transparent"
|
||||
|
@ -52,7 +52,7 @@ class WelcomeBlank1Column {
|
||||
"blocks" => array(
|
||||
array(
|
||||
"type" => "header",
|
||||
"text" => __("Display problems? <a href=\"[link:newsletter_view_in_browser_url]\">Open this email in your web browser</a>", 'mailpoet'),
|
||||
"text" => __("Display problems? <a href=\"[link:newsletter_view_in_browser_url]\">Open this email in your web browser.</a>", 'mailpoet'),
|
||||
"styles" => array(
|
||||
"block" => array(
|
||||
"backgroundColor" => "transparent"
|
||||
|
@ -1,9 +1,9 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
use \Twig_Loader_Filesystem as TwigFileSystem;
|
||||
use \Twig_Environment as TwigEnv;
|
||||
use \Twig_Lexer as TwigLexer;
|
||||
use \MailPoet\Twig;
|
||||
use Twig_Loader_Filesystem as TwigFileSystem;
|
||||
use Twig_Environment as TwigEnv;
|
||||
use Twig_Lexer as TwigLexer;
|
||||
use MailPoet\Twig;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
|
@ -1,14 +1,12 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
|
||||
use MailPoet\Config\Env;
|
||||
use MailPoet\Util\Helpers;
|
||||
use MailPoet\WP\Notice as WPNotice;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class RequirementsChecker {
|
||||
const TEST_PHP_VERSION = 'PHPVersion';
|
||||
const TEST_FOLDER_PERMISSIONS = 'TempAndCacheFolderCreation';
|
||||
const TEST_PDO_EXTENSION = 'PDOExtension';
|
||||
const TEST_MBSTRING_EXTENSION = 'MbstringExtension';
|
||||
@ -16,25 +14,26 @@ class RequirementsChecker {
|
||||
|
||||
public $display_error_notice;
|
||||
public $vendor_classes = array(
|
||||
'\ORM',
|
||||
'\Model',
|
||||
'\Twig_Environment',
|
||||
'\Twig_Loader_Filesystem',
|
||||
'\Twig_Lexer',
|
||||
'\Twig_Extension',
|
||||
'\Twig_Extension_GlobalsInterface',
|
||||
'\Twig_SimpleFunction',
|
||||
'\Swift_Mailer',
|
||||
'\Swift_SmtpTransport',
|
||||
'\Swift_Message',
|
||||
'\Carbon\Carbon',
|
||||
'\Sudzy\ValidModel',
|
||||
'\Sudzy\ValidationException',
|
||||
'\Sudzy\Engine',
|
||||
'\pQuery',
|
||||
'\Cron\CronExpression',
|
||||
'\Html2Text\Html2Text',
|
||||
'\csstidy'
|
||||
'\ORM',
|
||||
'\Model',
|
||||
'\Twig_Environment',
|
||||
'\Twig_Loader_Filesystem',
|
||||
'\Twig_Lexer',
|
||||
'\Twig_Extension',
|
||||
'\Twig_Extension_GlobalsInterface',
|
||||
'\Twig_SimpleFunction',
|
||||
'\Swift_Mailer',
|
||||
'\Swift_SmtpTransport',
|
||||
'\Swift_Message',
|
||||
'\Carbon\Carbon',
|
||||
'\Sudzy\ValidModel',
|
||||
'\Sudzy\ValidationException',
|
||||
'\Sudzy\Engine',
|
||||
'\pQuery',
|
||||
'\Cron\CronExpression',
|
||||
'\Html2Text\Html2Text',
|
||||
'\csstidy',
|
||||
'\Sabberworm\CSS\Parser'
|
||||
);
|
||||
|
||||
function __construct($display_error_notice = true) {
|
||||
@ -44,7 +43,6 @@ class RequirementsChecker {
|
||||
function checkAllRequirements() {
|
||||
$available_tests = array(
|
||||
self::TEST_PDO_EXTENSION,
|
||||
self::TEST_PHP_VERSION,
|
||||
self::TEST_FOLDER_PERMISSIONS,
|
||||
self::TEST_MBSTRING_EXTENSION,
|
||||
self::TEST_VENDOR_SOURCE
|
||||
@ -56,17 +54,6 @@ class RequirementsChecker {
|
||||
return $results;
|
||||
}
|
||||
|
||||
function checkPHPVersion() {
|
||||
if(version_compare(phpversion(), '5.3.0', '<')) {
|
||||
$error = Helpers::replaceLinkTags(
|
||||
__('This plugin requires PHP version 5.3 or newer. Please read our [link]instructions[/link] on how to resolve this issue.', 'mailpoet'),
|
||||
'//docs.mailpoet.com/article/152-minimum-requirements-for-mailpoet-3#php_version'
|
||||
);
|
||||
return $this->processError($error);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function checkTempAndCacheFolderCreation() {
|
||||
$paths = array(
|
||||
'temp_path' => Env::$temp_path,
|
||||
@ -75,7 +62,7 @@ class RequirementsChecker {
|
||||
if(!is_dir($paths['cache_path']) && !wp_mkdir_p($paths['cache_path'])) {
|
||||
$error = Helpers::replaceLinkTags(
|
||||
__('This plugin requires write permissions inside the /wp-content/uploads folder. Please read our [link]instructions[/link] on how to resolve this issue.', 'mailpoet'),
|
||||
'//docs.mailpoet.com/article/152-minimum-requirements-for-mailpoet-3#folder_permissions'
|
||||
'//beta.docs.mailpoet.com/article/152-minimum-requirements-for-mailpoet-3#folder_permissions'
|
||||
);
|
||||
return $this->processError($error);
|
||||
}
|
||||
@ -92,14 +79,12 @@ class RequirementsChecker {
|
||||
}
|
||||
|
||||
function checkPDOExtension() {
|
||||
if(!extension_loaded('pdo') && !extension_loaded('pdo_mysql')) {
|
||||
$error = Helpers::replaceLinkTags(
|
||||
__('This plugin requires PDO_MYSQL PHP extension. Please read our [link]instructions[/link] on how to resolve this issue.', 'mailpoet'),
|
||||
'//docs.mailpoet.com/article/152-minimum-requirements-for-mailpoet-3#php_extension'
|
||||
);
|
||||
return $this->processError($error);
|
||||
}
|
||||
return true;
|
||||
if(extension_loaded('pdo') && extension_loaded('pdo_mysql')) return true;
|
||||
$error = Helpers::replaceLinkTags(
|
||||
__('This plugin requires the PDO_MYSQL PHP extension. Please read our [link]instructions[/link] on how to resolve this issue.', 'mailpoet'),
|
||||
'//beta.docs.mailpoet.com/article/152-minimum-requirements-for-mailpoet-3#php_extension'
|
||||
);
|
||||
return $this->processError($error);
|
||||
}
|
||||
|
||||
function checkMbstringExtension() {
|
||||
|
49
lib/Config/ServicesChecker.php
Normal file
49
lib/Config/ServicesChecker.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Services\Bridge;
|
||||
use MailPoet\Util\Helpers;
|
||||
use MailPoet\WP\Notice as WPNotice;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class ServicesChecker {
|
||||
function checkMailPoetAPIKeyValid($display_error_notice = true) {
|
||||
if(!Bridge::isMPSendingServiceEnabled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$result = Setting::getValue(Bridge::API_KEY_STATE_SETTING_NAME);
|
||||
if(empty($result['state']) || $result['state'] == Bridge::MAILPOET_KEY_VALID) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if($result['state'] == Bridge::MAILPOET_KEY_INVALID) {
|
||||
$error = Helpers::replaceLinkTags(
|
||||
__('All sending is currently paused! Your key to send with MailPoet is invalid. [link]Visit MailPoet.com to purchase a key[/link]', 'mailpoet'),
|
||||
'https://account.mailpoet.com?s=' . Subscriber::getTotalSubscribers()
|
||||
);
|
||||
if($display_error_notice) {
|
||||
WPNotice::displayError($error);
|
||||
}
|
||||
return false;
|
||||
} elseif($result['state'] == Bridge::MAILPOET_KEY_EXPIRING
|
||||
&& !empty($result['data']['expire_at'])
|
||||
) {
|
||||
$date = date('Y-m-d', strtotime($result['data']['expire_at']));
|
||||
$error = Helpers::replaceLinkTags(
|
||||
__('Your newsletters are awesome! Don\'t forget to [link]upgrade your MailPoet email plan[/link] by %s to keep sending them to your subscribers.', 'mailpoet'),
|
||||
'https://account.mailpoet.com?s=' . Subscriber::getTotalSubscribers()
|
||||
);
|
||||
$error = sprintf($error, $date);
|
||||
if($display_error_notice) {
|
||||
WPNotice::displayWarning($error);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
use \MailPoet\Models\Newsletter;
|
||||
use \MailPoet\Models\Subscriber;
|
||||
use \MailPoet\Models\SubscriberSegment;
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Models\SubscriberSegment;
|
||||
use MailPoet\Newsletter\Url as NewsletterUrl;
|
||||
|
||||
class Shortcodes {
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
use \MailPoet\Util\Security;
|
||||
use \MailPoet\Models\Form;
|
||||
use MailPoet\Models\Form;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
|
@ -3,6 +3,7 @@ namespace MailPoet\Cron;
|
||||
use MailPoet\Cron\Workers\Scheduler as SchedulerWorker;
|
||||
use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker;
|
||||
use MailPoet\Cron\Workers\Bounce as BounceWorker;
|
||||
use MailPoet\Cron\Workers\SendingServiceKeyCheck as SendingServiceKeyCheckWorker;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||
@ -48,6 +49,7 @@ class Daemon {
|
||||
try {
|
||||
$this->executeScheduleWorker();
|
||||
$this->executeQueueWorker();
|
||||
$this->executeSendingServiceKeyCheckWorker();
|
||||
$this->executeBounceWorker();
|
||||
} catch(\Exception $e) {
|
||||
// continue processing, no need to handle errors
|
||||
@ -80,6 +82,11 @@ class Daemon {
|
||||
return $queue->process();
|
||||
}
|
||||
|
||||
function executeSendingServiceKeyCheckWorker() {
|
||||
$worker = new SendingServiceKeyCheckWorker($this->timer);
|
||||
return $worker->process();
|
||||
}
|
||||
|
||||
function executeBounceWorker() {
|
||||
$bounce = new BounceWorker($this->timer);
|
||||
return $bounce->process();
|
||||
|
@ -5,7 +5,9 @@ use MailPoet\Cron\CronHelper;
|
||||
use MailPoet\Cron\Workers\Scheduler as SchedulerWorker;
|
||||
use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker;
|
||||
use MailPoet\Cron\Workers\Bounce as BounceWorker;
|
||||
use MailPoet\Cron\Workers\SendingServiceKeyCheck as SendingServiceKeyCheckWorker;
|
||||
use MailPoet\Mailer\MailerLog;
|
||||
use MailPoet\Services\Bridge;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
@ -17,14 +19,24 @@ class WordPress {
|
||||
}
|
||||
|
||||
static function checkExecutionRequirements() {
|
||||
// sending queue
|
||||
$scheduled_queues = SchedulerWorker::getScheduledQueues();
|
||||
$running_queues = SendingQueueWorker::getRunningQueues();
|
||||
$sending_limit_reached = MailerLog::isSendingLimitReached();
|
||||
$bounce_sync_available = BounceWorker::checkBounceSyncAvailable();
|
||||
// sending service
|
||||
$mp_sending_enabled = Bridge::isMPSendingServiceEnabled();
|
||||
// bounce sync
|
||||
$bounce_due_queues = BounceWorker::getAllDueQueues();
|
||||
$bounce_future_queues = BounceWorker::getFutureQueues();
|
||||
return (($scheduled_queues || $running_queues) && !$sending_limit_reached)
|
||||
|| ($bounce_sync_available && ($bounce_due_queues || !$bounce_future_queues));
|
||||
// sending service key check
|
||||
$sskeycheck_due_queues = SendingServiceKeyCheckWorker::getAllDueQueues();
|
||||
$sskeycheck_future_queues = SendingServiceKeyCheckWorker::getFutureQueues();
|
||||
// check requirements for each worker
|
||||
$sending_queue_active = (($scheduled_queues || $running_queues) && !$sending_limit_reached);
|
||||
$bounce_sync_active = ($mp_sending_enabled && ($bounce_due_queues || !$bounce_future_queues));
|
||||
$sending_service_key_check_active = ($mp_sending_enabled && ($sskeycheck_due_queues || !$sskeycheck_future_queues));
|
||||
|
||||
return ($sending_queue_active || $bounce_sync_active || $sending_service_key_check_active);
|
||||
}
|
||||
|
||||
static function cleanup() {
|
||||
|
@ -6,15 +6,19 @@ use MailPoet\Cron\CronHelper;
|
||||
use MailPoet\Mailer\Mailer;
|
||||
use MailPoet\Models\SendingQueue;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Services\Bridge;
|
||||
use MailPoet\Services\Bridge\API;
|
||||
use MailPoet\Util\Helpers;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Bounce {
|
||||
const TASK_TYPE = 'bounce';
|
||||
const BATCH_SIZE = 100;
|
||||
|
||||
const BOUNCED_HARD = 'hard';
|
||||
const BOUNCED_SOFT = 'soft';
|
||||
const NOT_BOUNCED = null;
|
||||
const BATCH_SIZE = 100;
|
||||
|
||||
public $timer;
|
||||
public $api;
|
||||
@ -25,21 +29,15 @@ class Bounce {
|
||||
CronHelper::enforceExecutionLimit($this->timer);
|
||||
}
|
||||
|
||||
static function checkBounceSyncAvailable() {
|
||||
$mailer_config = Mailer::getMailerConfig();
|
||||
return !empty($mailer_config['method'])
|
||||
&& $mailer_config['method'] === Mailer::METHOD_MAILPOET;
|
||||
}
|
||||
|
||||
function initApi() {
|
||||
if(!$this->api) {
|
||||
$mailer_config = Mailer::getMailerConfig();
|
||||
$this->api = new Bounce\API($mailer_config['mailpoet_api_key']);
|
||||
$this->api = new API($mailer_config['mailpoet_api_key']);
|
||||
}
|
||||
}
|
||||
|
||||
function process() {
|
||||
if(!self::checkBounceSyncAvailable()) {
|
||||
if(!Bridge::isMPSendingServiceEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -64,7 +62,7 @@ class Bounce {
|
||||
}
|
||||
|
||||
static function scheduleBounceSync() {
|
||||
$already_scheduled = SendingQueue::where('type', 'bounce')
|
||||
$already_scheduled = SendingQueue::where('type', self::TASK_TYPE)
|
||||
->whereNull('deleted_at')
|
||||
->where('status', SendingQueue::STATUS_SCHEDULED)
|
||||
->findMany();
|
||||
@ -72,7 +70,7 @@ class Bounce {
|
||||
return false;
|
||||
}
|
||||
$queue = SendingQueue::create();
|
||||
$queue->type = 'bounce';
|
||||
$queue->type = self::TASK_TYPE;
|
||||
$queue->status = SendingQueue::STATUS_SCHEDULED;
|
||||
$queue->priority = SendingQueue::PRIORITY_LOW;
|
||||
$queue->scheduled_at = self::getNextRunDate();
|
||||
@ -143,7 +141,7 @@ class Bounce {
|
||||
}
|
||||
|
||||
function processEmails(array $subscriber_emails) {
|
||||
$checked_emails = $this->api->check($subscriber_emails);
|
||||
$checked_emails = $this->api->checkBounces($subscriber_emails);
|
||||
$this->processApiResponse((array)$checked_emails);
|
||||
}
|
||||
|
||||
@ -170,7 +168,7 @@ class Bounce {
|
||||
|
||||
static function getScheduledQueues($future = false) {
|
||||
$dateWhere = ($future) ? 'whereGt' : 'whereLte';
|
||||
return SendingQueue::where('type', 'bounce')
|
||||
return SendingQueue::where('type', self::TASK_TYPE)
|
||||
->$dateWhere('scheduled_at', Carbon::createFromTimestamp(current_time('timestamp')))
|
||||
->whereNull('deleted_at')
|
||||
->where('status', SendingQueue::STATUS_SCHEDULED)
|
||||
@ -178,7 +176,7 @@ class Bounce {
|
||||
}
|
||||
|
||||
static function getRunningQueues() {
|
||||
return SendingQueue::where('type', 'bounce')
|
||||
return SendingQueue::where('type', self::TASK_TYPE)
|
||||
->whereLte('scheduled_at', Carbon::createFromTimestamp(current_time('timestamp')))
|
||||
->whereNull('deleted_at')
|
||||
->whereNull('status')
|
||||
|
@ -1,41 +0,0 @@
|
||||
<?php
|
||||
namespace MailPoet\Cron\Workers\Bounce;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class API {
|
||||
public $url = 'https://bridge.mailpoet.com/api/v0/bounces/search';
|
||||
public $api_key;
|
||||
|
||||
function __construct($api_key) {
|
||||
$this->api_key = $api_key;
|
||||
}
|
||||
|
||||
function check(array $emails) {
|
||||
$result = wp_remote_post(
|
||||
$this->url,
|
||||
$this->request($emails)
|
||||
);
|
||||
if(wp_remote_retrieve_response_code($result) === 200) {
|
||||
return json_decode(wp_remote_retrieve_body($result), true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function auth() {
|
||||
return 'Basic ' . base64_encode('api:' . $this->api_key);
|
||||
}
|
||||
|
||||
private function request($body) {
|
||||
return array(
|
||||
'timeout' => 10,
|
||||
'httpversion' => '1.0',
|
||||
'method' => 'POST',
|
||||
'headers' => array(
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => $this->auth()
|
||||
),
|
||||
'body' => json_encode($body)
|
||||
);
|
||||
}
|
||||
}
|
147
lib/Cron/Workers/SendingServiceKeyCheck.php
Normal file
147
lib/Cron/Workers/SendingServiceKeyCheck.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
namespace MailPoet\Cron\Workers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use MailPoet\Cron\CronHelper;
|
||||
use MailPoet\Mailer\Mailer;
|
||||
use MailPoet\Models\SendingQueue;
|
||||
use MailPoet\Services\Bridge;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class SendingServiceKeyCheck {
|
||||
const TASK_TYPE = 'sending_service_key_check';
|
||||
const UNAVAILABLE_SERVICE_RESCHEDULE_TIMEOUT = 60;
|
||||
|
||||
public $timer;
|
||||
public $bridge;
|
||||
|
||||
function __construct($timer = false) {
|
||||
$this->timer = ($timer) ? $timer : microtime(true);
|
||||
// abort if execution limit is reached
|
||||
CronHelper::enforceExecutionLimit($this->timer);
|
||||
}
|
||||
|
||||
function initApi() {
|
||||
if(!$this->bridge) {
|
||||
$this->bridge = new Bridge();
|
||||
}
|
||||
}
|
||||
|
||||
function process() {
|
||||
if(!Bridge::isMPSendingServiceEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->initApi();
|
||||
|
||||
$scheduled_queues = self::getScheduledQueues();
|
||||
$running_queues = self::getRunningQueues();
|
||||
|
||||
if(!$scheduled_queues && !$running_queues) {
|
||||
self::schedule();
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach($scheduled_queues as $i => $queue) {
|
||||
$this->prepareQueue($queue);
|
||||
}
|
||||
foreach($running_queues as $i => $queue) {
|
||||
$this->processQueue($queue);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static function schedule() {
|
||||
$already_scheduled = SendingQueue::where('type', self::TASK_TYPE)
|
||||
->whereNull('deleted_at')
|
||||
->where('status', SendingQueue::STATUS_SCHEDULED)
|
||||
->findMany();
|
||||
if($already_scheduled) {
|
||||
return false;
|
||||
}
|
||||
$queue = SendingQueue::create();
|
||||
$queue->type = self::TASK_TYPE;
|
||||
$queue->status = SendingQueue::STATUS_SCHEDULED;
|
||||
$queue->priority = SendingQueue::PRIORITY_LOW;
|
||||
$queue->scheduled_at = self::getNextRunDate();
|
||||
$queue->newsletter_id = 0;
|
||||
$queue->save();
|
||||
return $queue;
|
||||
}
|
||||
|
||||
function prepareQueue(SendingQueue $queue) {
|
||||
$queue->status = null;
|
||||
$queue->save();
|
||||
|
||||
// abort if execution limit is reached
|
||||
CronHelper::enforceExecutionLimit($this->timer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function processQueue(SendingQueue $queue) {
|
||||
// abort if execution limit is reached
|
||||
CronHelper::enforceExecutionLimit($this->timer);
|
||||
|
||||
try {
|
||||
$mailer_config = Mailer::getMailerConfig();
|
||||
$result = $this->bridge->checkKey($mailer_config['mailpoet_api_key']);
|
||||
$this->bridge->updateSubscriberCount($result);
|
||||
} catch (\Exception $e) {
|
||||
$result = false;
|
||||
}
|
||||
|
||||
if(empty($result['code']) || $result['code'] == Bridge::CHECK_ERROR_UNAVAILABLE) {
|
||||
// reschedule the check
|
||||
$scheduled_at = Carbon::createFromTimestamp(current_time('timestamp'));
|
||||
$queue->scheduled_at = $scheduled_at->addMinutes(
|
||||
self::UNAVAILABLE_SERVICE_RESCHEDULE_TIMEOUT
|
||||
);
|
||||
$queue->save();
|
||||
return false;
|
||||
}
|
||||
|
||||
$queue->processed_at = current_time('mysql');
|
||||
$queue->status = SendingQueue::STATUS_COMPLETED;
|
||||
$queue->save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static function getNextRunDate() {
|
||||
$date = Carbon::createFromTimestamp(current_time('timestamp'));
|
||||
// Random day of the next week
|
||||
$date->setISODate($date->format('o'), $date->format('W') + 1, mt_rand(1, 7));
|
||||
$date->startOfDay();
|
||||
return $date;
|
||||
}
|
||||
|
||||
static function getScheduledQueues($future = false) {
|
||||
$dateWhere = ($future) ? 'whereGt' : 'whereLte';
|
||||
return SendingQueue::where('type', self::TASK_TYPE)
|
||||
->$dateWhere('scheduled_at', Carbon::createFromTimestamp(current_time('timestamp')))
|
||||
->whereNull('deleted_at')
|
||||
->where('status', SendingQueue::STATUS_SCHEDULED)
|
||||
->findMany();
|
||||
}
|
||||
|
||||
static function getRunningQueues() {
|
||||
return SendingQueue::where('type', self::TASK_TYPE)
|
||||
->whereLte('scheduled_at', Carbon::createFromTimestamp(current_time('timestamp')))
|
||||
->whereNull('deleted_at')
|
||||
->whereNull('status')
|
||||
->findMany();
|
||||
}
|
||||
|
||||
static function getAllDueQueues() {
|
||||
$scheduled_queues = self::getScheduledQueues();
|
||||
$running_queues = self::getRunningQueues();
|
||||
return array_merge((array)$scheduled_queues, (array)$running_queues);
|
||||
}
|
||||
|
||||
static function getFutureQueues() {
|
||||
return self::getScheduledQueues(true);
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ abstract class Base {
|
||||
|
||||
if($block['id'] === 'email') {
|
||||
$rules['required'] = true;
|
||||
$rules['error-message'] = __('Please specify a valid email address', 'mailpoet');
|
||||
$rules['error-message'] = __('Please specify a valid email address.', 'mailpoet');
|
||||
}
|
||||
|
||||
if($block['id'] === 'segments') {
|
||||
@ -132,4 +132,4 @@ abstract class Base {
|
||||
}
|
||||
return join(' ', $modifiers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
namespace MailPoet\Form;
|
||||
use MailPoet\Form\Block;
|
||||
use MailPoet\Form\Util;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
|
@ -1,13 +1,9 @@
|
||||
<?php
|
||||
namespace MailPoet\Form;
|
||||
use \MailPoet\Config\Renderer;
|
||||
use \MailPoet\Models\Form;
|
||||
use \MailPoet\Models\Segment;
|
||||
use \MailPoet\Models\Setting;
|
||||
use \MailPoet\Models\Subscriber;
|
||||
use \MailPoet\Form\Renderer as FormRenderer;
|
||||
use \MailPoet\Form\Util;
|
||||
use \MailPoet\Util\Security;
|
||||
use MailPoet\Config\Renderer;
|
||||
use MailPoet\Models\Form;
|
||||
use MailPoet\Form\Renderer as FormRenderer;
|
||||
use MailPoet\Util\Security;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
|
@ -28,9 +28,9 @@ class Mailer {
|
||||
$this->mailer_instance = $this->buildMailer();
|
||||
}
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
function send($newsletter, $subscriber, $extra_params = array()) {
|
||||
$subscriber = $this->formatSubscriberNameAndEmailAddress($subscriber);
|
||||
return $this->mailer_instance->send($newsletter, $subscriber);
|
||||
return $this->mailer_instance->send($newsletter, $subscriber, $extra_params);
|
||||
}
|
||||
|
||||
function buildMailer() {
|
||||
@ -80,7 +80,7 @@ class Mailer {
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new \Exception(__('Mailing method does not exist', 'mailpoet'));
|
||||
throw new \Exception(__('Mailing method does not exist.', 'mailpoet'));
|
||||
}
|
||||
return $mailer_instance;
|
||||
}
|
||||
@ -88,7 +88,7 @@ class Mailer {
|
||||
static function getMailerConfig($mailer = false) {
|
||||
if(!$mailer) {
|
||||
$mailer = Setting::getValue(self::MAILER_CONFIG_SETTING_NAME);
|
||||
if(!$mailer || !isset($mailer['method'])) throw new \Exception(__('Mailer is not configured', 'mailpoet'));
|
||||
if(!$mailer || !isset($mailer['method'])) throw new \Exception(__('Mailer is not configured.', 'mailpoet'));
|
||||
}
|
||||
if(empty($mailer['frequency'])) {
|
||||
$default_settings = Setting::getDefaults();
|
||||
@ -105,7 +105,7 @@ class Mailer {
|
||||
function getSenderNameAndAddress($sender = false) {
|
||||
if(empty($sender)) {
|
||||
$sender = Setting::getValue('sender', array());
|
||||
if(empty($sender['address'])) throw new \Exception(__('Sender name and email are not configured', 'mailpoet'));
|
||||
if(empty($sender['address'])) throw new \Exception(__('Sender name and email are not configured.', 'mailpoet'));
|
||||
}
|
||||
$from_name = $this->encodeAddressNamePart($sender['name']);
|
||||
return array(
|
||||
@ -187,4 +187,4 @@ class Mailer {
|
||||
'response' => true
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ class AmazonSES {
|
||||
public $sender;
|
||||
public $reply_to;
|
||||
public $return_path;
|
||||
public $message;
|
||||
public $date;
|
||||
public $date_without_time;
|
||||
private $available_regions = array(
|
||||
@ -31,7 +32,7 @@ class AmazonSES {
|
||||
$this->aws_secret_key = $secret_key;
|
||||
$this->aws_region = (in_array($region, $this->available_regions)) ? $region : false;
|
||||
if(!$this->aws_region) {
|
||||
throw new \Exception(__('Unsupported Amazon SES region.', 'mailpoet'));
|
||||
throw new \Exception(__('Unsupported Amazon SES region', 'mailpoet'));
|
||||
}
|
||||
$this->aws_endpoint = sprintf('email.%s.amazonaws.com', $this->aws_region);
|
||||
$this->aws_signing_algorithm = 'AWS4-HMAC-SHA256';
|
||||
@ -48,10 +49,10 @@ class AmazonSES {
|
||||
$this->date_without_time = gmdate('Ymd');
|
||||
}
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
function send($newsletter, $subscriber, $extra_params = array()) {
|
||||
$result = wp_remote_post(
|
||||
$this->url,
|
||||
$this->request($newsletter, $subscriber)
|
||||
$this->request($newsletter, $subscriber, $extra_params)
|
||||
);
|
||||
if(is_wp_error($result)) {
|
||||
return Mailer::formatMailerConnectionErrorResult($result->get_error_message());
|
||||
@ -66,27 +67,61 @@ class AmazonSES {
|
||||
return Mailer::formatMailerSendSuccessResult();
|
||||
}
|
||||
|
||||
function getBody($newsletter, $subscriber) {
|
||||
function getBody($newsletter, $subscriber, $extra_params = array()) {
|
||||
$this->message = $this->createMessage($newsletter, $subscriber, $extra_params);
|
||||
$body = array(
|
||||
'Action' => 'SendEmail',
|
||||
'Action' => 'SendRawEmail',
|
||||
'Version' => '2010-12-01',
|
||||
'Destination.ToAddresses.member.1' => $subscriber,
|
||||
'Source' => $this->sender['from_name_email'],
|
||||
'ReplyToAddresses.member.1' => $this->reply_to['reply_to_name_email'],
|
||||
'Message.Subject.Data' => $newsletter['subject'],
|
||||
'ReturnPath' => $this->return_path
|
||||
'RawMessage.Data' => $this->encodeMessage($this->message)
|
||||
);
|
||||
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) {
|
||||
$body = array_map('urlencode', $this->getBody($newsletter, $subscriber));
|
||||
function createMessage($newsletter, $subscriber, $extra_params = array()) {
|
||||
$message = \Swift_Message::newInstance()
|
||||
->setTo($this->processSubscriber($subscriber))
|
||||
->setFrom(array(
|
||||
$this->sender['from_email'] => $this->sender['from_name']
|
||||
))
|
||||
->setSender($this->sender['from_email'])
|
||||
->setReplyTo(array(
|
||||
$this->reply_to['reply_to_email'] => $this->reply_to['reply_to_name']
|
||||
))
|
||||
->setReturnPath($this->return_path)
|
||||
->setSubject($newsletter['subject']);
|
||||
if(!empty($extra_params['unsubscribe_url'])) {
|
||||
$headers = $message->getHeaders();
|
||||
$headers->addTextHeader('List-Unsubscribe', '<' . $extra_params['unsubscribe_url'] . '>');
|
||||
}
|
||||
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 encodeMessage(\Swift_Message $message) {
|
||||
return base64_encode($message->toString());
|
||||
}
|
||||
|
||||
function processSubscriber($subscriber) {
|
||||
preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriber_data);
|
||||
if(!isset($subscriber_data['email'])) {
|
||||
$subscriber_data = array(
|
||||
'email' => $subscriber,
|
||||
);
|
||||
}
|
||||
return array(
|
||||
$subscriber_data['email'] =>
|
||||
(isset($subscriber_data['name'])) ? $subscriber_data['name'] : ''
|
||||
);
|
||||
}
|
||||
|
||||
function request($newsletter, $subscriber, $extra_params = array()) {
|
||||
$body = array_map('urlencode', $this->getBody($newsletter, $subscriber, $extra_params));
|
||||
return array(
|
||||
'timeout' => 10,
|
||||
'httpversion' => '1.1',
|
||||
@ -176,4 +211,4 @@ class AmazonSES {
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,37 +2,46 @@
|
||||
namespace MailPoet\Mailer\Methods;
|
||||
|
||||
use MailPoet\Mailer\Mailer;
|
||||
use MailPoet\Config\ServicesChecker;
|
||||
use MailPoet\Services\Bridge;
|
||||
use MailPoet\Services\Bridge\API;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class MailPoet {
|
||||
public $url = 'https://bridge.mailpoet.com/api/messages';
|
||||
public $api_key;
|
||||
public $api;
|
||||
public $sender;
|
||||
public $reply_to;
|
||||
public $services_checker;
|
||||
|
||||
function __construct($api_key, $sender, $reply_to) {
|
||||
$this->api_key = $api_key;
|
||||
$this->api = new API($api_key);
|
||||
$this->sender = $sender;
|
||||
$this->reply_to = $reply_to;
|
||||
$this->services_checker = new ServicesChecker(false);
|
||||
}
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
$message_body = $this->getBody($newsletter, $subscriber);
|
||||
$result = wp_remote_post(
|
||||
$this->url,
|
||||
$this->request($message_body)
|
||||
);
|
||||
if(is_wp_error($result)) {
|
||||
return Mailer::formatMailerConnectionErrorResult($result->get_error_message());
|
||||
}
|
||||
if(wp_remote_retrieve_response_code($result) !== 201) {
|
||||
$response = (wp_remote_retrieve_body($result)) ?
|
||||
wp_remote_retrieve_body($result) :
|
||||
wp_remote_retrieve_response_message($result);
|
||||
function send($newsletter, $subscriber, $extra_params = array()) {
|
||||
if($this->services_checker->checkMailPoetAPIKeyValid() === false) {
|
||||
$response = __('MailPoet API key is invalid!', 'mailpoet');
|
||||
return Mailer::formatMailerSendErrorResult($response);
|
||||
}
|
||||
return Mailer::formatMailerSendSuccessResult();
|
||||
|
||||
$message_body = $this->getBody($newsletter, $subscriber);
|
||||
$result = $this->api->sendMessages($message_body);
|
||||
|
||||
switch($result['status']) {
|
||||
case API::SENDING_STATUS_CONNECTION_ERROR:
|
||||
return Mailer::formatMailerConnectionErrorResult($result['message']);
|
||||
case API::SENDING_STATUS_SEND_ERROR:
|
||||
if(!empty($result['code']) && $result['code'] === API::RESPONSE_CODE_KEY_INVALID) {
|
||||
Bridge::invalidateKey();
|
||||
}
|
||||
return Mailer::formatMailerSendErrorResult($result['message']);
|
||||
case API::SENDING_STATUS_OK:
|
||||
default:
|
||||
return Mailer::formatMailerSendSuccessResult();
|
||||
}
|
||||
}
|
||||
|
||||
function processSubscriber($subscriber) {
|
||||
@ -86,21 +95,4 @@ class MailPoet {
|
||||
}
|
||||
return $body;
|
||||
}
|
||||
|
||||
function auth() {
|
||||
return 'Basic ' . base64_encode('api:' . $this->api_key);
|
||||
}
|
||||
|
||||
function request($body) {
|
||||
return array(
|
||||
'timeout' => 10,
|
||||
'httpversion' => '1.0',
|
||||
'method' => 'POST',
|
||||
'headers' => array(
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => $this->auth()
|
||||
),
|
||||
'body' => json_encode($body)
|
||||
);
|
||||
}
|
||||
}
|
@ -20,9 +20,9 @@ class PHPMail {
|
||||
$this->mailer = $this->buildMailer();
|
||||
}
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
function send($newsletter, $subscriber, $extra_params = array()) {
|
||||
try {
|
||||
$message = $this->createMessage($newsletter, $subscriber);
|
||||
$message = $this->createMessage($newsletter, $subscriber, $extra_params);
|
||||
$result = $this->mailer->send($message);
|
||||
} catch(\Exception $e) {
|
||||
return Mailer::formatMailerSendErrorResult($e->getMessage());
|
||||
@ -39,7 +39,7 @@ class PHPMail {
|
||||
return \Swift_Mailer::newInstance($transport);
|
||||
}
|
||||
|
||||
function createMessage($newsletter, $subscriber) {
|
||||
function createMessage($newsletter, $subscriber, $extra_params = array()) {
|
||||
$message = \Swift_Message::newInstance()
|
||||
->setTo($this->processSubscriber($subscriber))
|
||||
->setFrom(array(
|
||||
@ -51,6 +51,10 @@ class PHPMail {
|
||||
))
|
||||
->setReturnPath($this->return_path)
|
||||
->setSubject($newsletter['subject']);
|
||||
if(!empty($extra_params['unsubscribe_url'])) {
|
||||
$headers = $message->getHeaders();
|
||||
$headers->addTextHeader('List-Unsubscribe', '<' . $extra_params['unsubscribe_url'] . '>');
|
||||
}
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
$message = $message->setBody($newsletter['body']['html'], 'text/html');
|
||||
}
|
||||
|
@ -34,9 +34,9 @@ class SMTP {
|
||||
$this->mailer = $this->buildMailer();
|
||||
}
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
function send($newsletter, $subscriber, $extra_params = array()) {
|
||||
try {
|
||||
$message = $this->createMessage($newsletter, $subscriber);
|
||||
$message = $this->createMessage($newsletter, $subscriber, $extra_params);
|
||||
$result = $this->mailer->send($message);
|
||||
} catch(\Exception $e) {
|
||||
return Mailer::formatMailerSendErrorResult($e->getMessage());
|
||||
@ -60,7 +60,7 @@ class SMTP {
|
||||
return \Swift_Mailer::newInstance($transport);
|
||||
}
|
||||
|
||||
function createMessage($newsletter, $subscriber) {
|
||||
function createMessage($newsletter, $subscriber, $extra_params = array()) {
|
||||
$message = \Swift_Message::newInstance()
|
||||
->setTo($this->processSubscriber($subscriber))
|
||||
->setFrom(array(
|
||||
@ -72,6 +72,10 @@ class SMTP {
|
||||
))
|
||||
->setReturnPath($this->return_path)
|
||||
->setSubject($newsletter['subject']);
|
||||
if(!empty($extra_params['unsubscribe_url'])) {
|
||||
$headers = $message->getHeaders();
|
||||
$headers->addTextHeader('List-Unsubscribe', '<' . $extra_params['unsubscribe_url'] . '>');
|
||||
}
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
$message = $message->setBody($newsletter['body']['html'], 'text/html');
|
||||
}
|
||||
|
@ -17,10 +17,10 @@ class SendGrid {
|
||||
$this->reply_to = $reply_to;
|
||||
}
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
function send($newsletter, $subscriber, $extra_params = array()) {
|
||||
$result = wp_remote_post(
|
||||
$this->url,
|
||||
$this->request($newsletter, $subscriber)
|
||||
$this->request($newsletter, $subscriber, $extra_params)
|
||||
);
|
||||
if(is_wp_error($result)) {
|
||||
return Mailer::formatMailerConnectionErrorResult($result->get_error_message());
|
||||
@ -35,7 +35,7 @@ class SendGrid {
|
||||
return Mailer::formatMailerSendSuccessResult();
|
||||
}
|
||||
|
||||
function getBody($newsletter, $subscriber) {
|
||||
function getBody($newsletter, $subscriber, $extra_params = array()) {
|
||||
$body = array(
|
||||
'to' => $subscriber,
|
||||
'from' => $this->sender['from_email'],
|
||||
@ -43,6 +43,13 @@ class SendGrid {
|
||||
'replyto' => $this->reply_to['reply_to_email'],
|
||||
'subject' => $newsletter['subject']
|
||||
);
|
||||
$headers = array();
|
||||
if(!empty($extra_params['unsubscribe_url'])) {
|
||||
$headers['List-Unsubscribe'] = '<' . $extra_params['unsubscribe_url'] . '>';
|
||||
}
|
||||
if($headers) {
|
||||
$body['headers'] = json_encode($headers);
|
||||
}
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
$body['html'] = $newsletter['body']['html'];
|
||||
}
|
||||
@ -56,8 +63,8 @@ class SendGrid {
|
||||
return 'Bearer ' . $this->api_key;
|
||||
}
|
||||
|
||||
function request($newsletter, $subscriber) {
|
||||
$body = $this->getBody($newsletter, $subscriber);
|
||||
function request($newsletter, $subscriber, $extra_params = array()) {
|
||||
$body = $this->getBody($newsletter, $subscriber, $extra_params);
|
||||
return array(
|
||||
'timeout' => 10,
|
||||
'httpversion' => '1.1',
|
||||
|
@ -11,10 +11,10 @@ class CustomField extends Model {
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
$this->addValidations('name', array(
|
||||
'required' => __('Please specify a name', 'mailpoet')
|
||||
'required' => __('Please specify a name.', 'mailpoet')
|
||||
));
|
||||
$this->addValidations('type', array(
|
||||
'required' => __('Please specify a type', 'mailpoet')
|
||||
'required' => __('Please specify a type.', 'mailpoet')
|
||||
));
|
||||
}
|
||||
|
||||
@ -142,4 +142,4 @@ class CustomField extends Model {
|
||||
|
||||
return $custom_field->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ class Form extends Model {
|
||||
parent::__construct();
|
||||
|
||||
$this->addValidations('name', array(
|
||||
'required' => __('Please specify a name', 'mailpoet')
|
||||
'required' => __('Please specify a name.', 'mailpoet')
|
||||
));
|
||||
}
|
||||
|
||||
@ -39,6 +39,49 @@ class Form extends Model {
|
||||
return parent::save();
|
||||
}
|
||||
|
||||
function getFieldList() {
|
||||
$form = $this->asArray();
|
||||
if(empty($form['body'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$skipped_types = array('html', 'divider', 'submit');
|
||||
$fields = array();
|
||||
|
||||
foreach((array)$form['body'] as $field) {
|
||||
if(empty($field['id'])
|
||||
|| empty($field['type'])
|
||||
|| in_array($field['type'], $skipped_types)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if($field['id'] > 0) {
|
||||
$fields[] = 'cf_' . $field['id'];
|
||||
} else {
|
||||
$fields[] = $field['id'];
|
||||
}
|
||||
}
|
||||
|
||||
return $fields ?: false;
|
||||
}
|
||||
|
||||
function filterSegments(array $segment_ids = array()) {
|
||||
$form = $this->asArray();
|
||||
if(empty($form['settings']['segments'])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if(!empty($form['settings']['segments_selected_by'])
|
||||
&& $form['settings']['segments_selected_by'] == 'user'
|
||||
) {
|
||||
$segment_ids = array_intersect($segment_ids, $form['settings']['segments']);
|
||||
} else {
|
||||
$segment_ids = $form['settings']['segments'];
|
||||
}
|
||||
|
||||
return $segment_ids;
|
||||
}
|
||||
|
||||
static function search($orm, $search = '') {
|
||||
return $orm->whereLike('name', '%'.$search.'%');
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ class Newsletter extends Model {
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
$this->addValidations('type', array(
|
||||
'required' => __('Please specify a type', 'mailpoet')
|
||||
'required' => __('Please specify a type.', 'mailpoet')
|
||||
));
|
||||
}
|
||||
|
||||
@ -593,6 +593,7 @@ class Newsletter extends Model {
|
||||
return self::select(array(
|
||||
'id',
|
||||
'subject',
|
||||
'hash',
|
||||
'type',
|
||||
'status',
|
||||
'updated_at',
|
||||
@ -714,4 +715,4 @@ class Newsletter extends Model {
|
||||
self::NEWSLETTER_HASH_LENGTH
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,10 @@ class NewsletterOptionField extends Model {
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
$this->addValidations('name', array(
|
||||
'required' => __('Please specify a name', 'mailpoet')
|
||||
'required' => __('Please specify a name.', 'mailpoet')
|
||||
));
|
||||
$this->addValidations('newsletter_type', array(
|
||||
'required' => __('Please specify a newsletter type', 'mailpoet')
|
||||
'required' => __('Please specify a newsletter type.', 'mailpoet')
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -10,10 +10,10 @@ class NewsletterTemplate extends Model {
|
||||
parent::__construct();
|
||||
|
||||
$this->addValidations('name', array(
|
||||
'required' => __('Please specify a name', 'mailpoet')
|
||||
'required' => __('Please specify a name.', 'mailpoet')
|
||||
));
|
||||
$this->addValidations('body', array(
|
||||
'required' => __('The template body cannot be empty', 'mailpoet')
|
||||
'required' => __('The template body cannot be empty.', 'mailpoet')
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ class Segment extends Model {
|
||||
parent::__construct();
|
||||
|
||||
$this->addValidations('name', array(
|
||||
'required' => __('Please specify a name', 'mailpoet')
|
||||
'required' => __('Please specify a name.', 'mailpoet')
|
||||
));
|
||||
}
|
||||
|
||||
@ -106,7 +106,7 @@ class Segment extends Model {
|
||||
$wp_segment->hydrate(array(
|
||||
'name' => __('WordPress Users', 'mailpoet'),
|
||||
'description' =>
|
||||
__('This lists containts all of your WordPress users', 'mailpoet'),
|
||||
__('This list contains all of your WordPress users.', 'mailpoet'),
|
||||
'type' => 'wp_users'
|
||||
));
|
||||
$wp_segment->save();
|
||||
|
@ -19,7 +19,7 @@ class Setting extends Model {
|
||||
parent::__construct();
|
||||
|
||||
$this->addValidations('name', array(
|
||||
'required' => __('Please specify a name', 'mailpoet')
|
||||
'required' => __('Please specify a name.', 'mailpoet')
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -280,7 +280,9 @@ class Subscriber extends Model {
|
||||
'value' => ''
|
||||
);
|
||||
|
||||
$subscribers_without_segment = self::filter('withoutSegments')->count();
|
||||
$subscribers_without_segment = self::filter('withoutSegments')
|
||||
->whereNull('deleted_at')
|
||||
->count();
|
||||
$subscribers_without_segment_label = sprintf(
|
||||
__('Subscribers without a list (%s)', 'mailpoet'),
|
||||
number_format($subscribers_without_segment)
|
||||
@ -485,6 +487,17 @@ class Subscriber extends Model {
|
||||
unset($data['segments']);
|
||||
}
|
||||
|
||||
// fields that must exist
|
||||
$not_null_fields = array(
|
||||
'first_name' => '',
|
||||
'last_name' => ''
|
||||
);
|
||||
foreach($not_null_fields as $field => $value) {
|
||||
if(!isset($data[$field])) {
|
||||
$data[$field] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// custom fields
|
||||
$custom_fields = array();
|
||||
foreach($data as $key => $value) {
|
||||
@ -771,13 +784,18 @@ class Subscriber extends Model {
|
||||
|
||||
static function withoutSegments($orm) {
|
||||
return $orm->select(MP_SUBSCRIBERS_TABLE.'.*')
|
||||
->leftOuterJoin(
|
||||
MP_SUBSCRIBER_SEGMENT_TABLE,
|
||||
->rawJoin(
|
||||
'LEFT OUTER JOIN (
|
||||
SELECT `subscriber_id`
|
||||
FROM '.MP_SUBSCRIBER_SEGMENT_TABLE.'
|
||||
WHERE `status` = "'.self::STATUS_SUBSCRIBED.'"
|
||||
)',
|
||||
array(
|
||||
MP_SUBSCRIBERS_TABLE.'.id',
|
||||
'=',
|
||||
MP_SUBSCRIBER_SEGMENT_TABLE.'.subscriber_id'
|
||||
)
|
||||
),
|
||||
MP_SUBSCRIBER_SEGMENT_TABLE
|
||||
)
|
||||
->whereNull(MP_SUBSCRIBER_SEGMENT_TABLE.'.subscriber_id');
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?php
|
||||
namespace MailPoet\Models;
|
||||
|
||||
use MailPoet\Util\Helpers;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
@ -54,6 +53,15 @@ class SubscriberSegment extends Model {
|
||||
return true;
|
||||
}
|
||||
|
||||
static function resubscribeToAllSegments($subscriber) {
|
||||
if($subscriber === false) return false;
|
||||
// (re)subscribe to all segments linked to the subscriber
|
||||
return self::where('subscriber_id', $subscriber->id)
|
||||
->findResultSet()
|
||||
->set('status', Subscriber::STATUS_SUBSCRIBED)
|
||||
->save();
|
||||
}
|
||||
|
||||
static function subscribeToSegments($subscriber, $segment_ids = array()) {
|
||||
if($subscriber === false) return false;
|
||||
if(!empty($segment_ids)) {
|
||||
@ -68,12 +76,6 @@ class SubscriberSegment extends Model {
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
// (re)subscribe to all segments linked to the subscriber
|
||||
return self::where('subscriber_id', $subscriber->id)
|
||||
->findResultSet()
|
||||
->set('status', Subscriber::STATUS_SUBSCRIBED)
|
||||
->save();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
namespace MailPoet\Newsletter;
|
||||
|
||||
use MailPoet\Newsletter\Editor\Transformer;
|
||||
use MailPoet\Util\Helpers;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\Newsletter\Editor;
|
||||
|
||||
use \MailPoet\Newsletter\Editor\PostTransformer;
|
||||
use MailPoet\Newsletter\Editor\PostTransformer;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
<?php
|
||||
namespace MailPoet\Newsletter\Editor;
|
||||
|
||||
use \MailPoet\Newsletter\Editor\PostContentManager;
|
||||
use \MailPoet\Newsletter\Editor\MetaInformationManager;
|
||||
use \MailPoet\Newsletter\Editor\StructureTransformer;
|
||||
use MailPoet\Newsletter\Editor\PostContentManager;
|
||||
use MailPoet\Newsletter\Editor\MetaInformationManager;
|
||||
use MailPoet\Newsletter\Editor\StructureTransformer;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\Newsletter\Editor;
|
||||
|
||||
use \pQuery;
|
||||
use pQuery;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
namespace MailPoet\Newsletter\Editor;
|
||||
|
||||
use \MailPoet\Newsletter\Editor\TitleListTransformer;
|
||||
use \MailPoet\Newsletter\Editor\PostListTransformer;
|
||||
use MailPoet\Newsletter\Editor\TitleListTransformer;
|
||||
use MailPoet\Newsletter\Editor\PostListTransformer;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
|
@ -27,8 +27,7 @@ class Url {
|
||||
$preview = true;
|
||||
break;
|
||||
case self::TYPE_LISTING_EDITOR:
|
||||
// enable preview and hide newsletter hash when displaying from editor or listings
|
||||
$newsletter->hash = null;
|
||||
// enable preview when displaying from editor or listings
|
||||
$preview = true;
|
||||
break;
|
||||
default:
|
||||
|
@ -50,15 +50,24 @@ class ViewInBrowser {
|
||||
if(empty($data->subscriber_token) ||
|
||||
!Subscriber::verifyToken($data->subscriber->email, $data->subscriber_token)
|
||||
) return false;
|
||||
} else if(!$data->subscriber && !empty($data->preview)) {
|
||||
// if this is a preview and subscriber does not exist,
|
||||
// attempt to set subscriber to the current logged-in WP user
|
||||
$data->subscriber = Subscriber::getCurrentWPUser();
|
||||
}
|
||||
|
||||
// if newsletter ID is defined then subscriber must exist
|
||||
if($data->newsletter_id && !$data->subscriber) return false;
|
||||
// if newsletter hash is not provided but newsletter ID is defined then subscriber must exist
|
||||
if(empty($data->newsletter_hash) && $data->newsletter_id && !$data->subscriber) return false;
|
||||
|
||||
// queue is optional; if defined, get it
|
||||
$data->queue = (!empty($data->queue_id)) ?
|
||||
SendingQueue::findOne($data->queue_id) :
|
||||
SendingQueue::where('newsletter_id', $data->newsletter->id)->findOne();
|
||||
// queue is optional; try to find it if it's not defined and this is not a welcome email
|
||||
if($data->newsletter->type !== Newsletter::TYPE_WELCOME) {
|
||||
$data->queue = (!empty($data->queue_id)) ?
|
||||
SendingQueue::findOne($data->queue_id) :
|
||||
SendingQueue::where('newsletter_id', $data->newsletter->id)
|
||||
->findOne();
|
||||
} else {
|
||||
$data->queue = false;
|
||||
}
|
||||
|
||||
// allow users with 'manage_options' permission to preview any newsletter
|
||||
if(!empty($data->preview) && current_user_can(Env::$required_permission)
|
||||
|
@ -31,11 +31,11 @@ class Router {
|
||||
$endpoint_class = __NAMESPACE__ . "\\Endpoints\\" . ucfirst($this->endpoint);
|
||||
if(!$this->api_request) return;
|
||||
if(!$this->endpoint || !class_exists($endpoint_class)) {
|
||||
return $this->terminateRequest(self::RESPONSE_ERROR, __('Invalid router endpoint.', 'mailpoet'));
|
||||
return $this->terminateRequest(self::RESPONSE_ERROR, __('Invalid router endpoint', 'mailpoet'));
|
||||
}
|
||||
$endpoint = new $endpoint_class($this->data);
|
||||
if(!method_exists($endpoint, $this->action) || !in_array($this->action, $endpoint->allowed_actions)) {
|
||||
return $this->terminateRequest(self::RESPONSE_ERROR, __('Invalid router endpoint action.', 'mailpoet'));
|
||||
return $this->terminateRequest(self::RESPONSE_ERROR, __('Invalid router endpoint action', 'mailpoet'));
|
||||
}
|
||||
do_action('mailpoet_conflict_resolver_router_url_query_parameters');
|
||||
return call_user_func(
|
||||
@ -74,4 +74,4 @@ class Router {
|
||||
status_header($code, $message);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
96
lib/Services/Bridge.php
Normal file
96
lib/Services/Bridge.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
namespace MailPoet\Services;
|
||||
|
||||
use MailPoet\Mailer\Mailer;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Models\Subscriber;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Bridge {
|
||||
const API_KEY_STATE_SETTING_NAME = 'mta.mailpoet_api_key_state';
|
||||
|
||||
const MAILPOET_KEY_VALID = 'valid';
|
||||
const MAILPOET_KEY_INVALID = 'invalid';
|
||||
const MAILPOET_KEY_EXPIRING = 'expiring';
|
||||
|
||||
const MAILPOET_KEY_CHECK_ERROR = 'check_error';
|
||||
|
||||
const CHECK_ERROR_UNAVAILABLE = 503;
|
||||
const CHECK_ERROR_UNKNOWN = 'unknown';
|
||||
|
||||
public $api;
|
||||
|
||||
static function isMPSendingServiceEnabled() {
|
||||
try {
|
||||
$mailer_config = Mailer::getMailerConfig();
|
||||
return !empty($mailer_config['method'])
|
||||
&& $mailer_config['method'] === Mailer::METHOD_MAILPOET;
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function initApi($api_key) {
|
||||
if($this->api) {
|
||||
$this->api->setKey($api_key);
|
||||
} else {
|
||||
$this->api = new Bridge\API($api_key);
|
||||
}
|
||||
}
|
||||
|
||||
function checkKey($api_key) {
|
||||
$this->initApi($api_key);
|
||||
$result = $this->api->checkKey();
|
||||
return $this->processResult($result);
|
||||
}
|
||||
|
||||
function processResult(array $result) {
|
||||
$state_map = array(
|
||||
200 => self::MAILPOET_KEY_VALID,
|
||||
401 => self::MAILPOET_KEY_INVALID,
|
||||
402 => self::MAILPOET_KEY_EXPIRING
|
||||
);
|
||||
|
||||
$update_settings = false;
|
||||
|
||||
if(!empty($result['code']) && isset($state_map[$result['code']])) {
|
||||
$key_state = $state_map[$result['code']];
|
||||
$update_settings = true;
|
||||
} else {
|
||||
$key_state = self::MAILPOET_KEY_CHECK_ERROR;
|
||||
}
|
||||
|
||||
$state = array(
|
||||
'state' => $key_state,
|
||||
'data' => !empty($result['data']) ? $result['data'] : null,
|
||||
'code' => !empty($result['code']) ? $result['code'] : self::CHECK_ERROR_UNKNOWN
|
||||
);
|
||||
|
||||
if($update_settings) {
|
||||
Setting::setValue(
|
||||
self::API_KEY_STATE_SETTING_NAME,
|
||||
$state
|
||||
);
|
||||
}
|
||||
|
||||
return $state;
|
||||
}
|
||||
|
||||
function updateSubscriberCount($result) {
|
||||
if(!empty($result['state'])
|
||||
&& ($result['state'] === self::MAILPOET_KEY_VALID
|
||||
|| $result['state'] === self::MAILPOET_KEY_EXPIRING)
|
||||
) {
|
||||
return $this->api->updateSubscriberCount(Subscriber::getTotalSubscribers());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static function invalidateKey() {
|
||||
Setting::setValue(
|
||||
self::API_KEY_STATE_SETTING_NAME,
|
||||
array('state' => self::MAILPOET_KEY_INVALID)
|
||||
);
|
||||
}
|
||||
}
|
119
lib/Services/Bridge/API.php
Normal file
119
lib/Services/Bridge/API.php
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
namespace MailPoet\Services\Bridge;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class API {
|
||||
const SENDING_STATUS_OK = 'ok';
|
||||
const SENDING_STATUS_CONNECTION_ERROR = 'connection_error';
|
||||
const SENDING_STATUS_SEND_ERROR = 'send_error';
|
||||
|
||||
const RESPONSE_CODE_KEY_INVALID = 401;
|
||||
|
||||
const RESPONSE_CODE_STATS_SAVED = 204;
|
||||
|
||||
private $api_key;
|
||||
|
||||
public $url_me = 'https://bridge.mailpoet.com/api/v0/me';
|
||||
public $url_messages = 'https://bridge.mailpoet.com/api/v0/messages';
|
||||
public $url_bounces = 'https://bridge.mailpoet.com/api/v0/bounces/search';
|
||||
public $url_stats = 'https://bridge.mailpoet.com/api/v0/stats';
|
||||
|
||||
function __construct($api_key) {
|
||||
$this->setKey($api_key);
|
||||
}
|
||||
|
||||
function checkKey() {
|
||||
$result = $this->request(
|
||||
$this->url_me,
|
||||
array('site' => home_url())
|
||||
);
|
||||
|
||||
$code = wp_remote_retrieve_response_code($result);
|
||||
switch($code) {
|
||||
case 200:
|
||||
case 402:
|
||||
$body = json_decode(wp_remote_retrieve_body($result), true);
|
||||
break;
|
||||
case 401:
|
||||
$body = wp_remote_retrieve_body($result);
|
||||
break;
|
||||
default:
|
||||
$body = null;
|
||||
break;
|
||||
}
|
||||
|
||||
return array('code' => $code, 'data' => $body);
|
||||
}
|
||||
|
||||
function sendMessages($message_body) {
|
||||
$result = $this->request(
|
||||
$this->url_messages,
|
||||
$message_body
|
||||
);
|
||||
if(is_wp_error($result)) {
|
||||
return array(
|
||||
'status' => self::SENDING_STATUS_CONNECTION_ERROR,
|
||||
'message' => $result->get_error_message()
|
||||
);
|
||||
}
|
||||
$response_code = wp_remote_retrieve_response_code($result);
|
||||
if($response_code !== 201) {
|
||||
$response = (wp_remote_retrieve_body($result)) ?
|
||||
wp_remote_retrieve_body($result) :
|
||||
wp_remote_retrieve_response_message($result);
|
||||
return array(
|
||||
'status' => self::SENDING_STATUS_SEND_ERROR,
|
||||
'message' => $response,
|
||||
'code' => $response_code
|
||||
);
|
||||
}
|
||||
return array('status' => self::SENDING_STATUS_OK);
|
||||
}
|
||||
|
||||
function checkBounces(array $emails) {
|
||||
$result = $this->request(
|
||||
$this->url_bounces,
|
||||
$emails
|
||||
);
|
||||
if(wp_remote_retrieve_response_code($result) === 200) {
|
||||
return json_decode(wp_remote_retrieve_body($result), true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function updateSubscriberCount($count) {
|
||||
$result = $this->request(
|
||||
$this->url_stats,
|
||||
array('subscriber_count' => (int)$count),
|
||||
'PUT'
|
||||
);
|
||||
return wp_remote_retrieve_response_code($result) === self::RESPONSE_CODE_STATS_SAVED;
|
||||
}
|
||||
|
||||
function setKey($api_key) {
|
||||
$this->api_key = $api_key;
|
||||
}
|
||||
|
||||
function getKey() {
|
||||
return $this->api_key;
|
||||
}
|
||||
|
||||
private function auth() {
|
||||
return 'Basic ' . base64_encode('api:' . $this->api_key);
|
||||
}
|
||||
|
||||
private function request($url, $body, $method = 'POST') {
|
||||
$params = array(
|
||||
'timeout' => 10,
|
||||
'httpversion' => '1.0',
|
||||
'method' => $method,
|
||||
'headers' => array(
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => $this->auth()
|
||||
),
|
||||
'body' => json_encode($body)
|
||||
);
|
||||
return wp_remote_post($url, $params);
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
namespace MailPoet\Settings;
|
||||
use \MailPoet\Subscription;
|
||||
use MailPoet\Subscription;
|
||||
|
||||
class Pages {
|
||||
function __construct() {
|
||||
|
@ -47,10 +47,10 @@ class Export {
|
||||
function process() {
|
||||
try {
|
||||
if(is_writable($this->export_path) === false) {
|
||||
throw new \Exception(__("Couldn't save export file on the server", 'mailpoet'));
|
||||
throw new \Exception(__("The export file could not be saved on the server.", 'mailpoet'));
|
||||
}
|
||||
if(!extension_loaded('zip')) {
|
||||
throw new \Exception(__('Export requires a ZIP extension to be installed on the host', 'mailpoet'));
|
||||
throw new \Exception(__('Export requires a ZIP extension to be installed on the host.', 'mailpoet'));
|
||||
}
|
||||
$processed_subscribers = call_user_func(
|
||||
array(
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\Subscription;
|
||||
use \MailPoet\Models\Setting;
|
||||
use \MailPoet\Models\Subscriber;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Models\Subscriber;
|
||||
|
||||
class Comment {
|
||||
const SPAM = 'spam';
|
||||
@ -20,7 +20,7 @@ class Comment {
|
||||
static function getSubscriptionField() {
|
||||
$label = Setting::getValue(
|
||||
'subscribe.on_comment.label',
|
||||
__('Yes, please add me to your mailing list', 'mailpoet')
|
||||
__('Yes, please add me to your mailing list.', 'mailpoet')
|
||||
);
|
||||
|
||||
return '<p class="comment-form-mailpoet">
|
||||
@ -91,4 +91,4 @@ class Comment {
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,8 @@
|
||||
<?php
|
||||
namespace MailPoet\Subscription;
|
||||
use \MailPoet\API\Endpoints\Subscribers;
|
||||
use \MailPoet\API\Response as APIResponse;
|
||||
use \MailPoet\Models\Subscriber;
|
||||
use \MailPoet\Models\StatisticsForms;
|
||||
use \MailPoet\Models\Form as FormModel;
|
||||
use \MailPoet\Util\Url;
|
||||
use MailPoet\API\Endpoints\Subscribers;
|
||||
use MailPoet\API\Response as APIResponse;
|
||||
use MailPoet\Util\Url;
|
||||
|
||||
class Form {
|
||||
static function onSubmit() {
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\Subscription;
|
||||
use \MailPoet\Models\Subscriber;
|
||||
use \MailPoet\Util\Url;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Util\Url;
|
||||
|
||||
class Manage {
|
||||
|
||||
|
@ -1,16 +1,15 @@
|
||||
<?php
|
||||
namespace MailPoet\Subscription;
|
||||
|
||||
use \MailPoet\Models\Subscriber;
|
||||
use \MailPoet\Models\SubscriberSegment;
|
||||
use \MailPoet\Models\CustomField;
|
||||
use \MailPoet\Models\Setting;
|
||||
use \MailPoet\Models\Segment;
|
||||
use \MailPoet\Util\Helpers;
|
||||
use \MailPoet\Util\Url;
|
||||
use \MailPoet\Subscription;
|
||||
use \MailPoet\Form\Renderer as FormRenderer;
|
||||
use \MailPoet\Form\Block\Date as FormBlockDate;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Models\SubscriberSegment;
|
||||
use MailPoet\Models\CustomField;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Util\Url;
|
||||
use MailPoet\Subscription;
|
||||
use MailPoet\Form\Renderer as FormRenderer;
|
||||
use MailPoet\Form\Block\Date as FormBlockDate;
|
||||
|
||||
class Pages {
|
||||
const DEMO_EMAIL = 'demo@mailpoet.com';
|
||||
@ -88,7 +87,7 @@ class Pages {
|
||||
global $post;
|
||||
|
||||
if($this->isPreview() === false && $this->subscriber === false) {
|
||||
return __("Hmmm... we don't have a record of you", 'mailpoet');
|
||||
return __("Hmmm... we don't have a record of you.", 'mailpoet');
|
||||
}
|
||||
|
||||
if(
|
||||
@ -190,7 +189,7 @@ class Pages {
|
||||
|
||||
private function getUnsubscribeTitle() {
|
||||
if($this->isPreview() || $this->subscriber !== false) {
|
||||
return __("You are now unsubscribed", 'mailpoet');
|
||||
return __("You are now unsubscribed.", 'mailpoet');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\Subscription;
|
||||
use \MailPoet\Models\Setting;
|
||||
use \MailPoet\Models\Subscriber;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Models\Subscriber;
|
||||
|
||||
class Registration {
|
||||
|
||||
|
@ -24,6 +24,7 @@ class I18n extends \Twig_Extension {
|
||||
'localize' => 'localize',
|
||||
'__' => 'translate',
|
||||
'_n' => 'pluralize',
|
||||
'_x' => 'translateWithContext',
|
||||
'date' => 'date'
|
||||
);
|
||||
|
||||
@ -63,6 +64,12 @@ class I18n extends \Twig_Extension {
|
||||
return call_user_func_array('_n', $this->setTextDomain($args));
|
||||
}
|
||||
|
||||
function translateWithContext() {
|
||||
$args = func_get_args();
|
||||
|
||||
return call_user_func_array('_x', $this->setTextDomain($args));
|
||||
}
|
||||
|
||||
function date() {
|
||||
$args = func_get_args();
|
||||
$date = (isset($args[0])) ? $args[0] : null;
|
||||
@ -88,4 +95,4 @@ class I18n extends \Twig_Extension {
|
||||
}
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,25 +2,23 @@
|
||||
namespace MailPoet\Util;
|
||||
|
||||
class ConflictResolver {
|
||||
public $allowed_assets = array(
|
||||
public $permitted_assets_locations = array(
|
||||
'styles' => array(
|
||||
// WP default
|
||||
'admin-bar',
|
||||
'colors',
|
||||
'ie',
|
||||
'wp-auth-check',
|
||||
'^/wp-admin',
|
||||
'^/wp-includes',
|
||||
// third-party
|
||||
'query-monitor'
|
||||
'query-monitor',
|
||||
'wpt-tx-updater-network'
|
||||
),
|
||||
'scripts' => array(
|
||||
// WP default
|
||||
'common',
|
||||
'admin-bar',
|
||||
'utils',
|
||||
'svg-painter',
|
||||
'wp-auth-check',
|
||||
'^/wp-admin',
|
||||
'^/wp-includes',
|
||||
'googleapis.com/ajax/libs',
|
||||
// third-party
|
||||
'query-monitor'
|
||||
'query-monitor',
|
||||
'wpt-tx-updater-network'
|
||||
)
|
||||
);
|
||||
|
||||
@ -54,32 +52,39 @@ class ConflictResolver {
|
||||
}
|
||||
|
||||
function resolveStylesConflict() {
|
||||
$_this = $this;
|
||||
// unload all styles except from the list of allowed
|
||||
$dequeue_styles = function() {
|
||||
$dequeue_styles = function() use($_this) {
|
||||
global $wp_styles;
|
||||
if(empty($wp_styles->queue)) return;
|
||||
foreach($wp_styles->queue as $wp_style) {
|
||||
if(!in_array($wp_style, $this->allowed_assets['styles'])) {
|
||||
if(empty($wp_styles->registered[$wp_style])) continue;
|
||||
$registered_style = $wp_styles->registered[$wp_style];
|
||||
if(!preg_match('!' . implode('|', $_this->permitted_assets_locations['styles']) . '!i', $registered_style->src)) {
|
||||
wp_dequeue_style($wp_style);
|
||||
}
|
||||
}
|
||||
};
|
||||
add_action('wp_print_styles', $dequeue_styles);
|
||||
add_action('admin_print_styles', $dequeue_styles);
|
||||
add_action('admin_print_footer_scripts', $dequeue_styles);
|
||||
add_action('admin_footer', $dequeue_styles);
|
||||
add_action('wp_print_styles', $dequeue_styles, PHP_INT_MAX);
|
||||
add_action('admin_print_styles', $dequeue_styles, PHP_INT_MAX);
|
||||
add_action('admin_print_footer_scripts', $dequeue_styles, PHP_INT_MAX);
|
||||
add_action('admin_footer', $dequeue_styles, PHP_INT_MAX);
|
||||
}
|
||||
|
||||
function resolveScriptsConflict() {
|
||||
$_this = $this;
|
||||
// unload all scripts except from the list of allowed
|
||||
$dequeue_scripts = function() {
|
||||
$dequeue_scripts = function() use($_this) {
|
||||
global $wp_scripts;
|
||||
foreach($wp_scripts->queue as $wp_script) {
|
||||
if(!in_array($wp_script, $this->allowed_assets['scripts'])) {
|
||||
if(empty($wp_scripts->registered[$wp_script])) continue;
|
||||
$registered_script = $wp_scripts->registered[$wp_script];
|
||||
if(!preg_match('!' . implode('|', $_this->permitted_assets_locations['scripts']) . '!i', $registered_script->src)) {
|
||||
wp_dequeue_script($wp_script);
|
||||
}
|
||||
}
|
||||
};
|
||||
add_action('wp_print_scripts', $dequeue_scripts);
|
||||
add_action('admin_print_footer_scripts', $dequeue_scripts);
|
||||
add_action('wp_print_scripts', $dequeue_scripts, PHP_INT_MAX);
|
||||
add_action('admin_print_footer_scripts', $dequeue_scripts, PHP_INT_MAX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ class Notice {
|
||||
}
|
||||
|
||||
function displayWPNotice() {
|
||||
$class = sprintf('notice notice-%s', $this->type);
|
||||
$class = sprintf('notice notice-%s mailpoet_notice_server', $this->type);
|
||||
$message = nl2br($this->message);
|
||||
|
||||
printf('<div class="%1$s"><p>%2$s</p></div>', $class, $message);
|
||||
|
74
mailpoet.php
74
mailpoet.php
@ -1,40 +1,72 @@
|
||||
<?php
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
use MailPoet\Config\Initializer;
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
/*
|
||||
* Plugin Name: MailPoet
|
||||
* Version: 3.0.0-beta.13
|
||||
* Version: 3.0.0-beta.17
|
||||
* Plugin URI: http://www.mailpoet.com
|
||||
* Description: Create and send beautiful email newsletters, autoresponders, and post notifications without leaving WordPress. This is a beta version of our brand new plugin!
|
||||
* Author: MailPoet
|
||||
* Author URI: http://www.mailpoet.com
|
||||
* Requires at least: 4.6
|
||||
* Tested up to: 4.7
|
||||
* Tested up to: 4.7.2
|
||||
*
|
||||
* Text Domain: mailpoet
|
||||
* Domain Path: /lang/
|
||||
*
|
||||
* @package WordPress
|
||||
* @author MailPoet
|
||||
* @since 0.0.8
|
||||
* @since 3.0.0-beta.1
|
||||
*/
|
||||
|
||||
$mailpoet_loader = dirname(__FILE__) . '/vendor/autoload.php';
|
||||
if(file_exists($mailpoet_loader)) {
|
||||
require $mailpoet_loader;
|
||||
define('MAILPOET_VERSION', '3.0.0-beta.13');
|
||||
$initializer = new Initializer(
|
||||
array(
|
||||
'file' => __FILE__,
|
||||
'version' => MAILPOET_VERSION
|
||||
)
|
||||
);
|
||||
$initializer->init();
|
||||
} else {
|
||||
add_action('admin_notices', function() {
|
||||
$notice = __('MailPoet cannot start because it is missing core files. Please reinstall the plugin.', 'mailpoet');
|
||||
printf('<div class="error"><p>%1$s</p></div>', $notice);
|
||||
});
|
||||
$mailpoet_plugin = array(
|
||||
'version' => '3.0.0-beta.17',
|
||||
'filename' => __FILE__,
|
||||
'path' => dirname(__FILE__),
|
||||
'autoloader' => dirname(__FILE__) . '/vendor/autoload.php',
|
||||
'initializer' => dirname(__FILE__) . '/mailpoet_initializer.php'
|
||||
);
|
||||
|
||||
function mailpoet_deactivate_plugin() {
|
||||
deactivate_plugins(plugin_basename(__FILE__));
|
||||
if(!empty($_GET['activate'])) {
|
||||
unset($_GET['activate']);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for minimum supported PHP version
|
||||
if(version_compare(phpversion(), '5.3.0', '<')) {
|
||||
add_action('admin_notices', 'mailpoet_php_version_notice');
|
||||
// deactivate the plugin
|
||||
add_action('admin_init', 'mailpoet_deactivate_plugin');
|
||||
return;
|
||||
}
|
||||
|
||||
// Display PHP version error notice
|
||||
function mailpoet_php_version_notice() {
|
||||
$notice = str_replace(
|
||||
'[link]',
|
||||
'<a href="//beta.docs.mailpoet.com/article/152-minimum-requirements-for-mailpoet-3#php_version" target="_blank">',
|
||||
__('MailPoet plugin requires PHP version 5.3 or newer. Please read our [link]instructions[/link] on how to resolve this issue.', 'mailpoet')
|
||||
);
|
||||
$notice = str_replace('[/link]', '</a>', $notice);
|
||||
printf('<div class="error"><p>%1$s</p></div>', $notice);
|
||||
}
|
||||
|
||||
// Check for presence of core dependencies
|
||||
if(!file_exists($mailpoet_plugin['autoloader']) || !file_exists($mailpoet_plugin['initializer'])) {
|
||||
add_action('admin_notices', 'mailpoet_core_dependency_notice');
|
||||
// deactivate the plugin
|
||||
add_action('admin_init', 'mailpoet_deactivate_plugin');
|
||||
return;
|
||||
}
|
||||
|
||||
// Display missing core dependencies error notice
|
||||
function mailpoet_core_dependency_notice() {
|
||||
$notice = __('MailPoet cannot start because it is missing core files. Please reinstall the plugin.', 'mailpoet');
|
||||
printf('<div class="error"><p>%1$s</p></div>', $notice);
|
||||
}
|
||||
|
||||
// Initialize plugin
|
||||
require_once($mailpoet_plugin['initializer']);
|
||||
|
17
mailpoet_initializer.php
Normal file
17
mailpoet_initializer.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
use MailPoet\Config\Initializer;
|
||||
|
||||
if(!defined('ABSPATH') || empty($mailpoet_plugin)) exit;
|
||||
|
||||
require_once($mailpoet_plugin['autoloader']);
|
||||
|
||||
define('MAILPOET_VERSION', $mailpoet_plugin['version']);
|
||||
|
||||
$initializer = new Initializer(
|
||||
array(
|
||||
'file' => $mailpoet_plugin['filename'],
|
||||
'version' => $mailpoet_plugin['version']
|
||||
)
|
||||
);
|
||||
$initializer->init();
|
27
readme.txt
27
readme.txt
@ -1,9 +1,9 @@
|
||||
=== MailPoet 3 - Beta Version ===
|
||||
Contributors: mailpoet, wysija
|
||||
Tags: newsletter, email, welcome email, post notification, autoresponder, mailchimp, signup, smtp
|
||||
Tags: newsletter, email, welcome email, post notification, autoresponder, signup, smtp
|
||||
Requires at least: 4.6
|
||||
Tested up to: 4.7
|
||||
Stable tag: 3.0.0-beta.13
|
||||
Tested up to: 4.7.2
|
||||
Stable tag: 3.0.0-beta.17
|
||||
Create and send beautiful emails and newsletters from WordPress.
|
||||
|
||||
== Description ==
|
||||
@ -83,6 +83,27 @@ Our [support site](https://docs.mailpoet.com/) has plenty of articles. You can w
|
||||
|
||||
== Changelog ==
|
||||
|
||||
= 3.0.0-beta.17 - 2017-02-01 =
|
||||
* Added: send in style with MailPoet's own sending service. Visit your MailPoet Settings > Send with... tab.
|
||||
|
||||
= 3.0.0-beta.16 - 2017-01-31 =
|
||||
* Improved: Updated language strings for better translation support;
|
||||
* Fixed: subscription forms now allow to subscribe only to specified lists. Thanks Paul!
|
||||
* Fixed: subscription forms now ignore any extra fields added not via the Form editor. Thx again Paul!
|
||||
* Fixed: previewing sent welcome emails now displays latest email version. Thanks Tim!
|
||||
* Fixed: plugin no longer triggers a PHP error during initialization on hosts using PHP 5.3;
|
||||
* Fixed: plugin warns about missing required PDO_MYSQL extension.
|
||||
|
||||
= 3.0.0-beta.15 - 2017-01-24 =
|
||||
* Fixed: plugin no longer throws a fatal exception error on (prehistoric :)) hosts running older versions than PHP 5.3. Thanks Otto & jtm12!;
|
||||
* Fixed: users who are not subscribed to any list can be filtered in the admin panel;
|
||||
* Fixed: newsletter preview links can now be shared with non WP users.
|
||||
|
||||
= 3.0.0-beta.14 - 2017-01-19 =
|
||||
* Fixed: images can't be added to newsletters. Thanks Leon!;
|
||||
* Fixed: forms require first & last name input fields on some systems;
|
||||
* Fixed: unable to remove subscribers from lists in admin panel. Thanks Kay!
|
||||
|
||||
= 3.0.0-beta.13 - 2017-01-17 =
|
||||
* Improved: style/script conflicts on MailPoet pages are now resolved by unloading non-default assets. Thx Michel for reporting one such case!;
|
||||
* Fixed: MySQL wait_timeout of less than 20 seconds results in errors when sending. Thx Tim!;
|
||||
|
4
tasks/makepot/node_modules/grunt-wp-i18n/vendor/wp-i18n-tools/extract.php
generated
vendored
4
tasks/makepot/node_modules/grunt-wp-i18n/vendor/wp-i18n-tools/extract.php
generated
vendored
@ -260,6 +260,7 @@ class StringExtractor {
|
||||
|
||||
$function_patterns = array(
|
||||
'/(__)\((([\'"]).+?\3)\)/',
|
||||
'/(_x)\(([\'"].+?[\'"],\s*[\'"].+?[\'"])\)/',
|
||||
'/(_n)\(([\'"].+?[\'"],\s*[\'"].+?[\'"],\s*.+?)\)/'
|
||||
);
|
||||
|
||||
@ -287,7 +288,8 @@ class StringExtractor {
|
||||
|
||||
$arguments = array();
|
||||
foreach($arguments_matches[0] as $argument) {
|
||||
$arguments[] = trim($argument, "'\"");
|
||||
// Remove surrounding quotes of the same type from argument strings
|
||||
$arguments[] = preg_replace("/^(('|\")+)(.*)\\1$/", "\\3", $argument);
|
||||
}
|
||||
|
||||
$call = array(
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
use \MailPoet\API\API;
|
||||
use MailPoet\API\API;
|
||||
|
||||
// required to be able to use wp_delete_user()
|
||||
require_once(ABSPATH.'wp-admin/includes/user.php');
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
use \MailPoet\API\Endpoints\CustomFields;
|
||||
use \MailPoet\API\Response as APIResponse;
|
||||
use \MailPoet\Models\CustomField;
|
||||
use MailPoet\API\Endpoints\CustomFields;
|
||||
use MailPoet\API\Response as APIResponse;
|
||||
use MailPoet\Models\CustomField;
|
||||
|
||||
class CustomFieldsTest extends MailPoetTest {
|
||||
private $custom_fields = array(
|
||||
@ -97,18 +97,18 @@ class CustomFieldsTest extends MailPoetTest {
|
||||
// missing type
|
||||
$response = $router->save(array('name' => 'New custom field'));
|
||||
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
|
||||
expect($response->errors[0]['message'])->equals('Please specify a type');
|
||||
expect($response->errors[0]['message'])->equals('Please specify a type.');
|
||||
|
||||
// missing name
|
||||
$response = $router->save(array('type' => 'text'));
|
||||
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
|
||||
expect($response->errors[0]['message'])->equals('Please specify a name');
|
||||
expect($response->errors[0]['message'])->equals('Please specify a name.');
|
||||
|
||||
// missing data
|
||||
$response = $router->save();
|
||||
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
|
||||
expect($response->errors[0]['message'])->equals('Please specify a name');
|
||||
expect($response->errors[1]['message'])->equals('Please specify a type');
|
||||
expect($response->errors[0]['message'])->equals('Please specify a name.');
|
||||
expect($response->errors[1]['message'])->equals('Please specify a type.');
|
||||
}
|
||||
|
||||
function testItCanGetACustomField() {
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
use \MailPoet\API\Endpoints\Forms;
|
||||
use \MailPoet\API\Response as APIResponse;
|
||||
use \MailPoet\Models\Form;
|
||||
use \MailPoet\Models\Segment;
|
||||
use MailPoet\API\Endpoints\Forms;
|
||||
use MailPoet\API\Response as APIResponse;
|
||||
use MailPoet\Models\Form;
|
||||
use MailPoet\Models\Segment;
|
||||
|
||||
class FormsTest extends MailPoetTest {
|
||||
function _before() {
|
||||
@ -65,7 +65,7 @@ class FormsTest extends MailPoetTest {
|
||||
$router = new Forms();
|
||||
$response = $router->save(/* missing data */);
|
||||
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
|
||||
expect($response->errors[0]['message'])->equals('Please specify a name');
|
||||
expect($response->errors[0]['message'])->equals('Please specify a name.');
|
||||
|
||||
$response = $router->save($form_data);
|
||||
expect($response->status)->equals(APIResponse::STATUS_OK);
|
||||
|
@ -1,8 +1,7 @@
|
||||
<?php
|
||||
use \MailPoet\API\Response as APIResponse;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
use \MailPoet\API\Endpoints\NewsletterTemplates;
|
||||
use \MailPoet\Models\NewsletterTemplate;
|
||||
use MailPoet\API\Response as APIResponse;
|
||||
use MailPoet\API\Endpoints\NewsletterTemplates;
|
||||
use MailPoet\Models\NewsletterTemplate;
|
||||
|
||||
class NewsletterTemplatesTest extends MailPoetTest {
|
||||
function _before() {
|
||||
|
@ -8,6 +8,8 @@ use MailPoet\Models\NewsletterOptionField;
|
||||
use MailPoet\Models\NewsletterSegment;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Newsletter\Scheduler\Scheduler;
|
||||
use MailPoet\Newsletter\Url;
|
||||
use MailPoet\Router\Router;
|
||||
|
||||
class NewslettersTest extends MailPoetTest {
|
||||
function _before() {
|
||||
@ -29,7 +31,7 @@ class NewslettersTest extends MailPoetTest {
|
||||
function testItCanGetANewsletter() {
|
||||
$router = new Newsletters();
|
||||
|
||||
$response = $router->get(/* missing id */);
|
||||
$response = $router->get(); // missing id
|
||||
expect($response->status)->equals(APIResponse::STATUS_NOT_FOUND);
|
||||
expect($response->errors[0]['message'])
|
||||
->equals('This newsletter does not exist.');
|
||||
@ -78,7 +80,7 @@ class NewslettersTest extends MailPoetTest {
|
||||
|
||||
$response = $router->save($invalid_data);
|
||||
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
|
||||
expect($response->errors[0]['message'])->equals('Please specify a type');
|
||||
expect($response->errors[0]['message'])->equals('Please specify a type.');
|
||||
}
|
||||
|
||||
function testItCanSaveAnExistingNewsletter() {
|
||||
@ -282,7 +284,7 @@ class NewslettersTest extends MailPoetTest {
|
||||
|
||||
$response = $router->create();
|
||||
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
|
||||
expect($response->errors[0]['message'])->equals('Please specify a type');
|
||||
expect($response->errors[0]['message'])->equals('Please specify a type.');
|
||||
}
|
||||
|
||||
function testItCanGetListingData() {
|
||||
@ -517,7 +519,7 @@ class NewslettersTest extends MailPoetTest {
|
||||
expect($response->status)->equals(APIResponse::STATUS_OK);
|
||||
}
|
||||
|
||||
function testItReturnsMaillerErrorWhenSendingFailed() {
|
||||
function testItReturnsMailerErrorWhenSendingFailed() {
|
||||
$subscriber = 'test@subscriber.com';
|
||||
$data = array(
|
||||
'subscriber' => $subscriber,
|
||||
@ -542,10 +544,22 @@ class NewslettersTest extends MailPoetTest {
|
||||
expect($response->errors[0]['message'])->equals('The email could not be sent: failed');
|
||||
}
|
||||
|
||||
function testItGeneratesPreviewLinksWithNewsletterHashAndNoSubscriberData() {
|
||||
$router = new Newsletters();
|
||||
$response = $router->listing();
|
||||
$preview_link = $response->data[0]['preview_url'];
|
||||
parse_str(parse_url($preview_link, PHP_URL_QUERY), $preview_link_data);
|
||||
$preview_link_data = Url::transformUrlDataObject(Router::decodeRequestData($preview_link_data['data']));
|
||||
expect($preview_link_data['newsletter_hash'])->notEmpty();
|
||||
expect($preview_link_data['subscriber_id'])->false();
|
||||
expect($preview_link_data['subscriber_token'])->false();
|
||||
expect((boolean)$preview_link_data['preview'])->true();
|
||||
}
|
||||
|
||||
function _after() {
|
||||
Newsletter::deleteMany();
|
||||
NewsletterSegment::deleteMany();
|
||||
NewsletterOptionField::deleteMany();
|
||||
Segment::deleteMany();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
use \MailPoet\API\Endpoints\Segments;
|
||||
use \MailPoet\API\Response as APIResponse;
|
||||
use \MailPoet\Models\Segment;
|
||||
use MailPoet\API\Endpoints\Segments;
|
||||
use MailPoet\API\Response as APIResponse;
|
||||
use MailPoet\Models\Segment;
|
||||
|
||||
class SegmentsTest extends MailPoetTest {
|
||||
function _before() {
|
||||
@ -52,7 +52,7 @@ class SegmentsTest extends MailPoetTest {
|
||||
$router = new Segments();
|
||||
$response = $router->save(/* missing data */);
|
||||
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
|
||||
expect($response->errors[0]['message'])->equals('Please specify a name');
|
||||
expect($response->errors[0]['message'])->equals('Please specify a name.');
|
||||
|
||||
$response = $router->save($segment_data);
|
||||
expect($response->status)->equals(APIResponse::STATUS_OK);
|
||||
|
65
tests/unit/API/Endpoints/ServicesTest.php
Normal file
65
tests/unit/API/Endpoints/ServicesTest.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
use Codeception\Util\Stub;
|
||||
use MailPoet\API\Endpoints\Services;
|
||||
use MailPoet\API\Response as APIResponse;
|
||||
use MailPoet\Services\Bridge;
|
||||
|
||||
class ServicesTest extends MailPoetTest {
|
||||
function _before() {
|
||||
$this->services_endpoint = new Services();
|
||||
$this->data = array('key' => '1234567890abcdef');
|
||||
}
|
||||
|
||||
function testItRespondsWithErrorIfNoKeyIsGiven() {
|
||||
$response = $this->services_endpoint->verifyMailPoetKey(array('key' => ''));
|
||||
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
|
||||
expect($response->errors[0]['message'])->equals('Please specify a key.');
|
||||
}
|
||||
|
||||
function testItRespondsWithSuccessIfKeyIsValid() {
|
||||
$this->services_endpoint->bridge = Stub::make(
|
||||
new Bridge(),
|
||||
array('checkKey' => array('state' => Bridge::MAILPOET_KEY_VALID)),
|
||||
$this
|
||||
);
|
||||
$response = $this->services_endpoint->verifyMailPoetKey($this->data);
|
||||
expect($response->status)->equals(APIResponse::STATUS_OK);
|
||||
}
|
||||
|
||||
function testItRespondsWithErrorIfKeyIsInvalid() {
|
||||
$this->services_endpoint->bridge = Stub::make(
|
||||
new Bridge(),
|
||||
array('checkKey' => array('state' => Bridge::MAILPOET_KEY_INVALID)),
|
||||
$this
|
||||
);
|
||||
$response = $this->services_endpoint->verifyMailPoetKey($this->data);
|
||||
expect($response->status)->equals(APIResponse::STATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
function testItRespondsWithErrorIfKeyIsExpiring() {
|
||||
$date = new DateTime;
|
||||
$this->services_endpoint->bridge = Stub::make(
|
||||
new Bridge(),
|
||||
array('checkKey' => array(
|
||||
'state' => Bridge::MAILPOET_KEY_EXPIRING,
|
||||
'data' => array('expire_at' => $date->format('c'))
|
||||
)),
|
||||
$this
|
||||
);
|
||||
$response = $this->services_endpoint->verifyMailPoetKey($this->data);
|
||||
expect($response->status)->equals(APIResponse::STATUS_OK);
|
||||
expect($response->data['message'])->contains($date->format('Y-m-d'));
|
||||
}
|
||||
|
||||
function testItRespondsWithErrorIfServiceIsUnavailable() {
|
||||
$this->services_endpoint->bridge = Stub::make(
|
||||
new Bridge(),
|
||||
array('checkKey' => array('code' => Bridge::CHECK_ERROR_UNAVAILABLE)),
|
||||
$this
|
||||
);
|
||||
$response = $this->services_endpoint->verifyMailPoetKey($this->data);
|
||||
expect($response->status)->equals(APIResponse::STATUS_NOT_FOUND);
|
||||
expect($response->errors[0]['message'])->contains((string)Bridge::CHECK_ERROR_UNAVAILABLE);
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
use \MailPoet\API\Response as APIResponse;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
use \MailPoet\API\Endpoints\Settings;
|
||||
use \MailPoet\Models\Setting;
|
||||
use MailPoet\API\Response as APIResponse;
|
||||
use MailPoet\API\Error as APIError;
|
||||
use MailPoet\API\Endpoints\Settings;
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
class SettingsTest extends MailPoetTest {
|
||||
function _before() {
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
use \MailPoet\API\Response as APIResponse;
|
||||
use \MailPoet\API\Endpoints\Setup;
|
||||
use \MailPoet\Models\Setting;
|
||||
use MailPoet\API\Response as APIResponse;
|
||||
use MailPoet\API\Endpoints\Setup;
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
class SetupTest extends MailPoetTest {
|
||||
function _before() {
|
||||
|
@ -1,10 +1,12 @@
|
||||
<?php
|
||||
|
||||
use \MailPoet\API\Endpoints\Subscribers;
|
||||
use \MailPoet\API\Response as APIResponse;
|
||||
use \MailPoet\Models\Subscriber;
|
||||
use \MailPoet\Models\Segment;
|
||||
use \MailPoet\Models\Setting;
|
||||
use Codeception\Util\Fixtures;
|
||||
use MailPoet\API\Endpoints\Subscribers;
|
||||
use MailPoet\API\Response as APIResponse;
|
||||
use MailPoet\Models\Form;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
class SubscribersTest extends MailPoetTest {
|
||||
function _before() {
|
||||
@ -28,6 +30,18 @@ class SubscribersTest extends MailPoetTest {
|
||||
)
|
||||
));
|
||||
|
||||
$this->form = Form::createOrUpdate(array(
|
||||
'name' => 'My Form',
|
||||
'body' => Fixtures::get('form_body_template'),
|
||||
'settings' => array(
|
||||
'segments_selected_by' => 'user',
|
||||
'segments' => array(
|
||||
$this->segment_1->id,
|
||||
$this->segment_2->id
|
||||
)
|
||||
)
|
||||
));
|
||||
|
||||
// setup mailer
|
||||
Setting::setValue('sender', array(
|
||||
'address' => 'sender@mailpoet.com',
|
||||
@ -116,6 +130,20 @@ class SubscribersTest extends MailPoetTest {
|
||||
expect($response->data['first_name'])->equals('Super Jane');
|
||||
}
|
||||
|
||||
function testItCanRemoveListsFromAnExistingSubscriber() {
|
||||
$router = new Subscribers();
|
||||
$subscriber_data = $this->subscriber_2->asArray();
|
||||
unset($subscriber_data['created_at']);
|
||||
unset($subscriber_data['segments']);
|
||||
|
||||
$response = $router->save($subscriber_data);
|
||||
expect($response->status)->equals(APIResponse::STATUS_OK);
|
||||
expect($response->data)->equals(
|
||||
Subscriber::findOne($this->subscriber_2->id)->asArray()
|
||||
);
|
||||
expect($this->subscriber_2->segments()->findArray())->count(0);
|
||||
}
|
||||
|
||||
function testItCanRestoreASubscriber() {
|
||||
$this->subscriber_1->trash();
|
||||
|
||||
@ -361,10 +389,22 @@ class SubscribersTest extends MailPoetTest {
|
||||
expect($response->errors[0]['message'])->contains('has no method');
|
||||
}
|
||||
|
||||
function testItCannotSubscribeWithoutSegments() {
|
||||
function testItCannotSubscribeWithoutFormID() {
|
||||
$router = new Subscribers();
|
||||
$response = $router->subscribe(array(
|
||||
'email' => 'toto@mailpoet.com'
|
||||
// no form ID specified
|
||||
));
|
||||
|
||||
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
|
||||
expect($response->errors[0]['message'])->equals('Please specify a valid form ID.');
|
||||
}
|
||||
|
||||
function testItCannotSubscribeWithoutSegmentsIfTheyAreSelectedByUser() {
|
||||
$router = new Subscribers();
|
||||
$response = $router->subscribe(array(
|
||||
'email' => 'toto@mailpoet.com',
|
||||
'form_id' => $this->form->id
|
||||
// no segments specified
|
||||
));
|
||||
|
||||
@ -376,23 +416,84 @@ class SubscribersTest extends MailPoetTest {
|
||||
$router = new Subscribers();
|
||||
$response = $router->subscribe(array(
|
||||
'email' => 'toto@mailpoet.com',
|
||||
'form_id' => $this->form->id,
|
||||
'segments' => array($this->segment_1->id, $this->segment_2->id)
|
||||
));
|
||||
expect($response->status)->equals(APIResponse::STATUS_OK);
|
||||
}
|
||||
|
||||
function testItCanSubscribeWithoutSegmentsIfTheyAreSelectedByAdmin() {
|
||||
$form = $this->form->asArray();
|
||||
$form['settings']['segments_selected_by'] = 'admin';
|
||||
$this->form->settings = $form['settings'];
|
||||
$this->form->save();
|
||||
|
||||
$router = new Subscribers();
|
||||
$response = $router->subscribe(array(
|
||||
'email' => 'toto@mailpoet.com',
|
||||
'form_id' => $this->form->id
|
||||
// no segments specified
|
||||
));
|
||||
|
||||
expect($response->status)->equals(APIResponse::STATUS_OK);
|
||||
$subscriber = Subscriber::findOne($response->data['id']);
|
||||
$subscriber_segments = $subscriber->segments()->findArray();
|
||||
expect($subscriber_segments)->count(2);
|
||||
expect($subscriber_segments[0]['id'])->equals($form['settings']['segments'][0]);
|
||||
expect($subscriber_segments[1]['id'])->equals($form['settings']['segments'][1]);
|
||||
}
|
||||
|
||||
function testItCannotSubscribeIfFormHasNoSegmentsDefined() {
|
||||
$form = $this->form->asArray();
|
||||
$form['settings']['segments_selected_by'] = 'admin';
|
||||
unset($form['settings']['segments']);
|
||||
$this->form->settings = $form['settings'];
|
||||
$this->form->save();
|
||||
|
||||
$router = new Subscribers();
|
||||
$response = $router->subscribe(array(
|
||||
'email' => 'toto@mailpoet.com',
|
||||
'form_id' => $this->form->id,
|
||||
'segments' => array($this->segment_1->id, $this->segment_2->id)
|
||||
));
|
||||
|
||||
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
|
||||
expect($response->errors[0]['message'])->equals('Please select a list.');
|
||||
}
|
||||
|
||||
function testItCanFilterOutNonFormFieldsWhenSubscribing() {
|
||||
$router = new Subscribers();
|
||||
$response = $router->subscribe(array(
|
||||
'email' => 'toto@mailpoet.com',
|
||||
'form_id' => $this->form->id,
|
||||
'segments' => array($this->segment_1->id, $this->segment_2->id),
|
||||
// exists in table and in the form
|
||||
'first_name' => 'aaa',
|
||||
// exists in table, but not in the form
|
||||
'last_name' => 'bbb',
|
||||
// doesn't exist
|
||||
'bogus' => 'hahaha'
|
||||
));
|
||||
expect($response->status)->equals(APIResponse::STATUS_OK);
|
||||
expect($response->data['first_name'])->equals('aaa');
|
||||
expect($response->data['last_name'])->isEmpty();
|
||||
expect(isset($response->data['bogus']))->false();
|
||||
}
|
||||
|
||||
function testItCannotMassSubscribe() {
|
||||
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||
|
||||
$router = new Subscribers();
|
||||
$response = $router->subscribe(array(
|
||||
'email' => 'toto@mailpoet.com',
|
||||
'form_id' => $this->form->id,
|
||||
'segments' => array($this->segment_1->id, $this->segment_2->id)
|
||||
));
|
||||
|
||||
try {
|
||||
$response = $router->subscribe(array(
|
||||
'email' => 'tata@mailpoet.com',
|
||||
'form_id' => $this->form->id,
|
||||
'segments' => array($this->segment_1->id, $this->segment_2->id)
|
||||
));
|
||||
$this->fail('It should not be possible to subscribe a second time so soon');
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user