MailPoet Newsletters (New) - Version 3.4.2

Version Description

  • 2018-02-13 =
  • Premium: you can now segment your subscribers by opened/clicked/unopened events;
  • Improved: default post search parameters inside newsletter editor can be manually changed using a custom WordPress filter. Thanks Jose Salazar;
  • Fixed: saving email templates when website uses both HTTP and HTTPS protocols.
Download this release

Release Info

Developer wysija
Plugin Icon 128x128 MailPoet Newsletters (New)
Version 3.4.2
Comparing to
See all releases

Code changes from version 3.4.1 to 3.4.2

Files changed (43) hide show
  1. assets/js/{admin.e914b58f.js → admin.fd56d82f.js} +14 -2
  2. assets/js/{admin_vendor.d60039d9.js → admin_vendor.dd4a8492.js} +3 -1
  3. assets/js/lib/mailpoet_shortcodes/plugin.js +16 -18
  4. assets/js/manifest.json +3 -3
  5. assets/js/{vendor.e9cd522f.js → vendor.30849db9.js} +1 -1
  6. lang/mailpoet-ca.mo +0 -0
  7. lang/mailpoet-da_DK.mo +0 -0
  8. lang/mailpoet-de_DE.mo +0 -0
  9. lang/mailpoet-en_GB.mo +0 -0
  10. lang/mailpoet-es_ES.mo +0 -0
  11. lang/mailpoet-fa_IR.mo +0 -0
  12. lang/mailpoet-fr_CA.mo +0 -0
  13. lang/mailpoet-fr_FR.mo +0 -0
  14. lang/mailpoet-it_IT.mo +0 -0
  15. lang/mailpoet-ja.mo +0 -0
  16. lang/mailpoet-nl_NL.mo +0 -0
  17. lang/mailpoet-pl_PL.mo +0 -0
  18. lang/mailpoet-pt_BR.mo +0 -0
  19. lang/mailpoet-pt_PT.mo +0 -0
  20. lang/mailpoet-ru_RU.mo +0 -0
  21. lang/mailpoet-sq.mo +0 -0
  22. lang/mailpoet-sv_SE.mo +0 -0
  23. lang/mailpoet-tr_TR.mo +0 -0
  24. lang/mailpoet.pot +17 -12
  25. lib/API/JSON/v1/AutomatedLatestContent.php +13 -13
  26. lib/API/JSON/v1/NewsletterTemplates.php +3 -0
  27. lib/Models/CustomField.php +1 -16
  28. lib/Models/Form.php +0 -17
  29. lib/Models/Model.php +48 -0
  30. lib/Models/Newsletter.php +3 -17
  31. lib/Models/NewsletterOption.php +7 -13
  32. lib/Models/NewsletterTemplate.php +19 -18
  33. lib/Models/ScheduledTaskSubscriber.php +8 -14
  34. lib/Models/Segment.php +0 -19
  35. lib/Models/Setting.php +2 -14
  36. lib/Models/SubscriberCustomField.php +4 -12
  37. lib/Models/SubscriberSegment.php +6 -19
  38. mailpoet.php +2 -2
  39. readme.txt +6 -1
  40. vendor/autoload.php +1 -1
  41. vendor/composer/autoload_real.php +7 -7
  42. vendor/composer/autoload_static.php +5 -5
  43. views/newsletters.html +3 -1
assets/js/{admin.e914b58f.js → admin.fd56d82f.js} RENAMED
@@ -10449,7 +10449,8 @@ webpackJsonp([0],{
10449
  var _this2 = this;
10450
 
10451
  var iframe = document.createElement('iframe');
10452
- iframe.src = response.meta.preview_url;
 
10453
  iframe.onload = function () {
10454
  html2canvas(iframe.contentDocument.documentElement).then(function (thumbnail) {
10455
  document.body.removeChild(iframe);
@@ -10468,9 +10469,20 @@ webpackJsonp([0],{
10468
  }).then(done).fail(_this2.showError);
10469
  });
10470
  };
 
 
 
 
 
 
 
10471
  // just to hide the iframe
10472
  iframe.className = 'mailpoet_template_iframe';
10473
- document.body.appendChild(iframe);
 
 
 
 
10474
  },
10475
  handleSend: function handleSend(e) {
10476
  var _this3 = this;
10449
  var _this2 = this;
10450
 
10451
  var iframe = document.createElement('iframe');
10452
+ var protocol = location.href.startsWith('https://') ? 'https' : 'http';
10453
+ iframe.src = protocol + response.meta.preview_url.replace(/^https?/, '');
10454
  iframe.onload = function () {
10455
  html2canvas(iframe.contentDocument.documentElement).then(function (thumbnail) {
10456
  document.body.removeChild(iframe);
10469
  }).then(done).fail(_this2.showError);
10470
  });
10471
  };
10472
+ var onError = function onError() {
10473
+ document.body.removeChild(iframe);
10474
+ MailPoet.Notice.error([MailPoet.I18n.t('errorWhileTakingScreenshot')], { scroll: true });
10475
+ done();
10476
+ };
10477
+ iframe.onerror = onError;
10478
+ iframe.onError = onError;
10479
  // just to hide the iframe
10480
  iframe.className = 'mailpoet_template_iframe';
10481
+ try {
10482
+ document.body.appendChild(iframe);
10483
+ } catch (err) {
10484
+ onError();
10485
+ }
10486
  },
10487
  handleSend: function handleSend(e) {
10488
  var _this3 = this;
assets/js/{admin_vendor.d60039d9.js → admin_vendor.dd4a8492.js} RENAMED
@@ -31338,7 +31338,9 @@ webpackJsonp([1],[
31338
  action: 'delete',
31339
  group: 'trash'
31340
  }).done(function (response) {
31341
- _mailpoet2['default'].Notice.success(_mailpoet2['default'].I18n.t('permanentlyDeleted').replace('%d', response.meta.count));
 
 
31342
  // redirect to default group
31343
  _this11.handleGroup('all');
31344
  }).fail(function (response) {
31338
  action: 'delete',
31339
  group: 'trash'
31340
  }).done(function (response) {
31341
+ if (_this11.props.messages !== undefined && _this11.props.messages.onDelete !== undefined) {
31342
+ _this11.props.messages.onDelete(response);
31343
+ }
31344
  // redirect to default group
31345
  _this11.handleGroup('all');
31346
  }).fail(function (response) {
assets/js/lib/mailpoet_shortcodes/plugin.js CHANGED
@@ -8,35 +8,33 @@
8
  * its placeholder into editor text.
9
  */
10
 
11
- /* jshint unused:false */
12
- /* global tinymce:true */
13
- tinymce.PluginManager.add('mailpoet_shortcodes', function (editor) { // eslint-disable-line func-names
14
- var appendLabelAndClose = function (shortcode) { // eslint-disable-line func-names
15
- editor.insertContent(shortcode);
16
- editor.windowManager.close();
17
- };
18
- var generateOnClickFunc = function (shortcode) { // eslint-disable-line func-names
19
- return function () { // eslint-disable-line func-names
20
- appendLabelAndClose(shortcode);
 
21
  };
22
- };
23
 
24
  editor.addButton('mailpoet_shortcodes', {
25
  icon: 'mailpoet_shortcodes',
26
- onclick: function () { // eslint-disable-line func-names
27
- var shortcodes = [];
28
- var configShortcodes = editor.settings.mailpoet_shortcodes;
29
- var segment;
30
- var i;
31
 
32
- for (segment in configShortcodes) {
33
  if (configShortcodes.hasOwnProperty(segment)) {
34
  shortcodes.push({
35
  type: 'label',
36
  text: segment
37
  });
38
 
39
- for (i = 0; i < configShortcodes[segment].length; i += 1) {
40
  shortcodes.push({
41
  type: 'button',
42
  text: configShortcodes[segment][i].text,
8
  * its placeholder into editor text.
9
  */
10
 
11
+ /*jshint unused:false */
12
+ /*global tinymce:true */
13
+ tinymce.PluginManager.add('mailpoet_shortcodes', function(editor, url) {
14
+ var appendLabelAndClose = function(shortcode) {
15
+ editor.insertContent(shortcode);
16
+ editor.windowManager.close();
17
+ },
18
+ generateOnClickFunc = function(shortcode) {
19
+ return function() {
20
+ appendLabelAndClose(shortcode);
21
+ };
22
  };
 
23
 
24
  editor.addButton('mailpoet_shortcodes', {
25
  icon: 'mailpoet_shortcodes',
26
+ onclick: function() {
27
+ var shortcodes = [],
28
+ configShortcodes = editor.settings.mailpoet_shortcodes;
 
 
29
 
30
+ for (var segment in configShortcodes) {
31
  if (configShortcodes.hasOwnProperty(segment)) {
32
  shortcodes.push({
33
  type: 'label',
34
  text: segment
35
  });
36
 
37
+ for (var i = 0; i < configShortcodes[segment].length; i += 1) {
38
  shortcodes.push({
39
  type: 'button',
40
  text: configShortcodes[segment][i].text,
assets/js/manifest.json CHANGED
@@ -1,10 +1,10 @@
1
  {
2
  "mp2migrator.js": "mp2migrator.dc0d6e2b.js",
3
  "public.js": "public.ea9ffa3f.js",
4
- "admin.js": "admin.e914b58f.js",
5
- "admin_vendor.js": "admin_vendor.d60039d9.js",
6
  "form_editor.js": "form_editor.13982476.js",
7
  "mailpoet.js": "mailpoet.a55b11ee.js",
8
  "newsletter_editor.js": "newsletter_editor.6416262e.js",
9
- "vendor.js": "vendor.e9cd522f.js"
10
  }
1
  {
2
  "mp2migrator.js": "mp2migrator.dc0d6e2b.js",
3
  "public.js": "public.ea9ffa3f.js",
4
+ "admin.js": "admin.fd56d82f.js",
5
+ "admin_vendor.js": "admin_vendor.dd4a8492.js",
6
  "form_editor.js": "form_editor.13982476.js",
7
  "mailpoet.js": "mailpoet.a55b11ee.js",
8
  "newsletter_editor.js": "newsletter_editor.6416262e.js",
9
+ "vendor.js": "vendor.30849db9.js"
10
  }
assets/js/{vendor.e9cd522f.js → vendor.30849db9.js} RENAMED
@@ -76,7 +76,7 @@
76
  /******/ script.charset = 'utf-8';
77
  /******/ script.async = true;
78
 
79
- /******/ script.src = __webpack_require__.p + "" + ({"0":"admin","1":"admin_vendor","2":"form_editor","3":"mailpoet","4":"newsletter_editor"}[chunkId]||chunkId) + "." + {"0":"e914b58f","1":"d60039d9","2":"13982476","3":"a55b11ee","4":"6416262e"}[chunkId] + ".chunk.js";
80
  /******/ head.appendChild(script);
81
  /******/ }
82
  /******/ };
76
  /******/ script.charset = 'utf-8';
77
  /******/ script.async = true;
78
 
79
+ /******/ script.src = __webpack_require__.p + "" + ({"0":"admin","1":"admin_vendor","2":"form_editor","3":"mailpoet","4":"newsletter_editor"}[chunkId]||chunkId) + "." + {"0":"fd56d82f","1":"dd4a8492","2":"13982476","3":"a55b11ee","4":"6416262e"}[chunkId] + ".chunk.js";
80
  /******/ head.appendChild(script);
81
  /******/ }
82
  /******/ };
lang/mailpoet-ca.mo CHANGED
Binary file
lang/mailpoet-da_DK.mo CHANGED
Binary file
lang/mailpoet-de_DE.mo CHANGED
Binary file
lang/mailpoet-en_GB.mo CHANGED
Binary file
lang/mailpoet-es_ES.mo CHANGED
Binary file
lang/mailpoet-fa_IR.mo CHANGED
Binary file
lang/mailpoet-fr_CA.mo CHANGED
Binary file
lang/mailpoet-fr_FR.mo CHANGED
Binary file
lang/mailpoet-it_IT.mo CHANGED
Binary file
lang/mailpoet-ja.mo CHANGED
Binary file
lang/mailpoet-nl_NL.mo CHANGED
Binary file
lang/mailpoet-pl_PL.mo CHANGED
Binary file
lang/mailpoet-pt_BR.mo CHANGED
Binary file
lang/mailpoet-pt_PT.mo CHANGED
Binary file
lang/mailpoet-ru_RU.mo CHANGED
Binary file
lang/mailpoet-sq.mo CHANGED
Binary file
lang/mailpoet-sv_SE.mo CHANGED
Binary file
lang/mailpoet-tr_TR.mo CHANGED
Binary file
lang/mailpoet.pot CHANGED
@@ -4,7 +4,7 @@ msgid ""
4
  msgstr ""
5
  "Project-Id-Version: \n"
6
  "Report-Msgid-Bugs-To: http://support.mailpoet.com/\n"
7
- "POT-Creation-Date: 2018-02-06 12:39:21+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -26,6 +26,13 @@ msgstr ""
26
  "X-Poedit-Bookmarks: \n"
27
  "X-Textdomain-Support: yes\n"
28
 
 
 
 
 
 
 
 
29
  #: lib/API/API.php:19
30
  msgid "Invalid API version."
31
  msgstr ""
@@ -103,7 +110,7 @@ msgid "The email could not be sent: %s"
103
  msgstr ""
104
 
105
  #: lib/API/JSON/v1/NewsletterTemplates.php:22
106
- #: lib/API/JSON/v1/NewsletterTemplates.php:65
107
  msgid "This template does not exist."
108
  msgstr ""
109
 
@@ -307,13 +314,6 @@ msgstr ""
307
  msgid "MailPoet Newsletter"
308
  msgstr ""
309
 
310
- #: lib/Config/Initializer.php:46
311
- msgid ""
312
- "Unable to connect to the database (the database is unable to open a file or "
313
- "folder), the connection is likely not configured correctly. Please read our "
314
- "[link] Knowledge Base article [/link] for steps how to resolve it."
315
- msgstr ""
316
-
317
  #: lib/Config/MP2Migrator.php:151
318
  msgid "Start import"
319
  msgstr ""
@@ -1307,7 +1307,7 @@ msgid "MailPoet API key is invalid!"
1307
  msgstr ""
1308
 
1309
  #: lib/Models/CustomField.php:20 lib/Models/Form.php:13
1310
- #: lib/Models/NewsletterOptionField.php:12 lib/Models/NewsletterTemplate.php:13
1311
  #: lib/Models/Segment.php:15 lib/Models/Setting.php:22
1312
  #: views/form/templates/settings/field_form.hbs:53
1313
  #: views/subscribers/importExport/import/step2.html:134
@@ -1331,7 +1331,8 @@ msgstr ""
1331
  msgid "Trash"
1332
  msgstr ""
1333
 
1334
- #: lib/Models/Model.php:60 views/subscribers/importExport/import/step2.html:137
 
1335
  msgid "Another record already exists. Please specify a different \"%1$s\"."
1336
  msgstr ""
1337
 
@@ -1374,7 +1375,7 @@ msgstr ""
1374
  msgid "Please specify a newsletter type."
1375
  msgstr ""
1376
 
1377
- #: lib/Models/NewsletterTemplate.php:16
1378
  msgid "The template body cannot be empty."
1379
  msgstr ""
1380
 
@@ -3944,6 +3945,10 @@ msgstr ""
3944
  msgid "This category does not contain any template yet!"
3945
  msgstr ""
3946
 
 
 
 
 
3947
  #: views/premium.html:6
3948
  msgid "What is MailPoet Premium?"
3949
  msgstr ""
4
  msgstr ""
5
  "Project-Id-Version: \n"
6
  "Report-Msgid-Bugs-To: http://support.mailpoet.com/\n"
7
+ "POT-Creation-Date: 2018-02-13 18:51:04+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
26
  "X-Poedit-Bookmarks: \n"
27
  "X-Textdomain-Support: yes\n"
28
 
29
+ #: Initializer.php:63 lib/Config/Initializer.php:46
30
+ msgid ""
31
+ "Unable to connect to the database (the database is unable to open a file or "
32
+ "folder), the connection is likely not configured correctly. Please read our "
33
+ "[link] Knowledge Base article [/link] for steps how to resolve it."
34
+ msgstr ""
35
+
36
  #: lib/API/API.php:19
37
  msgid "Invalid API version."
38
  msgstr ""
110
  msgstr ""
111
 
112
  #: lib/API/JSON/v1/NewsletterTemplates.php:22
113
+ #: lib/API/JSON/v1/NewsletterTemplates.php:68
114
  msgid "This template does not exist."
115
  msgstr ""
116
 
314
  msgid "MailPoet Newsletter"
315
  msgstr ""
316
 
 
 
 
 
 
 
 
317
  #: lib/Config/MP2Migrator.php:151
318
  msgid "Start import"
319
  msgstr ""
1307
  msgstr ""
1308
 
1309
  #: lib/Models/CustomField.php:20 lib/Models/Form.php:13
1310
+ #: lib/Models/NewsletterOptionField.php:12 lib/Models/NewsletterTemplate.php:16
1311
  #: lib/Models/Segment.php:15 lib/Models/Setting.php:22
1312
  #: views/form/templates/settings/field_form.hbs:53
1313
  #: views/subscribers/importExport/import/step2.html:134
1331
  msgid "Trash"
1332
  msgstr ""
1333
 
1334
+ #: lib/Models/Model.php:108
1335
+ #: views/subscribers/importExport/import/step2.html:137
1336
  msgid "Another record already exists. Please specify a different \"%1$s\"."
1337
  msgstr ""
1338
 
1375
  msgid "Please specify a newsletter type."
1376
  msgstr ""
1377
 
1378
+ #: lib/Models/NewsletterTemplate.php:19
1379
  msgid "The template body cannot be empty."
1380
  msgstr ""
1381
 
3945
  msgid "This category does not contain any template yet!"
3946
  msgstr ""
3947
 
3948
+ #: views/newsletters.html:275
3949
+ msgid "An error occured while saving the template in \"Recently sent\""
3950
+ msgstr ""
3951
+
3952
  #: views/premium.html:6
3953
  msgid "What is MailPoet Premium?"
3954
  msgstr ""
lib/API/JSON/v1/AutomatedLatestContent.php CHANGED
@@ -4,6 +4,7 @@ namespace MailPoet\API\JSON\v1;
4
 
5
  use MailPoet\API\JSON\Endpoint as APIEndpoint;
6
  use MailPoet\Config\AccessControl;
 
7
  use MailPoet\WP\Posts as WPPosts;
8
 
9
  if(!defined('ABSPATH')) exit;
@@ -43,20 +44,19 @@ class AutomatedLatestContent extends APIEndpoint {
43
  $search = (isset($data['search'])) ? $data['search'] : '';
44
  $limit = (isset($data['limit'])) ? (int)$data['limit'] : 50;
45
  $page = (isset($data['page'])) ? (int)$data['page'] : 1;
46
-
47
- return $this->successResponse(
48
- WPPosts::getTerms(
49
- array(
50
- 'taxonomy' => $taxonomies,
51
- 'hide_empty' => false,
52
- 'search' => $search,
53
- 'number' => $limit,
54
- 'offset' => $limit * ($page - 1),
55
- 'orderby' => 'name',
56
- 'order' => 'ASC'
57
- )
58
- )
59
  );
 
 
 
 
60
  }
61
 
62
  function getPosts($data = array()) {
4
 
5
  use MailPoet\API\JSON\Endpoint as APIEndpoint;
6
  use MailPoet\Config\AccessControl;
7
+ use MailPoet\WP\Hooks;
8
  use MailPoet\WP\Posts as WPPosts;
9
 
10
  if(!defined('ABSPATH')) exit;
44
  $search = (isset($data['search'])) ? $data['search'] : '';
45
  $limit = (isset($data['limit'])) ? (int)$data['limit'] : 50;
46
  $page = (isset($data['page'])) ? (int)$data['page'] : 1;
47
+ $args = array(
48
+ 'taxonomy' => $taxonomies,
49
+ 'hide_empty' => false,
50
+ 'search' => $search,
51
+ 'number' => $limit,
52
+ 'offset' => $limit * ($page - 1),
53
+ 'orderby' => 'name',
54
+ 'order' => 'ASC'
 
 
 
 
 
55
  );
56
+
57
+ $args = Hooks::applyFilters('mailpoet_search_terms_args', $args);
58
+
59
+ return $this->successResponse(WPPosts::getTerms($args));
60
  }
61
 
62
  function getPosts($data = array()) {
lib/API/JSON/v1/NewsletterTemplates.php CHANGED
@@ -45,9 +45,12 @@ class NewsletterTemplates extends APIEndpoint {
45
  $data['id'] = $template['id'];
46
  }
47
  }
 
48
  $template = NewsletterTemplate::createOrUpdate($data);
49
  $errors = $template->getErrors();
50
 
 
 
51
  if(!empty($errors)) {
52
  return $this->errorResponse($errors);
53
  } else {
45
  $data['id'] = $template['id'];
46
  }
47
  }
48
+
49
  $template = NewsletterTemplate::createOrUpdate($data);
50
  $errors = $template->getErrors();
51
 
52
+ NewsletterTemplate::cleanRecentlySent($data);
53
+
54
  if(!empty($errors)) {
55
  return $this->errorResponse($errors);
56
  } else {
lib/Models/CustomField.php CHANGED
@@ -127,25 +127,10 @@ class CustomField extends Model {
127
  }
128
 
129
  static function createOrUpdate($data = array()) {
130
- $custom_field = false;
131
-
132
- if(isset($data['id']) && (int)$data['id'] > 0) {
133
- $custom_field = self::findOne((int)$data['id']);
134
- }
135
-
136
  // set name as label by default
137
  if(empty($data['params']['label']) && isset($data['name'])) {
138
  $data['params']['label'] = $data['name'];
139
  }
140
-
141
- if($custom_field === false) {
142
- $custom_field = self::create();
143
- $custom_field->hydrate($data);
144
- } else {
145
- unset($data['id']);
146
- $custom_field->set($data);
147
- }
148
-
149
- return $custom_field->save();
150
  }
151
  }
127
  }
128
 
129
  static function createOrUpdate($data = array()) {
 
 
 
 
 
 
130
  // set name as label by default
131
  if(empty($data['params']['label']) && isset($data['name'])) {
132
  $data['params']['label'] = $data['name'];
133
  }
134
+ return parent::_createOrUpdate($data);
 
 
 
 
 
 
 
 
 
135
  }
136
  }
lib/Models/Form.php CHANGED
@@ -108,21 +108,4 @@ class Form extends Model {
108
  return $orm->whereNull('deleted_at');
109
  }
110
 
111
- static function createOrUpdate($data = array()) {
112
- $form = false;
113
-
114
- if(isset($data['id']) && (int)$data['id'] > 0) {
115
- $form = self::findOne((int)$data['id']);
116
- }
117
-
118
- if($form === false) {
119
- $form = self::create();
120
- $form->hydrate($data);
121
- } else {
122
- unset($data['id']);
123
- $form->set($data);
124
- }
125
-
126
- return $form->save();
127
- }
128
  }
108
  return $orm->whereNull('deleted_at');
109
  }
110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  }
lib/Models/Model.php CHANGED
@@ -20,6 +20,54 @@ class Model extends \Sudzy\ValidModel {
20
  return parent::create();
21
  }
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  function getErrors() {
24
  if(empty($this->_errors)) {
25
  return false;
20
  return parent::create();
21
  }
22
 
23
+ /**
24
+ * Creates a row, or updates it if already exists. It tries to find the existing
25
+ * row by `id` (if given in `$data`), or by the given `$keys`. If `$onCreate` is
26
+ * given, it's used to transform `$data` before creating the new row.
27
+ *
28
+ * @param array $data
29
+ * @param boolean $keys
30
+ * @param callable $onCreate
31
+ * @return self
32
+ */
33
+ static protected function _createOrUpdate($data = array(), $keys = false, $onCreate = false) {
34
+ $model = false;
35
+
36
+ if(isset($data['id']) && (int)$data['id'] > 0) {
37
+ $model = static::findOne((int)$data['id']);
38
+ }
39
+
40
+ if(!empty($keys)) {
41
+ $first = true;
42
+ foreach($keys as $field => $value) {
43
+ if($first) {
44
+ $model = static::where($field, $value);
45
+ $first = false;
46
+ } else {
47
+ $model = $model->where($field, $value);
48
+ }
49
+ }
50
+ $model = $model->findOne();
51
+ }
52
+
53
+ if($model === false) {
54
+ if(!empty($onCreate)) {
55
+ $data = $onCreate($data);
56
+ }
57
+ $model = static::create();
58
+ $model->hydrate($data);
59
+ } else {
60
+ unset($data['id']);
61
+ $model->set($data);
62
+ }
63
+
64
+ return $model->save();
65
+ }
66
+
67
+ static public function createOrUpdate($data = array()) {
68
+ return self::_createOrUpdate($data);
69
+ }
70
+
71
  function getErrors() {
72
  if(empty($this->_errors)) {
73
  return false;
lib/Models/Newsletter.php CHANGED
@@ -793,15 +793,7 @@ class Newsletter extends Model {
793
  }
794
 
795
  static function createOrUpdate($data = array()) {
796
- $newsletter = false;
797
-
798
- if(isset($data['id']) && (int)$data['id'] > 0) {
799
- $newsletter = self::findOne((int)$data['id']);
800
- }
801
-
802
- if($newsletter === false) {
803
- $newsletter = self::create();
804
-
805
  // set default sender based on settings
806
  if(empty($data['sender'])) {
807
  $sender = Setting::getValue('sender', array());
@@ -832,14 +824,8 @@ class Newsletter extends Model {
832
  );
833
  }
834
 
835
- $newsletter->hydrate($data);
836
- } else {
837
- unset($data['id']);
838
- $newsletter->set($data);
839
- }
840
-
841
- $newsletter->save();
842
- return $newsletter;
843
  }
844
 
845
  static function getWelcomeNotificationsForSegments($segments) {
793
  }
794
 
795
  static function createOrUpdate($data = array()) {
796
+ return parent::_createOrUpdate($data, false, function($data) {
 
 
 
 
 
 
 
 
797
  // set default sender based on settings
798
  if(empty($data['sender'])) {
799
  $sender = Setting::getValue('sender', array());
824
  );
825
  }
826
 
827
+ return $data;
828
+ });
 
 
 
 
 
 
829
  }
830
 
831
  static function getWelcomeNotificationsForSegments($segments) {
lib/Models/NewsletterOption.php CHANGED
@@ -7,18 +7,12 @@ class NewsletterOption extends Model {
7
  public static $_table = MP_NEWSLETTER_OPTION_TABLE;
8
 
9
  static function createOrUpdate($data = array()) {
10
- if(!is_array($data) || empty($data['newsletter_id']) || empty($data['option_field_id'])) return;
11
-
12
- $newsletter_option = self::where('option_field_id', $data['option_field_id'])
13
- ->where('newsletter_id', $data['newsletter_id'])
14
- ->findOne();
15
-
16
- if(empty($newsletter_option)) $newsletter_option = self::create();
17
-
18
- $newsletter_option->newsletter_id = $data['newsletter_id'];
19
- $newsletter_option->option_field_id = $data['option_field_id'];
20
- $newsletter_option->value = $data['value'];
21
- $newsletter_option->save();
22
- return $newsletter_option;
23
  }
24
  }
7
  public static $_table = MP_NEWSLETTER_OPTION_TABLE;
8
 
9
  static function createOrUpdate($data = array()) {
10
+ if(!is_array($data) || empty($data['newsletter_id']) || empty($data['option_field_id'])) {
11
+ return;
12
+ }
13
+ return parent::_createOrUpdate($data, array(
14
+ 'option_field_id' => $data['option_field_id'],
15
+ 'newsletter_id' => $data['newsletter_id']
16
+ ));
 
 
 
 
 
 
17
  }
18
  }
lib/Models/NewsletterTemplate.php CHANGED
@@ -6,6 +6,9 @@ if(!defined('ABSPATH')) exit;
6
  class NewsletterTemplate extends Model {
7
  public static $_table = MP_NEWSLETTER_TEMPLATES_TABLE;
8
 
 
 
 
9
  function __construct() {
10
  parent::__construct();
11
 
@@ -17,6 +20,22 @@ class NewsletterTemplate extends Model {
17
  ));
18
  }
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  function asArray() {
21
  $template = parent::asArray();
22
  if(isset($template['body'])) {
@@ -25,22 +44,4 @@ class NewsletterTemplate extends Model {
25
  return $template;
26
  }
27
 
28
- static function createOrUpdate($data = array()) {
29
- $template = false;
30
-
31
- if(isset($data['id']) && (int)$data['id'] > 0) {
32
- $template = self::findOne((int)$data['id']);
33
- }
34
-
35
- if($template === false) {
36
- $template = self::create();
37
- $template->hydrate($data);
38
- } else {
39
- unset($data['id']);
40
- $template->set($data);
41
- }
42
-
43
- $template->save();
44
- return $template;
45
- }
46
  }
6
  class NewsletterTemplate extends Model {
7
  public static $_table = MP_NEWSLETTER_TEMPLATES_TABLE;
8
 
9
+ const RECENTLY_SENT_CATEGORIES = '["recent"]';
10
+ const RECENTLY_SENT_COUNT = 12;
11
+
12
  function __construct() {
13
  parent::__construct();
14
 
20
  ));
21
  }
22
 
23
+ static function cleanRecentlySent($data) {
24
+ if(!empty($data['categories']) && $data['categories'] === self::RECENTLY_SENT_CATEGORIES) {
25
+ $ids = parent::where('categories', self::RECENTLY_SENT_CATEGORIES)
26
+ ->select('id')
27
+ ->orderByDesc('id')
28
+ ->limit(self::RECENTLY_SENT_COUNT)
29
+ ->findMany();
30
+ $ids = array_map(function ($template) {
31
+ return $template->id;
32
+ }, $ids);
33
+ parent::where('categories', self::RECENTLY_SENT_CATEGORIES)
34
+ ->whereNotIn('id', $ids)
35
+ ->deleteMany();
36
+ }
37
+ }
38
+
39
  function asArray() {
40
  $template = parent::asArray();
41
  if(isset($template['body'])) {
44
  return $template;
45
  }
46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  }
lib/Models/ScheduledTaskSubscriber.php CHANGED
@@ -11,20 +11,14 @@ class ScheduledTaskSubscriber extends Model {
11
  public static $_id_column = array('task_id', 'subscriber_id');
12
 
13
  static function createOrUpdate($data = array()) {
14
- if(!is_array($data) || empty($data['task_id']) || empty($data['subscriber_id'])) return;
15
-
16
- $task_subscriber = self::where('subscriber_id', $data['subscriber_id'])
17
- ->where('task_id', $data['task_id'])
18
- ->findOne();
19
-
20
- if(empty($task_subscriber)) $task_subscriber = self::create();
21
-
22
- $task_subscriber->task_id = $data['task_id'];
23
- $task_subscriber->subscriber_id = $data['subscriber_id'];
24
- $task_subscriber->processed = !empty($data['processed']) ? self::STATUS_PROCESSED : self::STATUS_UNPROCESSED;
25
- $task_subscriber->save();
26
-
27
- return $task_subscriber;
28
  }
29
 
30
  static function addSubscribers($task_id, array $subscriber_ids) {
11
  public static $_id_column = array('task_id', 'subscriber_id');
12
 
13
  static function createOrUpdate($data = array()) {
14
+ if(!is_array($data) || empty($data['task_id']) || empty($data['subscriber_id'])) {
15
+ return;
16
+ }
17
+ $data['processed'] = !empty($data['processed']) ? self::STATUS_PROCESSED : self::STATUS_UNPROCESSED;
18
+ return parent::_createOrUpdate($data, array(
19
+ 'subscriber_id' => $data['subscriber_id'],
20
+ 'task_id' => $data['task_id']
21
+ ));
 
 
 
 
 
 
22
  }
23
 
24
  static function addSubscribers($task_id, array $subscriber_ids) {
lib/Models/Segment.php CHANGED
@@ -219,25 +219,6 @@ class Segment extends Model {
219
  return $query;
220
  }
221
 
222
- static function createOrUpdate($data = array()) {
223
- $segment = false;
224
-
225
- if(isset($data['id']) && (int)$data['id'] > 0) {
226
- $segment = self::findOne((int)$data['id']);
227
- }
228
-
229
- if($segment === false) {
230
- $segment = self::create();
231
- $segment->hydrate($data);
232
- } else {
233
- unset($data['id']);
234
- $segment->set($data);
235
- }
236
-
237
- $segment->save();
238
- return $segment;
239
- }
240
-
241
  static function getPublic() {
242
  return self::getPublished()->where('type', self::TYPE_DEFAULT)->orderByAsc('name');
243
  }
219
  return $query;
220
  }
221
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
  static function getPublic() {
223
  return self::getPublished()->where('type', self::TYPE_DEFAULT)->orderByAsc('name');
224
  }
lib/Models/Setting.php CHANGED
@@ -150,20 +150,8 @@ class Setting extends Model {
150
  }
151
 
152
  public static function createOrUpdate($data = array()) {
153
- $setting = false;
154
-
155
- if(isset($data['name'])) {
156
- $setting = self::where('name', $data['name'])->findOne();
157
- }
158
-
159
- if($setting === false) {
160
- $setting = self::create();
161
- $setting->hydrate($data);
162
- } else {
163
- $setting->value = $data['value'];
164
- }
165
-
166
- return $setting->save();
167
  }
168
 
169
  public static function deleteValue($value) {
150
  }
151
 
152
  public static function createOrUpdate($data = array()) {
153
+ $keys = isset($data['name']) ? array('name' => $data['name']) : false;
154
+ return parent::_createOrUpdate($data, $keys);
 
 
 
 
 
 
 
 
 
 
 
 
155
  }
156
 
157
  public static function deleteValue($value) {
lib/Models/SubscriberCustomField.php CHANGED
@@ -37,18 +37,10 @@ class SubscriberCustomField extends Model {
37
  }
38
  }
39
 
40
- $relation = self::where('custom_field_id', $data['custom_field_id'])
41
- ->where('subscriber_id', $data['subscriber_id'])
42
- ->findOne();
43
-
44
- if($relation === false) {
45
- $relation = self::create();
46
- $relation->hydrate($data);
47
- } else {
48
- $relation->set($data);
49
- }
50
-
51
- return $relation->save();
52
  }
53
 
54
  static function createMultiple($values) {
37
  }
38
  }
39
 
40
+ return parent::_createOrUpdate($data, array(
41
+ 'custom_field_id' => $data['custom_field_id'],
42
+ 'subscriber_id' => $data['subscriber_id']
43
+ ));
 
 
 
 
 
 
 
 
44
  }
45
 
46
  static function createMultiple($values) {
lib/Models/SubscriberSegment.php CHANGED
@@ -151,26 +151,13 @@ class SubscriberSegment extends Model {
151
  }
152
 
153
  static function createOrUpdate($data = array()) {
154
- $subscription = false;
155
-
156
- if(isset($data['id']) && (int)$data['id'] > 0) {
157
- $subscription = self::findOne((int)$data['id']);
158
- }
159
-
160
  if(isset($data['subscriber_id']) && isset($data['segment_id'])) {
161
- $subscription = self::where('subscriber_id', (int)$data['subscriber_id'])
162
- ->where('segment_id', (int)$data['segment_id'])
163
- ->findOne();
164
- }
165
-
166
- if($subscription === false) {
167
- $subscription = self::create();
168
- $subscription->hydrate($data);
169
- } else {
170
- unset($data['id']);
171
- $subscription->set($data);
172
  }
173
-
174
- return $subscription->save();
175
  }
176
  }
151
  }
152
 
153
  static function createOrUpdate($data = array()) {
154
+ $keys = false;
 
 
 
 
 
155
  if(isset($data['subscriber_id']) && isset($data['segment_id'])) {
156
+ $keys = array(
157
+ 'subscriber_id' => (int)$data['subscriber_id'],
158
+ 'segment_id' => (int)$data['segment_id']
159
+ );
 
 
 
 
 
 
 
160
  }
161
+ return parent::_createOrUpdate($data, $keys);
 
162
  }
163
  }
mailpoet.php CHANGED
@@ -4,7 +4,7 @@ if(!defined('ABSPATH')) exit;
4
 
5
  /*
6
  * Plugin Name: MailPoet 3 (New)
7
- * Version: 3.4.1
8
  * Plugin URI: http://www.mailpoet.com
9
  * Description: Create and send newsletters, post notifications and welcome emails from your WordPress.
10
  * Author: MailPoet
@@ -20,7 +20,7 @@ if(!defined('ABSPATH')) exit;
20
  */
21
 
22
  $mailpoet_plugin = array(
23
- 'version' => '3.4.1',
24
  'filename' => __FILE__,
25
  'path' => dirname(__FILE__),
26
  'autoloader' => dirname(__FILE__) . '/vendor/autoload.php',
4
 
5
  /*
6
  * Plugin Name: MailPoet 3 (New)
7
+ * Version: 3.4.2
8
  * Plugin URI: http://www.mailpoet.com
9
  * Description: Create and send newsletters, post notifications and welcome emails from your WordPress.
10
  * Author: MailPoet
20
  */
21
 
22
  $mailpoet_plugin = array(
23
+ 'version' => '3.4.2',
24
  'filename' => __FILE__,
25
  'path' => dirname(__FILE__),
26
  'autoloader' => dirname(__FILE__) . '/vendor/autoload.php',
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: newsletter, email, welcome email, post notification, autoresponder, signup
4
  Requires at least: 4.7
5
  Tested up to: 4.9
6
  Requires PHP: 5.3
7
- Stable tag: 3.4.1
8
  License: GPLv3
9
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
10
 
@@ -116,6 +116,11 @@ Stop by our [support site](https://www.mailpoet.com/support).
116
 
117
  == Changelog ==
118
 
 
 
 
 
 
119
  = 3.4.1 - 2018-02-06 =
120
  * Fixed: previously saved templates are now under "Your saved templates";
121
  * Improved: imported templates with no matching category are now added to "Your saved templates".
4
  Requires at least: 4.7
5
  Tested up to: 4.9
6
  Requires PHP: 5.3
7
+ Stable tag: 3.4.2
8
  License: GPLv3
9
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
10
 
116
 
117
  == Changelog ==
118
 
119
+ = 3.4.2 - 2018-02-13 =
120
+ * Premium: you can now segment your subscribers by opened/clicked/unopened events;
121
+ * Improved: default post search parameters inside newsletter editor can be manually changed using a custom WordPress filter. Thanks Jose Salazar;
122
+ * Fixed: saving email templates when website uses both HTTP and HTTPS protocols.
123
+
124
  = 3.4.1 - 2018-02-06 =
125
  * Fixed: previously saved templates are now under "Your saved templates";
126
  * Improved: imported templates with no matching category are now added to "Your saved templates".
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit1540fc5119aa91bb83bcddb25ab5cc21::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit35eaa820f39f9d0aceb2d2697a7fa90c::getLoader();
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit1540fc5119aa91bb83bcddb25ab5cc21
6
  {
7
  private static $loader;
8
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInit1540fc5119aa91bb83bcddb25ab5cc21
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit1540fc5119aa91bb83bcddb25ab5cc21', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit1540fc5119aa91bb83bcddb25ab5cc21', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
- call_user_func(\Composer\Autoload\ComposerStaticInit1540fc5119aa91bb83bcddb25ab5cc21::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
@@ -48,19 +48,19 @@ class ComposerAutoloaderInit1540fc5119aa91bb83bcddb25ab5cc21
48
  $loader->register(true);
49
 
50
  if ($useStaticLoader) {
51
- $includeFiles = Composer\Autoload\ComposerStaticInit1540fc5119aa91bb83bcddb25ab5cc21::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
- composerRequire1540fc5119aa91bb83bcddb25ab5cc21($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
- function composerRequire1540fc5119aa91bb83bcddb25ab5cc21($fileIdentifier, $file)
64
  {
65
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
  require $file;
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit35eaa820f39f9d0aceb2d2697a7fa90c
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit35eaa820f39f9d0aceb2d2697a7fa90c', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit35eaa820f39f9d0aceb2d2697a7fa90c', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
+ call_user_func(\Composer\Autoload\ComposerStaticInit35eaa820f39f9d0aceb2d2697a7fa90c::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
48
  $loader->register(true);
49
 
50
  if ($useStaticLoader) {
51
+ $includeFiles = Composer\Autoload\ComposerStaticInit35eaa820f39f9d0aceb2d2697a7fa90c::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
+ composerRequire35eaa820f39f9d0aceb2d2697a7fa90c($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
+ function composerRequire35eaa820f39f9d0aceb2d2697a7fa90c($fileIdentifier, $file)
64
  {
65
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
  require $file;
vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInit1540fc5119aa91bb83bcddb25ab5cc21
8
  {
9
  public static $files = array (
10
  '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
@@ -985,10 +985,10 @@ class ComposerStaticInit1540fc5119aa91bb83bcddb25ab5cc21
985
  public static function getInitializer(ClassLoader $loader)
986
  {
987
  return \Closure::bind(function () use ($loader) {
988
- $loader->prefixLengthsPsr4 = ComposerStaticInit1540fc5119aa91bb83bcddb25ab5cc21::$prefixLengthsPsr4;
989
- $loader->prefixDirsPsr4 = ComposerStaticInit1540fc5119aa91bb83bcddb25ab5cc21::$prefixDirsPsr4;
990
- $loader->prefixesPsr0 = ComposerStaticInit1540fc5119aa91bb83bcddb25ab5cc21::$prefixesPsr0;
991
- $loader->classMap = ComposerStaticInit1540fc5119aa91bb83bcddb25ab5cc21::$classMap;
992
 
993
  }, null, ClassLoader::class);
994
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInit35eaa820f39f9d0aceb2d2697a7fa90c
8
  {
9
  public static $files = array (
10
  '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
985
  public static function getInitializer(ClassLoader $loader)
986
  {
987
  return \Closure::bind(function () use ($loader) {
988
+ $loader->prefixLengthsPsr4 = ComposerStaticInit35eaa820f39f9d0aceb2d2697a7fa90c::$prefixLengthsPsr4;
989
+ $loader->prefixDirsPsr4 = ComposerStaticInit35eaa820f39f9d0aceb2d2697a7fa90c::$prefixDirsPsr4;
990
+ $loader->prefixesPsr0 = ComposerStaticInit35eaa820f39f9d0aceb2d2697a7fa90c::$prefixesPsr0;
991
+ $loader->classMap = ComposerStaticInit35eaa820f39f9d0aceb2d2697a7fa90c::$classMap;
992
 
993
  }, null, ClassLoader::class);
994
  }
views/newsletters.html CHANGED
@@ -270,7 +270,9 @@
270
  'savedTemplates': __('Your saved templates'),
271
  'blank': _x('Blank', 'Blank newsletters templates category'),
272
  'sample': _x('Sample', 'Sample newsletters templates category'),
273
- 'noTemplates': __('This category does not contain any template yet!')
 
 
274
  }) %>
275
  <% endblock %>
276
 
270
  'savedTemplates': __('Your saved templates'),
271
  'blank': _x('Blank', 'Blank newsletters templates category'),
272
  'sample': _x('Sample', 'Sample newsletters templates category'),
273
+ 'noTemplates': __('This category does not contain any template yet!'),
274
+
275
+ 'errorWhileTakingScreenshot': __('An error occured while saving the template in "Recently sent"')
276
  }) %>
277
  <% endblock %>
278