MailPoet Newsletters (New) - Version 3.0.0-beta.8

Version Description

  • 2016-12-13 =
  • Added: MailPoet's sending service can now sync hard bounced addresses with the plugin to keep your lists tidy and clean;
  • Improved: gracefully catch vendor library conflicts with other plugins. Thx Vikas;
  • Improved: force browsers to load the intended JS and CSS assets by adding a parameter, ie style.css?ver=x.y.z;
  • Fixed: render non paragraph elements inside a block quote. Thx Remco!;
  • Fixed a query that's gone awry in Mysql version 5.6. Dank je Pim!
Download this release

Release Info

Developer wysija
Plugin Icon 128x128 MailPoet Newsletters (New)
Version 3.0.0-beta.8
Comparing to
See all releases

Code changes from version 3.0.0-beta.7.1 to 3.0.0-beta.8

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: 2016-12-07 10:21:51+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -145,71 +145,71 @@ msgstr ""
145
  msgid "MailPoet Newsletter"
146
  msgstr ""
147
 
148
- #: lib/Config/Menu.php:56 lib/Config/Menu.php:57 views/newsletters.html:23
149
  msgid "Emails"
150
  msgstr ""
151
 
152
- #: lib/Config/Menu.php:76 lib/Config/Menu.php:77 views/forms.html:16
153
  msgid "Forms"
154
  msgstr ""
155
 
156
- #: lib/Config/Menu.php:95 lib/Config/Menu.php:96
157
  #: views/subscribers/subscribers.html:17
158
  msgid "Subscribers"
159
  msgstr ""
160
 
161
- #: lib/Config/Menu.php:114 lib/Config/Menu.php:115 views/forms.html:43
162
  #: views/newsletters.html:63 views/newsletters.html:149 views/segments.html:13
163
  #: views/subscribers/subscribers.html:61
164
  msgid "Lists"
165
  msgstr ""
166
 
167
- #: lib/Config/Menu.php:134 lib/Config/Menu.php:135 views/form/editor.html:37
168
  #: views/newsletters.html:64 views/settings.html:6
169
  msgid "Settings"
170
  msgstr ""
171
 
172
- #: lib/Config/Menu.php:142 lib/Config/Menu.php:143
173
  #: views/subscribers/importExport/import.html:7
174
  #: views/subscribers/subscribers.html:89
175
  msgid "Import"
176
  msgstr ""
177
 
178
- #: lib/Config/Menu.php:151 lib/Config/Menu.php:152
179
  #: views/subscribers/importExport/export.html:6
180
  #: views/subscribers/importExport/export.html:96
181
  #: views/subscribers/subscribers.html:90
182
  msgid "Export"
183
  msgstr ""
184
 
185
- #: lib/Config/Menu.php:160 lib/Config/Menu.php:161 views/update.html:20
186
  #: views/welcome.html:29
187
  msgid "Welcome"
188
  msgstr ""
189
 
190
- #: lib/Config/Menu.php:169 lib/Config/Menu.php:170 views/segments.html:43
191
  msgid "Update"
192
  msgstr ""
193
 
194
- #: lib/Config/Menu.php:178 lib/Config/Menu.php:179
195
  msgid "Form Editor"
196
  msgstr ""
197
 
198
- #: lib/Config/Menu.php:187 lib/Newsletter/Shortcodes/ShortcodesHelper.php:32
199
  #: views/newsletter/templates/components/sidebar/styles.hbs:74
200
  #: views/newsletters.html:105
201
  msgid "Newsletter"
202
  msgstr ""
203
 
204
- #: lib/Config/Menu.php:188
205
  msgid "Newsletter Editor"
206
  msgstr ""
207
 
208
- #: lib/Config/Menu.php:352
209
  msgid "In any WordPress role"
210
  msgstr ""
211
 
212
- #: lib/Config/Menu.php:427
213
  msgid "MailPoet"
214
  msgstr ""
215
 
@@ -927,25 +927,38 @@ msgid ""
927
  "\"%s\" exists and has write permissions. Terminated with error: \"%s\""
928
  msgstr ""
929
 
930
- #: lib/Config/RequirementsChecker.php:37
931
  msgid ""
932
  "This plugin requires PHP version 5.3 or newer. Please read our "
933
  "[link]instructions[/link] on how to resolve this issue."
934
  msgstr ""
935
 
936
- #: lib/Config/RequirementsChecker.php:52
937
  msgid ""
938
  "This plugin requires write permissions inside the /wp-content/uploads "
939
  "folder. Please read our [link]instructions[/link] on how to resolve this "
940
  "issue."
941
  msgstr ""
942
 
943
- #: lib/Config/RequirementsChecker.php:72
944
  msgid ""
945
  "This plugin requires PDO_MYSQL PHP extension. Please read our "
946
  "[link]instructions[/link] on how to resolve this issue."
947
  msgstr ""
948
 
 
 
 
 
 
 
 
 
 
 
 
 
 
949
  #: lib/Config/Shortcodes.php:84
950
  msgid "Oops! There are no newsletters to display."
951
  msgstr ""
@@ -962,11 +975,11 @@ msgstr ""
962
  msgid "Maximum execution time has been reached."
963
  msgstr ""
964
 
965
- #: lib/Cron/Daemon.php:25
966
  msgid "Invalid or missing request data."
967
  msgstr ""
968
 
969
- #: lib/Cron/Daemon.php:28
970
  msgid "Daemon does not exist."
971
  msgstr ""
972
 
@@ -4451,11 +4464,15 @@ msgstr ""
4451
  msgid "List of Changes"
4452
  msgstr ""
4453
 
4454
- #: views/update.html:56 views/welcome.html:76
 
 
 
 
4455
  msgid "Awesome! Now"
4456
  msgstr ""
4457
 
4458
- #: views/update.html:56
4459
  msgid "View all changes"
4460
  msgstr ""
4461
 
@@ -4513,22 +4530,22 @@ msgstr ""
4513
  msgid "Sign up to get: Tips and tricks"
4514
  msgstr ""
4515
 
4516
- #: lib/Config/Menu.php:66
4517
  msgctxt "newsletters per page (screen options)"
4518
  msgid "Number of newsletters per page"
4519
  msgstr ""
4520
 
4521
- #: lib/Config/Menu.php:85
4522
  msgctxt "forms per page (screen options)"
4523
  msgid "Number of forms per page"
4524
  msgstr ""
4525
 
4526
- #: lib/Config/Menu.php:104
4527
  msgctxt "subscribers per page (screen options)"
4528
  msgid "Number of subscribers per page"
4529
  msgstr ""
4530
 
4531
- #: lib/Config/Menu.php:124
4532
  msgctxt "segments per page (screen options)"
4533
  msgid "Number of segments per page"
4534
  msgstr ""
4
  msgstr ""
5
  "Project-Id-Version: \n"
6
  "Report-Msgid-Bugs-To: http://support.mailpoet.com/\n"
7
+ "POT-Creation-Date: 2016-12-13 12:21:25+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
145
  msgid "MailPoet Newsletter"
146
  msgstr ""
147
 
148
+ #: lib/Config/Menu.php:57 lib/Config/Menu.php:58 views/newsletters.html:23
149
  msgid "Emails"
150
  msgstr ""
151
 
152
+ #: lib/Config/Menu.php:77 lib/Config/Menu.php:78 views/forms.html:16
153
  msgid "Forms"
154
  msgstr ""
155
 
156
+ #: lib/Config/Menu.php:96 lib/Config/Menu.php:97
157
  #: views/subscribers/subscribers.html:17
158
  msgid "Subscribers"
159
  msgstr ""
160
 
161
+ #: lib/Config/Menu.php:115 lib/Config/Menu.php:116 views/forms.html:43
162
  #: views/newsletters.html:63 views/newsletters.html:149 views/segments.html:13
163
  #: views/subscribers/subscribers.html:61
164
  msgid "Lists"
165
  msgstr ""
166
 
167
+ #: lib/Config/Menu.php:135 lib/Config/Menu.php:136 views/form/editor.html:37
168
  #: views/newsletters.html:64 views/settings.html:6
169
  msgid "Settings"
170
  msgstr ""
171
 
172
+ #: lib/Config/Menu.php:143 lib/Config/Menu.php:144
173
  #: views/subscribers/importExport/import.html:7
174
  #: views/subscribers/subscribers.html:89
175
  msgid "Import"
176
  msgstr ""
177
 
178
+ #: lib/Config/Menu.php:152 lib/Config/Menu.php:153
179
  #: views/subscribers/importExport/export.html:6
180
  #: views/subscribers/importExport/export.html:96
181
  #: views/subscribers/subscribers.html:90
182
  msgid "Export"
183
  msgstr ""
184
 
185
+ #: lib/Config/Menu.php:161 lib/Config/Menu.php:162 views/update.html:20
186
  #: views/welcome.html:29
187
  msgid "Welcome"
188
  msgstr ""
189
 
190
+ #: lib/Config/Menu.php:170 lib/Config/Menu.php:171 views/segments.html:43
191
  msgid "Update"
192
  msgstr ""
193
 
194
+ #: lib/Config/Menu.php:179 lib/Config/Menu.php:180
195
  msgid "Form Editor"
196
  msgstr ""
197
 
198
+ #: lib/Config/Menu.php:188 lib/Newsletter/Shortcodes/ShortcodesHelper.php:32
199
  #: views/newsletter/templates/components/sidebar/styles.hbs:74
200
  #: views/newsletters.html:105
201
  msgid "Newsletter"
202
  msgstr ""
203
 
204
+ #: lib/Config/Menu.php:189
205
  msgid "Newsletter Editor"
206
  msgstr ""
207
 
208
+ #: lib/Config/Menu.php:361
209
  msgid "In any WordPress role"
210
  msgstr ""
211
 
212
+ #: lib/Config/Menu.php:436
213
  msgid "MailPoet"
214
  msgstr ""
215
 
927
  "\"%s\" exists and has write permissions. Terminated with error: \"%s\""
928
  msgstr ""
929
 
930
+ #: lib/Config/RequirementsChecker.php:62
931
  msgid ""
932
  "This plugin requires PHP version 5.3 or newer. Please read our "
933
  "[link]instructions[/link] on how to resolve this issue."
934
  msgstr ""
935
 
936
+ #: lib/Config/RequirementsChecker.php:77
937
  msgid ""
938
  "This plugin requires write permissions inside the /wp-content/uploads "
939
  "folder. Please read our [link]instructions[/link] on how to resolve this "
940
  "issue."
941
  msgstr ""
942
 
943
+ #: lib/Config/RequirementsChecker.php:97
944
  msgid ""
945
  "This plugin requires PDO_MYSQL PHP extension. Please read our "
946
  "[link]instructions[/link] on how to resolve this issue."
947
  msgstr ""
948
 
949
+ #: lib/Config/RequirementsChecker.php:117
950
+ msgid ""
951
+ "A MailPoet dependency (%s) does not appear to be loaded correctly, thus "
952
+ "MailPoet will not work correctly. Please reinstall the plugin."
953
+ msgstr ""
954
+
955
+ #: lib/Config/RequirementsChecker.php:128
956
+ msgid ""
957
+ "MailPoet has detected a dependency conflict (%s) with another plugin (%s), "
958
+ "which may cause unexpected behavior. Please disable the offending plugin to "
959
+ "fix this issue."
960
+ msgstr ""
961
+
962
  #: lib/Config/Shortcodes.php:84
963
  msgid "Oops! There are no newsletters to display."
964
  msgstr ""
975
  msgid "Maximum execution time has been reached."
976
  msgstr ""
977
 
978
+ #: lib/Cron/Daemon.php:26
979
  msgid "Invalid or missing request data."
980
  msgstr ""
981
 
982
+ #: lib/Cron/Daemon.php:29
983
  msgid "Daemon does not exist."
984
  msgstr ""
985
 
4464
  msgid "List of Changes"
4465
  msgstr ""
4466
 
4467
+ #: views/update.html:37
4468
+ msgid "See readme.txt for a changelog."
4469
+ msgstr ""
4470
+
4471
+ #: views/update.html:45 views/welcome.html:76
4472
  msgid "Awesome! Now"
4473
  msgstr ""
4474
 
4475
+ #: views/update.html:45
4476
  msgid "View all changes"
4477
  msgstr ""
4478
 
4530
  msgid "Sign up to get: Tips and tricks"
4531
  msgstr ""
4532
 
4533
+ #: lib/Config/Menu.php:67
4534
  msgctxt "newsletters per page (screen options)"
4535
  msgid "Number of newsletters per page"
4536
  msgstr ""
4537
 
4538
+ #: lib/Config/Menu.php:86
4539
  msgctxt "forms per page (screen options)"
4540
  msgid "Number of forms per page"
4541
  msgstr ""
4542
 
4543
+ #: lib/Config/Menu.php:105
4544
  msgctxt "subscribers per page (screen options)"
4545
  msgid "Number of subscribers per page"
4546
  msgstr ""
4547
 
4548
+ #: lib/Config/Menu.php:125
4549
  msgctxt "segments per page (screen options)"
4550
  msgid "Number of segments per page"
4551
  msgstr ""
lib/Config/Initializer.php CHANGED
@@ -22,10 +22,11 @@ class Initializer {
22
  }
23
 
24
  function init() {
25
- $requiments_check_results = $this->checkRequirements();
26
 
27
  // abort initialization if PDO extension is missing
28
- if(!$requiments_check_results[RequirementsChecker::TEST_PDO_EXTENSION]) return;
 
29
 
30
  $this->setupDB();
31
 
@@ -51,9 +52,12 @@ class Initializer {
51
  \ORM::configure('password', Env::$db_password);
52
  \ORM::configure('logging', WP_DEBUG);
53
  \ORM::configure('driver_options', array(
54
- \PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
55
  \PDO::MYSQL_ATTR_INIT_COMMAND =>
56
- 'SET TIME_ZONE = "' . Env::$db_timezone_offset. '"'
 
 
 
 
57
  ));
58
 
59
  $settings = Env::$db_prefix . 'settings';
@@ -128,6 +132,7 @@ class Initializer {
128
  $this->setupAPI();
129
  $this->setupRouter();
130
  $this->setupPages();
 
131
  } catch(\Exception $e) {
132
  $this->handleFailedInitialization($e);
133
  }
@@ -223,4 +228,4 @@ class Initializer {
223
  function handleFailedInitialization($message) {
224
  return WPNotice::displayError($message);
225
  }
226
- }
22
  }
23
 
24
  function init() {
25
+ $requirements_check_results = $this->checkRequirements();
26
 
27
  // abort initialization if PDO extension is missing
28
+ if(!$requirements_check_results[RequirementsChecker::TEST_PDO_EXTENSION] ||
29
+ !$requirements_check_results[RequirementsChecker::TEST_VENDOR_SOURCE]) return;
30
 
31
  $this->setupDB();
32
 
52
  \ORM::configure('password', Env::$db_password);
53
  \ORM::configure('logging', WP_DEBUG);
54
  \ORM::configure('driver_options', array(
 
55
  \PDO::MYSQL_ATTR_INIT_COMMAND =>
56
+ 'SET NAMES utf8',
57
+ \PDO::MYSQL_ATTR_INIT_COMMAND =>
58
+ 'SET TIME_ZONE = "' . Env::$db_timezone_offset. '"',
59
+ \PDO::MYSQL_ATTR_INIT_COMMAND =>
60
+ 'SET sql_mode=(SELECT REPLACE(@@sql_mode,"ONLY_FULL_GROUP_BY",""))'
61
  ));
62
 
63
  $settings = Env::$db_prefix . 'settings';
132
  $this->setupAPI();
133
  $this->setupRouter();
134
  $this->setupPages();
135
+ do_action('mailpoet_initialized', MAILPOET_VERSION);
136
  } catch(\Exception $e) {
137
  $this->handleFailedInitialization($e);
138
  }
228
  function handleFailedInitialization($message) {
229
  return WPNotice::displayError($message);
230
  }
231
+ }
lib/Config/Menu.php CHANGED
@@ -17,6 +17,7 @@ use MailPoet\Listing;
17
  use MailPoet\Util\License\Features\Subscribers as SubscribersFeature;
18
  use MailPoet\WP\DateTime;
19
  use MailPoet\WP\Notice as WPNotice;
 
20
 
21
  if(!defined('ABSPATH')) exit;
22
 
@@ -242,6 +243,14 @@ class Menu {
242
  'sub_menu' => 'mailpoet-newsletters'
243
  );
244
 
 
 
 
 
 
 
 
 
245
  $this->displayPage('update.html', $data);
246
  }
247
 
17
  use MailPoet\Util\License\Features\Subscribers as SubscribersFeature;
18
  use MailPoet\WP\DateTime;
19
  use MailPoet\WP\Notice as WPNotice;
20
+ use MailPoet\WP\Readme;
21
 
22
  if(!defined('ABSPATH')) exit;
23
 
243
  'sub_menu' => 'mailpoet-newsletters'
244
  );
245
 
246
+ $readme_file = Env::$path . '/readme.txt';
247
+ if(is_readable($readme_file)) {
248
+ $changelog = Readme::parseChangelog(file_get_contents($readme_file), 2);
249
+ if($changelog) {
250
+ $data['changelog'] = $changelog;
251
+ }
252
+ }
253
+
254
  $this->displayPage('update.html', $data);
255
  }
256
 
lib/Config/Migrator.php CHANGED
@@ -106,6 +106,7 @@ class Migrator {
106
  function sendingQueues() {
107
  $attributes = array(
108
  'id mediumint(9) NOT NULL AUTO_INCREMENT,',
 
109
  'newsletter_id mediumint(9) NOT NULL,',
110
  'newsletter_rendered_body longtext,',
111
  'newsletter_rendered_subject varchar(250) NULL DEFAULT NULL,',
106
  function sendingQueues() {
107
  $attributes = array(
108
  'id mediumint(9) NOT NULL AUTO_INCREMENT,',
109
+ 'type varchar(12) NULL DEFAULT NULL,',
110
  'newsletter_id mediumint(9) NOT NULL,',
111
  'newsletter_rendered_body longtext,',
112
  'newsletter_rendered_subject varchar(250) NULL DEFAULT NULL,',
lib/Config/Renderer.php CHANGED
@@ -55,8 +55,8 @@ class Renderer {
55
 
56
  function setupGlobalVariables() {
57
  $this->renderer->addExtension(new Twig\Assets(array(
58
- 'assets_url' => Env::$assets_url,
59
- 'assets_path' => Env::$assets_path
60
  )));
61
  }
62
 
55
 
56
  function setupGlobalVariables() {
57
  $this->renderer->addExtension(new Twig\Assets(array(
58
+ 'version' => Env::$version,
59
+ 'assets_url' => Env::$assets_url
60
  )));
61
  }
62
 
lib/Config/RequirementsChecker.php CHANGED
@@ -1,6 +1,7 @@
1
  <?php
2
  namespace MailPoet\Config;
3
 
 
4
  use MailPoet\Util\Helpers;
5
  use MailPoet\WP\Notice as WPNotice;
6
 
@@ -11,7 +12,30 @@ class RequirementsChecker {
11
  const TEST_FOLDER_PERMISSIONS = 'TempAndCacheFolderCreation';
12
  const TEST_PDO_EXTENSION = 'PDOExtension';
13
  const TEST_MBSTRING_EXTENSION = 'MbstringExtension';
 
 
14
  public $display_error_notice;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
  function __construct($display_error_notice = true) {
17
  $this->display_error_notice = $display_error_notice;
@@ -22,7 +46,8 @@ class RequirementsChecker {
22
  self::TEST_PDO_EXTENSION,
23
  self::TEST_PHP_VERSION,
24
  self::TEST_FOLDER_PERMISSIONS,
25
- self::TEST_MBSTRING_EXTENSION
 
26
  );
27
  $results = array();
28
  foreach($available_tests as $test) {
@@ -84,10 +109,47 @@ class RequirementsChecker {
84
  return true;
85
  }
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  function processError($error) {
88
  if($this->display_error_notice) {
89
  WPNotice::displayError($error);
90
  }
91
  return false;
92
  }
93
- }
1
  <?php
2
  namespace MailPoet\Config;
3
 
4
+ use MailPoet\Config\Env;
5
  use MailPoet\Util\Helpers;
6
  use MailPoet\WP\Notice as WPNotice;
7
 
12
  const TEST_FOLDER_PERMISSIONS = 'TempAndCacheFolderCreation';
13
  const TEST_PDO_EXTENSION = 'PDOExtension';
14
  const TEST_MBSTRING_EXTENSION = 'MbstringExtension';
15
+ const TEST_VENDOR_SOURCE = 'VendorSource';
16
+
17
  public $display_error_notice;
18
+ public $vendor_classes = array(
19
+ '\ORM',
20
+ '\Model',
21
+ '\Twig_Environment',
22
+ '\Twig_Loader_Filesystem',
23
+ '\Twig_Lexer',
24
+ '\Twig_Extension',
25
+ '\Twig_Extension_GlobalsInterface',
26
+ '\Twig_SimpleFunction',
27
+ '\Swift_Mailer',
28
+ '\Swift_SmtpTransport',
29
+ '\Swift_Message',
30
+ '\Carbon\Carbon',
31
+ '\Sudzy\ValidModel',
32
+ '\Sudzy\ValidationException',
33
+ '\Sudzy\Engine',
34
+ '\pQuery',
35
+ '\Cron\CronExpression',
36
+ '\Html2Text\Html2Text',
37
+ '\csstidy'
38
+ );
39
 
40
  function __construct($display_error_notice = true) {
41
  $this->display_error_notice = $display_error_notice;
46
  self::TEST_PDO_EXTENSION,
47
  self::TEST_PHP_VERSION,
48
  self::TEST_FOLDER_PERMISSIONS,
49
+ self::TEST_MBSTRING_EXTENSION,
50
+ self::TEST_VENDOR_SOURCE
51
  );
52
  $results = array();
53
  foreach($available_tests as $test) {
109
  return true;
110
  }
111
 
112
+ function checkVendorSource() {
113
+ foreach($this->vendor_classes as $dependency) {
114
+ $dependency_path = $this->getDependencyPath($dependency);
115
+ if(!$dependency_path) {
116
+ $error = sprintf(
117
+ __('A MailPoet dependency (%s) does not appear to be loaded correctly, thus MailPoet will not work correctly. Please reinstall the plugin.', 'mailpoet'),
118
+ $dependency
119
+ );
120
+
121
+ return $this->processError($error);
122
+ }
123
+
124
+ $pattern = '#' . preg_quote(Env::$path) . '[\\\/]#';
125
+ $is_loaded_by_plugin = preg_match($pattern, $dependency_path);
126
+ if(!$is_loaded_by_plugin) {
127
+ $error = sprintf(
128
+ __('MailPoet has detected a dependency conflict (%s) with another plugin (%s), which may cause unexpected behavior. Please disable the offending plugin to fix this issue.', 'mailpoet'),
129
+ $dependency,
130
+ $dependency_path
131
+ );
132
+
133
+ return $this->processError($error);
134
+ }
135
+ }
136
+
137
+ return true;
138
+ }
139
+
140
+ private function getDependencyPath($namespaced_class) {
141
+ try {
142
+ $reflector = new \ReflectionClass($namespaced_class);
143
+ return $reflector->getFileName();
144
+ } catch(\ReflectionException $ex) {
145
+ return false;
146
+ }
147
+ }
148
+
149
  function processError($error) {
150
  if($this->display_error_notice) {
151
  WPNotice::displayError($error);
152
  }
153
  return false;
154
  }
155
+ }
lib/Cron/Daemon.php CHANGED
@@ -2,6 +2,7 @@
2
  namespace MailPoet\Cron;
3
  use MailPoet\Cron\Workers\Scheduler as SchedulerWorker;
4
  use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker;
 
5
 
6
  if(!defined('ABSPATH')) exit;
7
  require_once(ABSPATH . 'wp-includes/pluggable.php');
@@ -43,6 +44,7 @@ class Daemon {
43
  try {
44
  $this->executeScheduleWorker();
45
  $this->executeQueueWorker();
 
46
  } catch(\Exception $e) {
47
  // continue processing, no need to handle errors
48
  }
@@ -74,6 +76,11 @@ class Daemon {
74
  return $queue->process();
75
  }
76
 
 
 
 
 
 
77
  function callSelf() {
78
  CronHelper::accessDaemon($this->token, self::REQUEST_TIMEOUT);
79
  return $this->terminateRequest();
2
  namespace MailPoet\Cron;
3
  use MailPoet\Cron\Workers\Scheduler as SchedulerWorker;
4
  use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker;
5
+ use MailPoet\Cron\Workers\Bounce as BounceWorker;
6
 
7
  if(!defined('ABSPATH')) exit;
8
  require_once(ABSPATH . 'wp-includes/pluggable.php');
44
  try {
45
  $this->executeScheduleWorker();
46
  $this->executeQueueWorker();
47
+ $this->executeBounceWorker();
48
  } catch(\Exception $e) {
49
  // continue processing, no need to handle errors
50
  }
76
  return $queue->process();
77
  }
78
 
79
+ function executeBounceWorker() {
80
+ $bounce = new BounceWorker($this->timer);
81
+ return $bounce->process();
82
+ }
83
+
84
  function callSelf() {
85
  CronHelper::accessDaemon($this->token, self::REQUEST_TIMEOUT);
86
  return $this->terminateRequest();
lib/Cron/Triggers/WordPress.php CHANGED
@@ -4,6 +4,7 @@ namespace MailPoet\Cron\Triggers;
4
  use MailPoet\Cron\CronHelper;
5
  use MailPoet\Cron\Workers\Scheduler as SchedulerWorker;
6
  use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker;
 
7
  use MailPoet\Mailer\MailerLog;
8
 
9
  if(!defined('ABSPATH')) exit;
@@ -19,7 +20,11 @@ class WordPress {
19
  $scheduled_queues = SchedulerWorker::getScheduledQueues();
20
  $running_queues = SendingQueueWorker::getRunningQueues();
21
  $sending_limit_reached = MailerLog::isSendingLimitReached();
22
- return (($scheduled_queues || $running_queues) && !$sending_limit_reached);
 
 
 
 
23
  }
24
 
25
  static function cleanup() {
4
  use MailPoet\Cron\CronHelper;
5
  use MailPoet\Cron\Workers\Scheduler as SchedulerWorker;
6
  use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker;
7
+ use MailPoet\Cron\Workers\Bounce as BounceWorker;
8
  use MailPoet\Mailer\MailerLog;
9
 
10
  if(!defined('ABSPATH')) exit;
20
  $scheduled_queues = SchedulerWorker::getScheduledQueues();
21
  $running_queues = SendingQueueWorker::getRunningQueues();
22
  $sending_limit_reached = MailerLog::isSendingLimitReached();
23
+ $bounce_sync_available = BounceWorker::checkBounceSyncAvailable();
24
+ $bounce_due_queues = BounceWorker::getAllDueQueues();
25
+ $bounce_future_queues = BounceWorker::getFutureQueues();
26
+ return (($scheduled_queues || $running_queues) && !$sending_limit_reached)
27
+ || ($bounce_sync_available && ($bounce_due_queues || !$bounce_future_queues));
28
  }
29
 
30
  static function cleanup() {
lib/Cron/Workers/Bounce.php ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace MailPoet\Cron\Workers;
3
+
4
+ use Carbon\Carbon;
5
+ use MailPoet\Cron\CronHelper;
6
+ use MailPoet\Mailer\Mailer;
7
+ use MailPoet\Models\SendingQueue;
8
+ use MailPoet\Models\Subscriber;
9
+ use MailPoet\Util\Helpers;
10
+
11
+ if(!defined('ABSPATH')) exit;
12
+
13
+ class Bounce {
14
+ const BOUNCED_HARD = 'hard';
15
+ const BOUNCED_SOFT = 'soft';
16
+ const NOT_BOUNCED = null;
17
+ const BATCH_SIZE = 100;
18
+
19
+ public $timer;
20
+ public $api;
21
+
22
+ function __construct($timer = false) {
23
+ $this->timer = ($timer) ? $timer : microtime(true);
24
+ // abort if execution limit is reached
25
+ CronHelper::enforceExecutionLimit($this->timer);
26
+ }
27
+
28
+ static function checkBounceSyncAvailable() {
29
+ $mailer_config = Mailer::getMailerConfig();
30
+ return !empty($mailer_config['method'])
31
+ && $mailer_config['method'] === Mailer::METHOD_MAILPOET;
32
+ }
33
+
34
+ function initApi() {
35
+ if(!$this->api) {
36
+ $mailer_config = Mailer::getMailerConfig();
37
+ $this->api = new Bounce\API($mailer_config['mailpoet_api_key']);
38
+ }
39
+ }
40
+
41
+ function process() {
42
+ if(!self::checkBounceSyncAvailable()) {
43
+ return false;
44
+ }
45
+
46
+ $this->initApi();
47
+
48
+ $scheduled_queues = self::getScheduledQueues();
49
+ $running_queues = self::getRunningQueues();
50
+
51
+ if(!$scheduled_queues && !$running_queues) {
52
+ self::scheduleBounceSync();
53
+ return false;
54
+ }
55
+
56
+ foreach($scheduled_queues as $i => $queue) {
57
+ $this->prepareBounceQueue($queue);
58
+ }
59
+ foreach($running_queues as $i => $queue) {
60
+ $this->processBounceQueue($queue);
61
+ }
62
+
63
+ return true;
64
+ }
65
+
66
+ static function scheduleBounceSync() {
67
+ $already_scheduled = SendingQueue::where('type', 'bounce')
68
+ ->whereNull('deleted_at')
69
+ ->where('status', SendingQueue::STATUS_SCHEDULED)
70
+ ->findMany();
71
+ if($already_scheduled) {
72
+ return false;
73
+ }
74
+ $queue = SendingQueue::create();
75
+ $queue->type = 'bounce';
76
+ $queue->status = SendingQueue::STATUS_SCHEDULED;
77
+ $queue->priority = SendingQueue::PRIORITY_LOW;
78
+ $queue->scheduled_at = self::getNextRunDate();
79
+ $queue->newsletter_id = 0;
80
+ $queue->save();
81
+ return $queue;
82
+ }
83
+
84
+ function prepareBounceQueue(SendingQueue $queue) {
85
+ $subscribers = Subscriber::select('id')
86
+ ->whereNull('deleted_at')
87
+ ->whereIn('status', array(
88
+ Subscriber::STATUS_SUBSCRIBED,
89
+ Subscriber::STATUS_UNCONFIRMED
90
+ ))
91
+ ->findArray();
92
+ $subscribers = Helpers::arrayColumn($subscribers, 'id');
93
+
94
+ if(empty($subscribers)) {
95
+ $queue->delete();
96
+ return false;
97
+ }
98
+
99
+ // update current queue
100
+ $queue->subscribers = serialize(
101
+ array(
102
+ 'to_process' => $subscribers
103
+ )
104
+ );
105
+ $queue->count_total = $queue->count_to_process = count($subscribers);
106
+ $queue->status = null;
107
+ $queue->save();
108
+
109
+ // abort if execution limit is reached
110
+ CronHelper::enforceExecutionLimit($this->timer);
111
+
112
+ return true;
113
+ }
114
+
115
+ function processBounceQueue(SendingQueue $queue) {
116
+ $queue->subscribers = $queue->getSubscribers();
117
+ if(empty($queue->subscribers['to_process'])) {
118
+ $queue->delete();
119
+ return false;
120
+ }
121
+
122
+ $subscriber_batches = array_chunk(
123
+ $queue->subscribers['to_process'],
124
+ self::BATCH_SIZE
125
+ );
126
+
127
+ foreach($subscriber_batches as $subscribers_to_process_ids) {
128
+ // abort if execution limit is reached
129
+ CronHelper::enforceExecutionLimit($this->timer);
130
+
131
+ $subscriber_emails = Subscriber::select('email')
132
+ ->whereIn('id', $subscribers_to_process_ids)
133
+ ->whereNull('deleted_at')
134
+ ->findArray();
135
+ $subscriber_emails = Helpers::arrayColumn($subscriber_emails, 'email');
136
+
137
+ $this->processEmails($subscriber_emails);
138
+
139
+ $queue->updateProcessedSubscribers($subscribers_to_process_ids);
140
+ }
141
+
142
+ return true;
143
+ }
144
+
145
+ function processEmails(array $subscriber_emails) {
146
+ $checked_emails = $this->api->check($subscriber_emails);
147
+ $this->processApiResponse((array)$checked_emails);
148
+ }
149
+
150
+ function processApiResponse(array $checked_emails) {
151
+ foreach($checked_emails as $email) {
152
+ if(!isset($email['address'], $email['bounce'])) {
153
+ continue;
154
+ }
155
+ if($email['bounce'] === self::BOUNCED_HARD) {
156
+ $subscriber = Subscriber::findOne($email['address']);
157
+ $subscriber->status = Subscriber::STATUS_BOUNCED;
158
+ $subscriber->save();
159
+ }
160
+ }
161
+ }
162
+
163
+ static function getNextRunDate() {
164
+ $date = Carbon::createFromTimestamp(current_time('timestamp'));
165
+ // Random day of the next week
166
+ $date->setISODate($date->format('o'), $date->format('W') + 1, mt_rand(1, 7));
167
+ $date->startOfDay();
168
+ return $date;
169
+ }
170
+
171
+ static function getScheduledQueues($future = false) {
172
+ $dateWhere = ($future) ? 'whereGt' : 'whereLte';
173
+ return SendingQueue::where('type', 'bounce')
174
+ ->$dateWhere('scheduled_at', Carbon::createFromTimestamp(current_time('timestamp')))
175
+ ->whereNull('deleted_at')
176
+ ->where('status', SendingQueue::STATUS_SCHEDULED)
177
+ ->findMany();
178
+ }
179
+
180
+ static function getRunningQueues() {
181
+ return SendingQueue::where('type', 'bounce')
182
+ ->whereLte('scheduled_at', Carbon::createFromTimestamp(current_time('timestamp')))
183
+ ->whereNull('deleted_at')
184
+ ->whereNull('status')
185
+ ->findMany();
186
+ }
187
+
188
+ static function getAllDueQueues() {
189
+ $scheduled_queues = self::getScheduledQueues();
190
+ $running_queues = self::getRunningQueues();
191
+ return array_merge((array)$scheduled_queues, (array)$running_queues);
192
+ }
193
+
194
+ static function getFutureQueues() {
195
+ return self::getScheduledQueues(true);
196
+ }
197
+ }
lib/Cron/Workers/Bounce/API.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace MailPoet\Cron\Workers\Bounce;
3
+
4
+ if(!defined('ABSPATH')) exit;
5
+
6
+ class API {
7
+ public $url = 'https://bridge.mailpoet.com/api/v0/bounces/search';
8
+ public $api_key;
9
+
10
+ function __construct($api_key) {
11
+ $this->api_key = $api_key;
12
+ }
13
+
14
+ function check(array $emails) {
15
+ $result = wp_remote_post(
16
+ $this->url,
17
+ $this->request($emails)
18
+ );
19
+ if(wp_remote_retrieve_response_code($result) === 201) {
20
+ return json_decode(wp_remote_retrieve_body($result), true);
21
+ }
22
+ return false;
23
+ }
24
+
25
+ private function auth() {
26
+ return 'Basic ' . base64_encode('api:' . $this->api_key);
27
+ }
28
+
29
+ private function request($body) {
30
+ return array(
31
+ 'timeout' => 10,
32
+ 'httpversion' => '1.0',
33
+ 'method' => 'POST',
34
+ 'headers' => array(
35
+ 'Content-Type' => 'application/json',
36
+ 'Authorization' => $this->auth()
37
+ ),
38
+ 'body' => json_encode($body)
39
+ );
40
+ }
41
+ }
lib/Cron/Workers/Bounce/index.php ADDED
File without changes
lib/Cron/Workers/Scheduler.php CHANGED
@@ -187,6 +187,7 @@ class Scheduler {
187
  static function getScheduledQueues() {
188
  return SendingQueue::where('status', 'scheduled')
189
  ->whereLte('scheduled_at', Carbon::createFromTimestamp(current_time('timestamp')))
 
190
  ->findMany();
191
  }
192
  }
187
  static function getScheduledQueues() {
188
  return SendingQueue::where('status', 'scheduled')
189
  ->whereLte('scheduled_at', Carbon::createFromTimestamp(current_time('timestamp')))
190
+ ->whereNull('type')
191
  ->findMany();
192
  }
193
  }
lib/Cron/Workers/SendingQueue/SendingQueue.php CHANGED
@@ -167,6 +167,7 @@ class SendingQueue {
167
  return SendingQueueModel::orderByAsc('priority')
168
  ->whereNull('deleted_at')
169
  ->whereNull('status')
 
170
  ->findMany();
171
  }
172
  }
167
  return SendingQueueModel::orderByAsc('priority')
168
  ->whereNull('deleted_at')
169
  ->whereNull('status')
170
+ ->whereNull('type')
171
  ->findMany();
172
  }
173
  }
lib/Newsletter/Renderer/Blocks/Text.php CHANGED
@@ -27,16 +27,19 @@ class Text {
27
  $DOM_parser = new \pQuery();
28
  $DOM = $DOM_parser->parseStr($html);
29
  $blockquotes = $DOM->query('blockquote');
30
- if(!$blockquotes->count()) return $html;
31
  foreach($blockquotes as $blockquote) {
32
  $contents = array();
33
- $paragraphs = $blockquote->query('p', 0);
34
  foreach($paragraphs as $index => $paragraph) {
35
- $contents[] = $paragraph->html();
36
- if($index + 1 < $paragraphs->count()) $contents[] = '<br />';
37
- $paragraph->remove();
 
 
 
 
38
  }
39
- $paragraph->remove();
40
  $blockquote->setTag('table');
41
  $blockquote->addClass('mailpoet_blockquote');
42
  $blockquote->width = '100%';
@@ -49,7 +52,7 @@ class Text {
49
  <td width="2" bgcolor="#565656"></td>
50
  <td width="10"></td>
51
  <td valign="top">
52
- <table style="border-spacing:0;mso-table-lspace:0;mso-table-rspace:0">
53
  <tr>
54
  <td class="mailpoet_blockquote">
55
  ' . implode('', $contents) . '
27
  $DOM_parser = new \pQuery();
28
  $DOM = $DOM_parser->parseStr($html);
29
  $blockquotes = $DOM->query('blockquote');
 
30
  foreach($blockquotes as $blockquote) {
31
  $contents = array();
32
+ $paragraphs = $blockquote->query('p, h1, h2, h3, h4', 0);
33
  foreach($paragraphs as $index => $paragraph) {
34
+ if(preg_match('/h\d/', $paragraph->getTag())) {
35
+ $contents[] = $paragraph->getOuterText();
36
+ } else {
37
+ $contents[] = $paragraph->html();
38
+ }
39
+ if($index + 1 < $paragraphs->count()) $contents[] = '<br />';
40
+ $paragraph->remove();
41
  }
42
+ if(empty($contents)) continue;
43
  $blockquote->setTag('table');
44
  $blockquote->addClass('mailpoet_blockquote');
45
  $blockquote->width = '100%';
52
  <td width="2" bgcolor="#565656"></td>
53
  <td width="10"></td>
54
  <td valign="top">
55
+ <table width="100%" border="0" cellpadding="0" cellspacing="0" style="border-spacing:0;mso-table-lspace:0;mso-table-rspace:0">
56
  <tr>
57
  <td class="mailpoet_blockquote">
58
  ' . implode('', $contents) . '
lib/Twig/Assets.php CHANGED
@@ -47,8 +47,13 @@ class Assets
47
  $output = array();
48
 
49
  foreach($stylesheets as $stylesheet) {
50
- $output[] = '<link rel="stylesheet" type="text/css"'.
51
- ' href="'.$this->_globals['assets_url'].'/css/'.$stylesheet.'">';
 
 
 
 
 
52
  }
53
 
54
  return join("\n", $output);
@@ -59,15 +64,25 @@ class Assets
59
  $output = array();
60
 
61
  foreach($scripts as $script) {
62
- $output[] = '<script type="text/javascript"'.
63
- ' src="'.$this->_globals['assets_url'].'/js/'.$script.'">'.
64
- '</script>';
 
 
 
 
65
  }
66
 
67
  return join("\n", $output);
68
  }
69
 
70
  public function generateImageUrl($path) {
71
- return $this->_globals['assets_url'].'/img/'.$path;
 
 
 
 
 
 
72
  }
73
- }
47
  $output = array();
48
 
49
  foreach($stylesheets as $stylesheet) {
50
+ $url = $this->appendVersionToUrl(
51
+ $this->_globals['assets_url'] . '/css/' . $stylesheet
52
+ );
53
+ $output[] = sprintf(
54
+ '<link rel="stylesheet" type="text/css" href="%s">',
55
+ $url
56
+ );
57
  }
58
 
59
  return join("\n", $output);
64
  $output = array();
65
 
66
  foreach($scripts as $script) {
67
+ $url = $this->appendVersionToUrl(
68
+ $this->_globals['assets_url'] . '/js/' . $script
69
+ );
70
+ $output[] = sprintf(
71
+ '<script type="text/javascript" src="%s"></script>',
72
+ $url
73
+ );
74
  }
75
 
76
  return join("\n", $output);
77
  }
78
 
79
  public function generateImageUrl($path) {
80
+ return $this->appendVersionToUrl(
81
+ $this->_globals['assets_url'] . '/img/' . $path
82
+ );
83
+ }
84
+
85
+ public function appendVersionToUrl($url) {
86
+ return add_query_arg('mailpoet_version', $this->_globals['version'], $url);
87
  }
88
+ }
lib/Util/CSS.php CHANGED
@@ -1,6 +1,5 @@
1
  <?php
2
  namespace MailPoet\Util;
3
- use \Sunra\PhpSimple\HtmlDomParser;
4
  use csstidy;
5
 
6
  /*
1
  <?php
2
  namespace MailPoet\Util;
 
3
  use csstidy;
4
 
5
  /*
lib/WP/Readme.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace MailPoet\WP;
3
+
4
+ class Readme {
5
+ static function parseChangelog($readme_txt, $limit = null) {
6
+ // Extract changelog section of the readme.txt
7
+ preg_match('/== Changelog ==(.*?)(\n==|$)/is', $readme_txt, $changelog);
8
+
9
+ if(empty($changelog[1])) {
10
+ return false;
11
+ }
12
+
13
+ // Get changelog entries
14
+ $entries = preg_split('/\n(?=\=)/', trim($changelog[1]), -1, PREG_SPLIT_NO_EMPTY);
15
+
16
+ if(empty($entries)) {
17
+ return false;
18
+ }
19
+
20
+ $c = 0;
21
+ $changelog = array();
22
+
23
+ foreach($entries as $entry) {
24
+ // Locate version header and changes list
25
+ preg_match('/=(.*?)=(.*)/s', $entry, $parts);
26
+
27
+ if(empty($parts[1]) || empty($parts[2])) {
28
+ return false;
29
+ }
30
+
31
+ $header = trim($parts[1]);
32
+ $list = trim($parts[2]);
33
+
34
+ // Get individual items from the list
35
+ $list = preg_split('/(^|\n)[\* ]*/', $list, -1, PREG_SPLIT_NO_EMPTY);
36
+
37
+ $changelog[] = array(
38
+ 'version' => $header,
39
+ 'changes' => $list,
40
+ );
41
+
42
+ if(++$c == $limit) {
43
+ break;
44
+ }
45
+ }
46
+
47
+ return $changelog;
48
+ }
49
+ }
mailpoet.php CHANGED
@@ -5,7 +5,7 @@ use MailPoet\Config\Initializer;
5
 
6
  /*
7
  * Plugin Name: MailPoet
8
- * Version: 3.0.0-beta.7.1
9
  * Plugin URI: http://www.mailpoet.com
10
  * Description: Create and send beautiful email newsletters, autoresponders, and post notifications without leaving WordPress. This is a beta version of our brand new plugin!
11
  * Author: MailPoet
@@ -24,7 +24,7 @@ use MailPoet\Config\Initializer;
24
  $mailpoet_loader = dirname(__FILE__) . '/vendor/autoload.php';
25
  if(file_exists($mailpoet_loader)) {
26
  require $mailpoet_loader;
27
- define('MAILPOET_VERSION', '3.0.0-beta.7.1');
28
  $initializer = new Initializer(
29
  array(
30
  'file' => __FILE__,
5
 
6
  /*
7
  * Plugin Name: MailPoet
8
+ * Version: 3.0.0-beta.8
9
  * Plugin URI: http://www.mailpoet.com
10
  * Description: Create and send beautiful email newsletters, autoresponders, and post notifications without leaving WordPress. This is a beta version of our brand new plugin!
11
  * Author: MailPoet
24
  $mailpoet_loader = dirname(__FILE__) . '/vendor/autoload.php';
25
  if(file_exists($mailpoet_loader)) {
26
  require $mailpoet_loader;
27
+ define('MAILPOET_VERSION', '3.0.0-beta.8');
28
  $initializer = new Initializer(
29
  array(
30
  'file' => __FILE__,
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: mailpoet, wysija
3
  Tags: newsletter, email, welcome email, post notification, autoresponder, mailchimp, signup, smtp
4
  Requires at least: 4.6
5
  Tested up to: 4.6.1
6
- Stable tag: 3.0.0-beta.7.1
7
  Create and send beautiful emails and newsletters from WordPress.
8
 
9
  == Description ==
@@ -83,6 +83,13 @@ Our [support site](https://docs.mailpoet.com/) has plenty of articles. You can w
83
 
84
  == Changelog ==
85
 
 
 
 
 
 
 
 
86
  = 3.0.0-beta.7.1 - 2016-12-06 =
87
  * Improved: allow user to restart sending after sending method failure;
88
  * Fixed: subscribers are not added to lists after import;
3
  Tags: newsletter, email, welcome email, post notification, autoresponder, mailchimp, signup, smtp
4
  Requires at least: 4.6
5
  Tested up to: 4.6.1
6
+ Stable tag: 3.0.0-beta.8
7
  Create and send beautiful emails and newsletters from WordPress.
8
 
9
  == Description ==
83
 
84
  == Changelog ==
85
 
86
+ = 3.0.0-beta.8 - 2016-12-13 =
87
+ * Added: MailPoet's sending service can now sync hard bounced addresses with the plugin to keep your lists tidy and clean;
88
+ * Improved: gracefully catch vendor library conflicts with other plugins. Thx Vikas;
89
+ * Improved: force browsers to load the intended JS and CSS assets by adding a parameter, ie style.css?ver=x.y.z;
90
+ * Fixed: render non paragraph elements inside a block quote. Thx Remco!;
91
+ * Fixed a query that's gone awry in Mysql version 5.6. Dank je Pim!
92
+
93
  = 3.0.0-beta.7.1 - 2016-12-06 =
94
  * Improved: allow user to restart sending after sending method failure;
95
  * Fixed: subscribers are not added to lists after import;
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit1c2d6b6090f2eaed05adc5ed9f6f45d8::getLoader();
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInitde03c7532711bbc1a262cf6cc194779e::getLoader();
vendor/composer/autoload_classmap.php CHANGED
@@ -76,6 +76,8 @@ return array(
76
  'MailPoet\\Cron\\Supervisor' => $baseDir . '/lib/Cron/Supervisor.php',
77
  'MailPoet\\Cron\\Triggers\\MailPoet' => $baseDir . '/lib/Cron/Triggers/MailPoet.php',
78
  'MailPoet\\Cron\\Triggers\\WordPress' => $baseDir . '/lib/Cron/Triggers/WordPress.php',
 
 
79
  'MailPoet\\Cron\\Workers\\Scheduler' => $baseDir . '/lib/Cron/Workers/Scheduler.php',
80
  'MailPoet\\Cron\\Workers\\SendingQueue\\SendingQueue' => $baseDir . '/lib/Cron/Workers/SendingQueue/SendingQueue.php',
81
  'MailPoet\\Cron\\Workers\\SendingQueue\\Tasks\\Links' => $baseDir . '/lib/Cron/Workers/SendingQueue/Tasks/Links.php',
@@ -198,6 +200,7 @@ return array(
198
  'MailPoet\\Util\\XLSXWriter_BuffererWriter' => $baseDir . '/lib/Util/XLSXWriter.php',
199
  'MailPoet\\WP\\DateTime' => $baseDir . '/lib/WP/DateTime.php',
200
  'MailPoet\\WP\\Notice' => $baseDir . '/lib/WP/Notice.php',
 
201
  'Model' => $vendorDir . '/j4mie/paris/paris.php',
202
  'ORM' => $vendorDir . '/j4mie/idiorm/idiorm.php',
203
  'ORMWrapper' => $vendorDir . '/j4mie/paris/paris.php',
76
  'MailPoet\\Cron\\Supervisor' => $baseDir . '/lib/Cron/Supervisor.php',
77
  'MailPoet\\Cron\\Triggers\\MailPoet' => $baseDir . '/lib/Cron/Triggers/MailPoet.php',
78
  'MailPoet\\Cron\\Triggers\\WordPress' => $baseDir . '/lib/Cron/Triggers/WordPress.php',
79
+ 'MailPoet\\Cron\\Workers\\Bounce' => $baseDir . '/lib/Cron/Workers/Bounce.php',
80
+ 'MailPoet\\Cron\\Workers\\Bounce\\API' => $baseDir . '/lib/Cron/Workers/Bounce/API.php',
81
  'MailPoet\\Cron\\Workers\\Scheduler' => $baseDir . '/lib/Cron/Workers/Scheduler.php',
82
  'MailPoet\\Cron\\Workers\\SendingQueue\\SendingQueue' => $baseDir . '/lib/Cron/Workers/SendingQueue/SendingQueue.php',
83
  'MailPoet\\Cron\\Workers\\SendingQueue\\Tasks\\Links' => $baseDir . '/lib/Cron/Workers/SendingQueue/Tasks/Links.php',
200
  'MailPoet\\Util\\XLSXWriter_BuffererWriter' => $baseDir . '/lib/Util/XLSXWriter.php',
201
  'MailPoet\\WP\\DateTime' => $baseDir . '/lib/WP/DateTime.php',
202
  'MailPoet\\WP\\Notice' => $baseDir . '/lib/WP/Notice.php',
203
+ 'MailPoet\\WP\\Readme' => $baseDir . '/lib/WP/Readme.php',
204
  'Model' => $vendorDir . '/j4mie/paris/paris.php',
205
  'ORM' => $vendorDir . '/j4mie/idiorm/idiorm.php',
206
  'ORMWrapper' => $vendorDir . '/j4mie/paris/paris.php',
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit1c2d6b6090f2eaed05adc5ed9f6f45d8
6
  {
7
  private static $loader;
8
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInit1c2d6b6090f2eaed05adc5ed9f6f45d8
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit1c2d6b6090f2eaed05adc5ed9f6f45d8', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit1c2d6b6090f2eaed05adc5ed9f6f45d8', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
- call_user_func(\Composer\Autoload\ComposerStaticInit1c2d6b6090f2eaed05adc5ed9f6f45d8::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
@@ -48,19 +48,19 @@ class ComposerAutoloaderInit1c2d6b6090f2eaed05adc5ed9f6f45d8
48
  $loader->register(true);
49
 
50
  if ($useStaticLoader) {
51
- $includeFiles = Composer\Autoload\ComposerStaticInit1c2d6b6090f2eaed05adc5ed9f6f45d8::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
- composerRequire1c2d6b6090f2eaed05adc5ed9f6f45d8($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
- function composerRequire1c2d6b6090f2eaed05adc5ed9f6f45d8($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 ComposerAutoloaderInitde03c7532711bbc1a262cf6cc194779e
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInitde03c7532711bbc1a262cf6cc194779e', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInitde03c7532711bbc1a262cf6cc194779e', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
+ call_user_func(\Composer\Autoload\ComposerStaticInitde03c7532711bbc1a262cf6cc194779e::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\ComposerStaticInitde03c7532711bbc1a262cf6cc194779e::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
+ composerRequirede03c7532711bbc1a262cf6cc194779e($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
+ function composerRequirede03c7532711bbc1a262cf6cc194779e($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 ComposerStaticInit1c2d6b6090f2eaed05adc5ed9f6f45d8
8
  {
9
  public static $files = array (
10
  '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
@@ -147,6 +147,8 @@ class ComposerStaticInit1c2d6b6090f2eaed05adc5ed9f6f45d8
147
  'MailPoet\\Cron\\Supervisor' => __DIR__ . '/../..' . '/lib/Cron/Supervisor.php',
148
  'MailPoet\\Cron\\Triggers\\MailPoet' => __DIR__ . '/../..' . '/lib/Cron/Triggers/MailPoet.php',
149
  'MailPoet\\Cron\\Triggers\\WordPress' => __DIR__ . '/../..' . '/lib/Cron/Triggers/WordPress.php',
 
 
150
  'MailPoet\\Cron\\Workers\\Scheduler' => __DIR__ . '/../..' . '/lib/Cron/Workers/Scheduler.php',
151
  'MailPoet\\Cron\\Workers\\SendingQueue\\SendingQueue' => __DIR__ . '/../..' . '/lib/Cron/Workers/SendingQueue/SendingQueue.php',
152
  'MailPoet\\Cron\\Workers\\SendingQueue\\Tasks\\Links' => __DIR__ . '/../..' . '/lib/Cron/Workers/SendingQueue/Tasks/Links.php',
@@ -269,6 +271,7 @@ class ComposerStaticInit1c2d6b6090f2eaed05adc5ed9f6f45d8
269
  'MailPoet\\Util\\XLSXWriter_BuffererWriter' => __DIR__ . '/../..' . '/lib/Util/XLSXWriter.php',
270
  'MailPoet\\WP\\DateTime' => __DIR__ . '/../..' . '/lib/WP/DateTime.php',
271
  'MailPoet\\WP\\Notice' => __DIR__ . '/../..' . '/lib/WP/Notice.php',
 
272
  'Model' => __DIR__ . '/..' . '/j4mie/paris/paris.php',
273
  'ORM' => __DIR__ . '/..' . '/j4mie/idiorm/idiorm.php',
274
  'ORMWrapper' => __DIR__ . '/..' . '/j4mie/paris/paris.php',
@@ -552,10 +555,10 @@ class ComposerStaticInit1c2d6b6090f2eaed05adc5ed9f6f45d8
552
  public static function getInitializer(ClassLoader $loader)
553
  {
554
  return \Closure::bind(function () use ($loader) {
555
- $loader->prefixLengthsPsr4 = ComposerStaticInit1c2d6b6090f2eaed05adc5ed9f6f45d8::$prefixLengthsPsr4;
556
- $loader->prefixDirsPsr4 = ComposerStaticInit1c2d6b6090f2eaed05adc5ed9f6f45d8::$prefixDirsPsr4;
557
- $loader->prefixesPsr0 = ComposerStaticInit1c2d6b6090f2eaed05adc5ed9f6f45d8::$prefixesPsr0;
558
- $loader->classMap = ComposerStaticInit1c2d6b6090f2eaed05adc5ed9f6f45d8::$classMap;
559
 
560
  }, null, ClassLoader::class);
561
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInitde03c7532711bbc1a262cf6cc194779e
8
  {
9
  public static $files = array (
10
  '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
147
  'MailPoet\\Cron\\Supervisor' => __DIR__ . '/../..' . '/lib/Cron/Supervisor.php',
148
  'MailPoet\\Cron\\Triggers\\MailPoet' => __DIR__ . '/../..' . '/lib/Cron/Triggers/MailPoet.php',
149
  'MailPoet\\Cron\\Triggers\\WordPress' => __DIR__ . '/../..' . '/lib/Cron/Triggers/WordPress.php',
150
+ 'MailPoet\\Cron\\Workers\\Bounce' => __DIR__ . '/../..' . '/lib/Cron/Workers/Bounce.php',
151
+ 'MailPoet\\Cron\\Workers\\Bounce\\API' => __DIR__ . '/../..' . '/lib/Cron/Workers/Bounce/API.php',
152
  'MailPoet\\Cron\\Workers\\Scheduler' => __DIR__ . '/../..' . '/lib/Cron/Workers/Scheduler.php',
153
  'MailPoet\\Cron\\Workers\\SendingQueue\\SendingQueue' => __DIR__ . '/../..' . '/lib/Cron/Workers/SendingQueue/SendingQueue.php',
154
  'MailPoet\\Cron\\Workers\\SendingQueue\\Tasks\\Links' => __DIR__ . '/../..' . '/lib/Cron/Workers/SendingQueue/Tasks/Links.php',
271
  'MailPoet\\Util\\XLSXWriter_BuffererWriter' => __DIR__ . '/../..' . '/lib/Util/XLSXWriter.php',
272
  'MailPoet\\WP\\DateTime' => __DIR__ . '/../..' . '/lib/WP/DateTime.php',
273
  'MailPoet\\WP\\Notice' => __DIR__ . '/../..' . '/lib/WP/Notice.php',
274
+ 'MailPoet\\WP\\Readme' => __DIR__ . '/../..' . '/lib/WP/Readme.php',
275
  'Model' => __DIR__ . '/..' . '/j4mie/paris/paris.php',
276
  'ORM' => __DIR__ . '/..' . '/j4mie/idiorm/idiorm.php',
277
  'ORMWrapper' => __DIR__ . '/..' . '/j4mie/paris/paris.php',
555
  public static function getInitializer(ClassLoader $loader)
556
  {
557
  return \Closure::bind(function () use ($loader) {
558
+ $loader->prefixLengthsPsr4 = ComposerStaticInitde03c7532711bbc1a262cf6cc194779e::$prefixLengthsPsr4;
559
+ $loader->prefixDirsPsr4 = ComposerStaticInitde03c7532711bbc1a262cf6cc194779e::$prefixDirsPsr4;
560
+ $loader->prefixesPsr0 = ComposerStaticInitde03c7532711bbc1a262cf6cc194779e::$prefixesPsr0;
561
+ $loader->classMap = ComposerStaticInitde03c7532711bbc1a262cf6cc194779e::$classMap;
562
 
563
  }, null, ClassLoader::class);
564
  }
views/update.html CHANGED
@@ -23,30 +23,19 @@
23
 
24
  <div id="mailpoet-changelog" clas="feature-section one-col">
25
  <h2><%= __("List of Changes") %></h2>
26
- <h3>3.0.0-beta.7.1 - 2016-12-06</h3>
27
- <ul>
28
- <li>Improved: allow user to restart sending after sending method failure;</li>
29
- <li>Fixed: subscribers are not added to lists after import;</li>
30
- <li>Fixed: sending should stop when newsletter is trashed;</li>
31
- <li>Fixed: update database schema after an update which fixes an SQL error;</li>
32
- <li>Fixed: status of sent newsletters is showing "paused" instead of "sent";</li>
33
- <li>Fixed: dividers in Automatic Latest Posts posts are not displayed. Thx Gregor!;</li>
34
- <li>Fixed: shortcodes (ie, first name) are not rendered when sending a preview;</li>
35
- <li>Fixed: count of confirmed subscribers only in step 2 of import is erroneous.</li>
36
- </ul>
37
- <br>
38
- <h3>3.0.0-beta.6 - 2016-11-29</h3>
39
- <ul>
40
- <li>Added: "bounced" status has been added to subscribers;</li>
41
- <li>Improved: execution time enforced between individual send operations. Avoids duplicate sending on really slow servers;</li>
42
- <li>Improved: Welcome emails are given higher priority for sending;</li>
43
- <li>Fixed: Welcome emails are not scheduled for WP users;</li>
44
- <li>Fixed: Unicode characters in FROM/REPLY-TO/TO fields are not rendered;</li>
45
- <li>Fixed: sending HTML emails with Amazon SES works again. Kudos Alex for reporting;</li>
46
- <li>Fixed: import fails when subscriber already exists in the database but the email is in different case format. Thx Ellen for telling us;</li>
47
- <li>Fixed: ampersand char ("&") inside the subject line won't throw errors in browser preview. Thanks Michel for reporting.</li>
48
- </ul>
49
- <br>
50
  </div>
51
 
52
  <hr>
23
 
24
  <div id="mailpoet-changelog" clas="feature-section one-col">
25
  <h2><%= __("List of Changes") %></h2>
26
+ <% if changelog %>
27
+ <% for item in changelog %>
28
+ <h3><%= item.version %></h3>
29
+ <ul>
30
+ <% for change in item.changes %>
31
+ <li><%= change %></li>
32
+ <% endfor %>
33
+ </ul>
34
+ <br>
35
+ <% endfor %>
36
+ <% else %>
37
+ <p style="text-align: center"><%= __("See readme.txt for a changelog.") %></p>
38
+ <% endif %>
 
 
 
 
 
 
 
 
 
 
 
39
  </div>
40
 
41
  <hr>