Newsletter - Version 6.5.9

Version Description

  • Revisited the posts block
  • Support for the new Reports addon styles
  • Improved the excerpt extraction
  • Cancellation administrative notifications on/off switch
Download this release

Release Info

Developer satollo
Plugin Icon 128x128 Newsletter
Version 6.5.9
Comparing to
See all releases

Code changes from version 6.5.8 to 6.5.9

admin.css CHANGED
@@ -2441,3 +2441,6 @@ span.tnp-email-status-sent {
2441
  color: #3498DB;
2442
  }
2443
 
 
 
 
2441
  color: #3498DB;
2442
  }
2443
 
2444
+ .text-left {
2445
+ text-align: left;
2446
+ }
admin.js CHANGED
@@ -44,3 +44,43 @@ function tnp_toggle_schedule() {
44
  jQuery("#tnp-schedule-button").toggle();
45
  jQuery("#tnp-schedule").toggle();
46
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  jQuery("#tnp-schedule-button").toggle();
45
  jQuery("#tnp-schedule").toggle();
46
  }
47
+
48
+ jQuery(document).ready(function () {
49
+ jQuery('.tnp-counter-animation').each(function () {
50
+ var _this = jQuery(this);
51
+
52
+ var val = null;
53
+ if (!isFloat(_this.text())) {
54
+ val = {
55
+ parsed: parseInt(_this.text()),
56
+ rounded: function (value) {
57
+ return Math.ceil(value);
58
+ }
59
+ };
60
+
61
+ if (_this.hasClass('percentage')) {
62
+ _this.css('min-width', '60px');
63
+ }
64
+ } else {
65
+ val = {
66
+ parsed: parseFloat(_this.text()),
67
+ rounded: function (value) {
68
+ return value.toFixed(1);
69
+ }
70
+ };
71
+ }
72
+
73
+ jQuery({counter: 0}).animate({counter: val.parsed}, {
74
+ duration: 1000,
75
+ easing: 'swing',
76
+ step: function () {
77
+ _this.text(val.rounded(this.counter));
78
+ }
79
+ });
80
+
81
+ function isFloat(value) {
82
+ return !isNaN(Number(value)) && Number(value).toString().indexOf('.') !== -1;
83
+ }
84
+
85
+ });
86
+ });
css/widgets.css CHANGED
@@ -1,11 +1,11 @@
1
- /*
2
  Widgets are blocks used within rows and columns (bootstrap like) and identified by the
3
  class "tnp-widget"
4
  */
5
 
6
  .tnp-widget {
7
  width: 100%;
8
- box-shadow: 0 2px 2px rgba(0,0,0,.1);
9
  background: #fff;
10
  min-height: 320px;
11
  color: #000;
@@ -14,7 +14,7 @@ class "tnp-widget"
14
  }
15
 
16
  .tnp-height-full {
17
- height: 500px!important;
18
  }
19
 
20
  #tnp-body .tnp-widget p {
@@ -27,7 +27,7 @@ class "tnp-widget"
27
  font-family: soleil, sans-serif;
28
  letter-spacing: 0.05rem;
29
  background-color: #2980B9;
30
- color: #fff!important;
31
  margin: 15px 0px;
32
  padding: 9px;
33
  border: 0;
@@ -51,13 +51,13 @@ class "tnp-widget"
51
  }
52
 
53
  .tnp-widget.tnp-inactive {
54
- color: #999!important;
55
- background-color: #ddd!important;
56
  }
57
 
58
  .tnp-widget.tnp-inactive h3 {
59
  background-color: #999;
60
- color: #ccc!important;
61
  }
62
 
63
  /* Widget title button */
@@ -120,7 +120,7 @@ class "tnp-widget"
120
 
121
  .tnp-widget.tnp-number {
122
  text-align: center;
123
- min-height: 0!important;
124
  height: 250px;
125
  }
126
 
@@ -176,11 +176,202 @@ class "tnp-widget"
176
  }
177
 
178
  #tnp-body .tnp-widget.tnp-table table.widefat thead {
179
- background-color: #fff!important;
180
  }
181
 
182
  #tnp-body .tnp-widget.tnp-table table.widefat thead th {
183
  font-weight: bold;
184
- background-color: #fff!important;
185
- color: #000!important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  }
1
+ /*
2
  Widgets are blocks used within rows and columns (bootstrap like) and identified by the
3
  class "tnp-widget"
4
  */
5
 
6
  .tnp-widget {
7
  width: 100%;
8
+ box-shadow: 0 2px 2px rgba(0, 0, 0, .1);
9
  background: #fff;
10
  min-height: 320px;
11
  color: #000;
14
  }
15
 
16
  .tnp-height-full {
17
+ height: 500px !important;
18
  }
19
 
20
  #tnp-body .tnp-widget p {
27
  font-family: soleil, sans-serif;
28
  letter-spacing: 0.05rem;
29
  background-color: #2980B9;
30
+ color: #fff !important;
31
  margin: 15px 0px;
32
  padding: 9px;
33
  border: 0;
51
  }
52
 
53
  .tnp-widget.tnp-inactive {
54
+ color: #999 !important;
55
+ background-color: #ddd !important;
56
  }
57
 
58
  .tnp-widget.tnp-inactive h3 {
59
  background-color: #999;
60
+ color: #ccc !important;
61
  }
62
 
63
  /* Widget title button */
120
 
121
  .tnp-widget.tnp-number {
122
  text-align: center;
123
+ min-height: 0 !important;
124
  height: 250px;
125
  }
126
 
176
  }
177
 
178
  #tnp-body .tnp-widget.tnp-table table.widefat thead {
179
+ background-color: #fff !important;
180
  }
181
 
182
  #tnp-body .tnp-widget.tnp-table table.widefat thead th {
183
  font-weight: bold;
184
+ background-color: #fff !important;
185
+ color: #000 !important;
186
+ }
187
+
188
+ .tnp-cards-container {
189
+ display: flex;
190
+ flex-wrap: wrap;
191
+ flex-direction: row;
192
+ }
193
+
194
+ .tnp-card {
195
+ flex: 1 0;
196
+ align-content: flex-start;
197
+ margin: 15px;
198
+ font-family: soleil, sans-serif;
199
+ border-radius: 15px;
200
+ background-color: #232D3B;
201
+ -webkit-box-shadow: 1px 1px 7px 0px rgba(0, 0, 0, 0.15);
202
+ -moz-box-shadow: 1px 1px 7px 0px rgba(0, 0, 0, 0.15);
203
+ box-shadow: 1px 1px 7px 0px rgba(0, 0, 0, 0.15);
204
+ padding: 15px;
205
+ color: #FFF;
206
+ display: flex;
207
+ flex-wrap: wrap;
208
+ position: relative;
209
+ }
210
+
211
+ .tnp-card.tnp-card-col-2 {
212
+ flex: 0 0 calc(50% - 31px);
213
+ }
214
+
215
+ @media screen and (max-width: 700px) {
216
+ .tnp-card {
217
+ flex: 1 0 100%;
218
+ }
219
+ }
220
+
221
+ @media screen and (min-width: 700px) and (max-width: 1200px) {
222
+ .tnp-card {
223
+ flex: 1 0 40%;
224
+ }
225
+ }
226
+
227
+ .tnp-card .tnp-card-title {
228
+ flex-basis: 100%;
229
+ font-size: 19px;
230
+ margin-bottom: 25px;
231
+ }
232
+
233
+ .tnp-card .tnp-card-value {
234
+ flex-basis: 75%;
235
+ font-size: 39px;
236
+ font-weight: bold;
237
+ }
238
+
239
+ .tnp-counter-animation.percentage {
240
+ display: inline-block;
241
+ min-width: 75px;
242
+ }
243
+
244
+ .tnp-card-button-container {
245
+ flex-basis: 100%;
246
+ margin-top: 60px;
247
+ }
248
+
249
+ .tnp-card-button-container a {
250
+ padding: 5px 18px;
251
+ font-size: 12px;
252
+ color: #FFF !important;
253
+ background-color: #2980B9;
254
+ border-radius: 4px;
255
+ text-decoration: none;
256
+ position: absolute;
257
+ bottom: 15px;
258
+ left: 50%;
259
+ -webkit-transform: translateX(-50%);
260
+ transform: translateX(-50%);
261
+ }
262
+
263
+ .tnp-card-button-container a:hover {
264
+ background-color: #2887c1;
265
+ }
266
+
267
+ .tnp-card-button-container a:hover {
268
+ color: #FFF !important;
269
+ }
270
+
271
+ .tnp-card-icon {
272
+ flex-basis: 25%;
273
+ display: flex;
274
+ justify-content: flex-end;
275
+ }
276
+
277
+ .tnp-card .green {
278
+ color: #81B4A3;
279
+ }
280
+
281
+ .tnp-card .yellow {
282
+ color: #F8CF61;
283
+ }
284
+
285
+ .tnp-card .red {
286
+ color: #F36C7F;
287
+ }
288
+
289
+ .tnp-card .tnp-card-description {
290
+ font-size: 11px;
291
+ line-height: 13px;
292
+ font-weight: 500;
293
+ color: #7f8286;
294
+ margin-top: 20px;
295
+ font-family: -apple-system, system-ui, BlinkMacSystemFont,
296
+ 'Segoe UI', Roboto, 'Helvetica Neue',
297
+ Ubuntu, Arial, sans-serif;
298
+ }
299
+
300
+ .tnp-card .tnp-card-description .value {
301
+ color: #919498;
302
+ font-weight: 700;
303
+ }
304
+
305
+ .tnp-card .tnp-card-chart {
306
+ flex-basis: 100%;
307
+ }
308
+
309
+ .tnp-card .tnp-card-chart .mini-chart {
310
+ max-height: 200px;
311
+ max-width: 200px;
312
+ margin: 0 auto;
313
+ }
314
+
315
+ .tnp-card .tnp-card-chart.h-400 {
316
+ height: 400px;
317
+ }
318
+
319
+ .tnp-card-table,
320
+ .tnp-card-table table {
321
+ width: 100%;
322
+ }
323
+
324
+ .tnp-card-table table {
325
+ border-collapse: collapse;
326
+ }
327
+
328
+ .tnp-card-table table .w-25 {
329
+ width: 25%;
330
+ }
331
+
332
+ .tnp-card-table table .w-50 {
333
+ width: 50%;
334
+ }
335
+
336
+ .tnp-card-table table .w-75 {
337
+ width: 75%;
338
+ }
339
+
340
+ .tnp-card-table table .w-33 {
341
+ width: 33%;
342
+ }
343
+
344
+ .tnp-card-table table .w-20 {
345
+ width: 20%;
346
+ }
347
+
348
+ .tnp-card-table table .w-10 {
349
+ width: 10%;
350
+ }
351
+
352
+ .tnp-card-table table .w-80 {
353
+ width: 80%;
354
+ }
355
+
356
+ .tnp-card-table table tbody::before {
357
+ content: '';
358
+ display: table-row;
359
+ height: 15px;
360
+ }
361
+
362
+ .tnp-card-table table tbody tr {
363
+ line-height: 30px;
364
+ }
365
+
366
+ #tnp-body .tnp-card-table table tbody td,
367
+ .tnp-card-table table tbody td {
368
+ color: #FFF;
369
+ }
370
+
371
+ .tnp-card-table table tbody tr:nth-child(even) {
372
+ background-color: #26303E;
373
+ }
374
+
375
+ .mt-25 {
376
+ margin-top: 25px;
377
  }
emails/blocks/footer/block.php CHANGED
@@ -30,9 +30,9 @@ $options = array_merge($default_options, $options);
30
  }
31
  </style>
32
 
33
- <a inline-class="footer-text" href="{profile_url}"><?php echo $options['profile'] ?></a>
34
 
35
  <span inline-class="footer-text">&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;</span>
36
 
37
- <a inline-class="footer-text" href="{email_url}"><?php echo $options['view'] ?></a>
38
 
30
  }
31
  </style>
32
 
33
+ <a inline-class="footer-text" href="{profile_url}" target="_blank"><?php echo $options['profile'] ?></a>
34
 
35
  <span inline-class="footer-text">&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;</span>
36
 
37
+ <a inline-class="footer-text" href="{email_url}" target="_blank"><?php echo $options['view'] ?></a>
38
 
emails/blocks/html/block.php CHANGED
@@ -10,9 +10,11 @@
10
  /* @var $wpdb wpdb */
11
 
12
  $default_options = array(
13
- 'html'=>'<p>This is a piece of nice html code. You can use any tag, but be aware that email readers do not render everything.<p>',
14
  'block_padding_left' => 15,
15
  'block_padding_right' => 15,
 
 
16
  'block_background' => '#ffffff',
17
  'font_family' => 'Helvetica, Arial, sans-serif',
18
  'font_size' => 16
10
  /* @var $wpdb wpdb */
11
 
12
  $default_options = array(
13
+ 'html'=>'<p style="font-size: 16px; font-family: Helvetica, Arial, sans-serif">This is a piece of nice html code. You can use any tag, but be aware that email readers do not render everything.<p>',
14
  'block_padding_left' => 15,
15
  'block_padding_right' => 15,
16
+ 'block_padding_top' => 20,
17
+ 'block_padding_bottom' => 20,
18
  'block_background' => '#ffffff',
19
  'font_family' => 'Helvetica, Arial, sans-serif',
20
  'font_size' => 16
emails/blocks/posts/block.php CHANGED
@@ -56,9 +56,9 @@ $title_font_size = $options['title_font_size'];
56
 
57
  $show_image = !empty($options['show_image']);
58
 
59
- $filters = array();
60
  $filters['posts_per_page'] = (int) $options['max'];
61
- $filters['offset'] = max( (int) $options['post_offset'], 0 );
62
 
63
  if (!empty($options['categories'])) {
64
  $filters['category__in'] = $options['categories'];
@@ -91,7 +91,7 @@ if ($context['type'] == 'automated' && !empty($context['last_run'])) {
91
  return;
92
  }
93
  }
94
-
95
  // We have something new but we need to reload the posts without filtering by date
96
  if ($options['automated_include'] == 'max') {
97
  unset($filters['date_query']);
@@ -109,10 +109,11 @@ $button_font_family = $options['button_font_family'];
109
  $button_font_size = $options['button_font_size'];
110
  $button_color = $options['button_font_color'];
111
 
112
- $alternative = plugins_url( 'newsletter' ) . '/emails/blocks/posts/images/blank.png';
113
- $alternative_2 = plugins_url( 'newsletter' ) . '/emails/blocks/posts/images/blank-240x160.png';
114
 
115
  remove_all_filters('excerpt_more');
 
116
  ?>
117
 
118
  <?php if (!$posts) { ?>
@@ -121,12 +122,15 @@ remove_all_filters('excerpt_more');
121
  <div inline-class="nocontents"><?php echo $options['automated_no_contents'] ?></div>
122
 
123
 
124
- <?php return; } ?>
 
 
 
125
 
126
  <?php if ($options['layout'] == 'one') { ?>
127
  <style>
128
  .posts-post-date {
129
- padding: 0 0 5px 25px;
130
  font-size: 13px;
131
  font-family: <?php echo $font_family ?>;
132
  font-weight: normal;
@@ -134,7 +138,7 @@ remove_all_filters('excerpt_more');
134
  }
135
 
136
  .posts-post-title {
137
- padding: 0 0 5px 25px;
138
  font-size: <?php echo $title_font_size ?>px;
139
  font-family: <?php echo $title_font_family ?>;
140
  font-weight: normal;
@@ -143,7 +147,7 @@ remove_all_filters('excerpt_more');
143
  }
144
 
145
  .posts-post-excerpt {
146
- padding: 10px 0 15px 25px;
147
  font-family: <?php echo $font_family ?>;
148
  color: <?php echo $options['font_color'] ?>;
149
  font-size: <?php echo $font_size ?>px;
@@ -163,10 +167,10 @@ remove_all_filters('excerpt_more');
163
  font-weight:normal;
164
  letter-spacing:normal;
165
  line-height:normal;
166
- padding-top:15px;
167
- padding-right:30px;
168
- padding-bottom:15px;
169
- padding-left:30px;
170
  text-align: right;
171
  }
172
  .posts-button-a {
@@ -183,74 +187,97 @@ remove_all_filters('excerpt_more');
183
  <table border="0" cellpadding="0" cellspacing="0" width="100%" class="responsive-table">
184
 
185
  <?php foreach ($posts as $post) { ?>
186
- <?php
187
- $url = tnp_post_permalink($post);
188
- ?>
 
 
 
 
 
189
 
190
  <tr>
191
- <?php if ( $show_image ) { ?>
192
- <?php
193
- $size = array( 'width' => 105, 'height' => 105 );
194
- $media = tnp_composer_block_posts_get_media( $post, $size, $alternative );
195
- ?>
196
- <td valign="top" style="padding: 30px 0 0 0; width: <?php echo $size['width'] ?>px!important"
197
- class="mobile-hide">
198
- <a href="<?php echo tnp_post_permalink( $post ) ?>" target="_blank">
199
- <img src="<?php echo $media->url ?>"
200
- width="<?php echo $media->width ?>"
201
- height="<?php echo $media->height ?>"
202
- alt="Image"
203
- border="0"
204
- style="display: block; font-family: Arial;color: #666666; font-size: 14px;min-width: <?php echo $size['width'] ?>px!important;width: <?php echo $size['width'] ?>px!important;">
205
- </a>
206
- </td>
207
- <?php } ?>
208
- <td style="padding: 30px 0 0 0;" class="no-padding">
209
- <!-- ARTICLE -->
210
- <table border="0" cellspacing="0" cellpadding="0" width="100%">
211
- <?php if (!empty($options['show_date'])) { ?>
212
  <tr>
213
- <td align="left" inline-class="posts-post-date" class="padding-meta">
214
- <?php echo tnp_post_date($post) ?>
 
 
 
 
 
 
 
 
215
  </td>
216
  </tr>
217
- <?php } ?>
218
- <tr>
219
- <td align="left"
220
- inline-class="posts-post-title"
221
- class="padding-copy tnpc-row-edit tnpc-inline-editable"
222
- data-type="title" data-id="<?php echo $post->ID ?>">
223
- <?php echo TNP_Composer::is_post_field_edited_inline( $options['inline_edits'], 'title', $post->ID ) ?
224
- TNP_Composer::get_edited_inline_post_field( $options['inline_edits'], 'title', $post->ID ) :
225
- tnp_post_title($post) ?>
226
- </td>
227
- </tr>
228
- <tr>
229
- <td align="left"
230
- inline-class="posts-post-excerpt"
231
- class="padding-copy tnpc-row-edit tnpc-inline-editable"
232
- data-type="text" data-id="<?php echo $post->ID ?>">
233
- <?php echo TNP_Composer::is_post_field_edited_inline( $options['inline_edits'], 'text', $post->ID ) ?
234
- TNP_Composer::get_edited_inline_post_field( $options['inline_edits'], 'text', $post->ID ) :
235
- tnp_post_excerpt( $post, $excerpt_length ) ?>
236
- </td>
237
- </tr>
238
- <tr>
239
- <td align="left" class="padding">
240
- <table border="0" cellpadding="0" cellspacing="0" inline-class="posts-button-table" align="right">
241
- <tr>
242
- <td align="center" valign="middle" inline-class="posts-button-td">
243
- <a href="<?php echo esc_attr($url) ?>" target="_blank" inline-class="posts-button-a"><?php echo $button_label ?></a>
244
- </td>
245
- </tr>
246
- </table>
247
- </td>
248
- </tr>
249
- </table>
250
- </td>
251
- </tr>
252
 
 
 
 
 
 
 
 
 
 
 
 
 
253
  <?php } ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
 
255
  </table>
256
 
@@ -311,7 +338,7 @@ remove_all_filters('excerpt_more');
311
 
312
  <!-- TWO COLUMNS -->
313
  <table cellspacing="0" cellpadding="0" border="0" width="100%">
314
- <?php foreach (array_chunk($posts, 2) AS $row) { ?>
315
  <tr>
316
  <td valign="top" style="padding: 10px;" class="mobile-wrapper two-columns">
317
 
@@ -320,14 +347,14 @@ remove_all_filters('excerpt_more');
320
  <tr>
321
  <td style="padding: 20px 0 40px 0;">
322
  <table cellpadding="0" cellspacing="0" border="0" width="100%">
323
- <?php if ( $show_image ) { ?>
324
- <?php
325
- $size = array( 'width' => 240, 'height' => 160, "crop" => true );
326
- $media = tnp_composer_block_posts_get_media( $row[0], $size, $alternative_2 );
327
- ?>
328
  <tr>
329
  <td align="center" valign="middle" class="tnpc-row-edit" data-type="image">
330
- <a href="<?php echo tnp_post_permalink( $row[0] ) ?>" target="_blank">
331
  <img src="<?php echo $media->url ?>"
332
  width="<?php echo $media->width ?>"
333
  height="<?php echo $media->height ?>"
@@ -337,32 +364,36 @@ remove_all_filters('excerpt_more');
337
  </a>
338
  </td>
339
  </tr>
340
- <?php } ?>
341
  <tr>
342
  <td align="center"
343
  inline-class="posts-post-title"
344
  class="tnpc-row-edit tnpc-inline-editable"
345
  data-type="title" data-id="<?php echo $row[0]->ID ?>">
346
- <?php echo TNP_Composer::is_post_field_edited_inline( $options['inline_edits'], 'title', $row[0]->ID ) ?
347
- TNP_Composer::get_edited_inline_post_field( $options['inline_edits'], 'title', $row[0]->ID ) :
348
- tnp_post_title( $row[0] ) ?>
 
 
349
  </td>
350
  </tr>
351
- <?php if (!empty($options['show_date'])) { ?>
352
- <tr>
353
- <td align="center" inline-class="posts-post-date">
354
- <?php echo tnp_post_date($row[0]) ?>
355
- </td>
356
- </tr>
357
- <?php } ?>
358
  <tr>
359
  <td align="center"
360
  inline-class="posts-post-excerpt"
361
  class="tnpc-row-edit tnpc-inline-editable"
362
  data-type="text" data-id="<?php echo $row[0]->ID ?>">
363
- <?php echo TNP_Composer::is_post_field_edited_inline( $options['inline_edits'], 'text', $row[0]->ID ) ?
364
- TNP_Composer::get_edited_inline_post_field( $options['inline_edits'], 'text', $row[0]->ID ) :
365
- tnp_post_excerpt( $row[0], $excerpt_length ) ?>
 
 
366
  </td>
367
  </tr>
368
  <tr>
@@ -382,17 +413,17 @@ remove_all_filters('excerpt_more');
382
  </tr>
383
  </table>
384
 
385
- <?php if (!empty($row[1])) { ?>
386
  <!-- RIGHT COLUMN -->
387
  <table cellpadding="0" cellspacing="0" border="0" width="47%" align="right" class="responsive-table">
388
  <tr>
389
  <td style="padding: 20px 0 40px 0;">
390
  <table cellpadding="0" cellspacing="0" border="0" width="100%">
391
  <?php if ($show_image) { ?>
392
- <?php
393
- $size = array( 'width' => 240, 'height' => 160, "crop" => true );
394
- $media = tnp_composer_block_posts_get_media( $row[1], $size, $alternative_2 );
395
- ?>
396
  <tr>
397
  <td align="center" valign="middle" class="tnpc-row-edit" data-type="image">
398
  <a href="<?php echo tnp_post_permalink($row[1]) ?>" target="_blank">
@@ -403,56 +434,60 @@ remove_all_filters('excerpt_more');
403
  </a>
404
  </td>
405
  </tr>
406
- <?php } ?>
407
  <tr>
408
  <td align="center"
409
  inline-class="posts-post-title"
410
  class="tnpc-row-edit tnpc-inline-editable"
411
  data-type="title" data-id="<?php echo $row[1]->ID ?>">
412
- <?php echo TNP_Composer::is_post_field_edited_inline( $options['inline_edits'], 'title', $row[1]->ID ) ?
413
- TNP_Composer::get_edited_inline_post_field( $options['inline_edits'], 'title', $row[1]->ID ) :
414
- tnp_post_title( $row[1] ) ?>
 
 
415
  </td>
416
  </tr>
417
- <?php if (!empty($options['show_date'])) { ?>
418
- <tr>
419
- <td align="center" inline-class="posts-post-date">
420
- <?php echo tnp_post_date($row[1]) ?>
421
- </td>
422
- </tr>
423
- <?php } ?>
424
  <tr>
425
  <td align="center"
426
  inline-class="posts-post-excerpt"
427
  class="tnpc-row-edit tnpc-inline-editable"
428
  data-type="text" data-id="<?php echo $row[1]->ID ?>">
429
- <?php echo TNP_Composer::is_post_field_edited_inline( $options['inline_edits'], 'text', $row[1]->ID ) ?
430
- TNP_Composer::get_edited_inline_post_field( $options['inline_edits'], 'text', $row[1]->ID ) :
431
- tnp_post_excerpt( $row[1], $excerpt_length ) ?>
 
 
432
  </td>
433
  </tr>
434
  <tr>
435
- <td align="center">
436
- <br>
437
- <table border="0" cellpadding="0" cellspacing="0" inline-class="posts-button-table" align="center">
438
- <tr>
439
- <td align="center" valign="middle" inline-class="posts-button-td">
440
- <a href="<?php echo tnp_post_permalink($row[1]) ?>" target="_blank" inline-class="posts-button-a"><?php echo $button_label ?></a>
441
- </td>
442
- </tr>
443
- </table>
444
- </td>
445
- </tr>
446
  </table>
447
  </td>
448
  </tr>
449
  </table>
450
- <?php } ?>
451
 
452
  </td>
453
  </tr>
454
 
455
- <?php } ?>
456
 
457
  </table>
458
 
56
 
57
  $show_image = !empty($options['show_image']);
58
 
59
+ $filters = array();
60
  $filters['posts_per_page'] = (int) $options['max'];
61
+ $filters['offset'] = max((int) $options['post_offset'], 0);
62
 
63
  if (!empty($options['categories'])) {
64
  $filters['category__in'] = $options['categories'];
91
  return;
92
  }
93
  }
94
+
95
  // We have something new but we need to reload the posts without filtering by date
96
  if ($options['automated_include'] == 'max') {
97
  unset($filters['date_query']);
109
  $button_font_size = $options['button_font_size'];
110
  $button_color = $options['button_font_color'];
111
 
112
+ $alternative = plugins_url('newsletter') . '/emails/blocks/posts/images/blank.png';
113
+ $alternative_2 = plugins_url('newsletter') . '/emails/blocks/posts/images/blank-240x160.png';
114
 
115
  remove_all_filters('excerpt_more');
116
+
117
  ?>
118
 
119
  <?php if (!$posts) { ?>
122
  <div inline-class="nocontents"><?php echo $options['automated_no_contents'] ?></div>
123
 
124
 
125
+ <?php
126
+ return;
127
+ }
128
+ ?>
129
 
130
  <?php if ($options['layout'] == 'one') { ?>
131
  <style>
132
  .posts-post-date {
133
+ padding: 0 0 5px 0;
134
  font-size: 13px;
135
  font-family: <?php echo $font_family ?>;
136
  font-weight: normal;
138
  }
139
 
140
  .posts-post-title {
141
+ padding: 0 0 5px 0;
142
  font-size: <?php echo $title_font_size ?>px;
143
  font-family: <?php echo $title_font_family ?>;
144
  font-weight: normal;
147
  }
148
 
149
  .posts-post-excerpt {
150
+ padding: 10px 0 15px 0;
151
  font-family: <?php echo $font_family ?>;
152
  color: <?php echo $options['font_color'] ?>;
153
  font-size: <?php echo $font_size ?>px;
167
  font-weight:normal;
168
  letter-spacing:normal;
169
  line-height:normal;
170
+ padding-top:10px;
171
+ padding-right:15px;
172
+ padding-bottom:10px;
173
+ padding-left:15px;
174
  text-align: right;
175
  }
176
  .posts-button-a {
187
  <table border="0" cellpadding="0" cellspacing="0" width="100%" class="responsive-table">
188
 
189
  <?php foreach ($posts as $post) { ?>
190
+ <?php
191
+ $url = tnp_post_permalink($post);
192
+ $media = null;
193
+ if ($show_image) {
194
+ $media = tnp_composer_block_posts_get_media($post, ['width' => 300, 'height' => 0]);
195
+ if ($media) $media->set_width(105);
196
+ }
197
+ ?>
198
 
199
  <tr>
200
+
201
+ <td valign="top" style="padding: 20px 0 0 0;" class="posts-td-1">
202
+
203
+ <?php if ($media) { ?>
204
+ <table width="20%" cellpadding="0" cellspacing="0" border="0" align="left" class="posts-1-column" style="margin-bottom: 20px">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  <tr>
206
+ <td>
207
+ <a href="<?php echo tnp_post_permalink($post) ?>" target="_blank">
208
+ <img src="<?php echo $media->url ?>"
209
+ width="<?php echo $media->width ?>"
210
+ height="<?php echo $media->height ?>"
211
+ alt="<?php echo esc_attr($media->alt) ?>"
212
+ border="0"
213
+ class="posts-1-image"
214
+ style="display: block; max-width: 100%; width: <?php echo $media->width ?>px" width="<?php echo $media->width ?>">
215
+ </a>
216
  </td>
217
  </tr>
218
+ </table>
219
+
220
+
221
+ <?php } ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
 
223
+ <table width="<?php echo $media?'78%':'100%'?>" cellpadding="0" cellspacing="0" border="0" class="posts-1-column" align="right">
224
+ <tr>
225
+ <td>
226
+
227
+ <!-- ARTICLE -->
228
+ <table border="0" cellspacing="0" cellpadding="0" width="100%">
229
+ <?php if (!empty($options['show_date'])) { ?>
230
+ <tr>
231
+ <td align="left" inline-class="posts-post-date">
232
+ <?php echo tnp_post_date($post) ?>
233
+ </td>
234
+ </tr>
235
  <?php } ?>
236
+ <tr>
237
+ <td align="left"
238
+ inline-class="posts-post-title"
239
+ class="tnpc-row-edit tnpc-inline-editable"
240
+ data-type="title" data-id="<?php echo $post->ID ?>">
241
+ <?php
242
+ echo TNP_Composer::is_post_field_edited_inline($options['inline_edits'], 'title', $post->ID) ?
243
+ TNP_Composer::get_edited_inline_post_field($options['inline_edits'], 'title', $post->ID) :
244
+ tnp_post_title($post)
245
+ ?>
246
+ </td>
247
+ </tr>
248
+ <tr>
249
+ <td align="left"
250
+ inline-class="posts-post-excerpt"
251
+ class="padding-copy tnpc-row-edit tnpc-inline-editable"
252
+ data-type="text" data-id="<?php echo $post->ID ?>">
253
+ <?php
254
+ echo TNP_Composer::is_post_field_edited_inline($options['inline_edits'], 'text', $post->ID) ?
255
+ TNP_Composer::get_edited_inline_post_field($options['inline_edits'], 'text', $post->ID) :
256
+ tnp_post_excerpt($post, $excerpt_length)
257
+ ?>
258
+ </td>
259
+ </tr>
260
+ <tr>
261
+ <td align="left" class="padding">
262
+ <table border="0" cellpadding="0" cellspacing="0" inline-class="posts-button-table" align="right">
263
+ <tr>
264
+ <td align="center" valign="middle" inline-class="posts-button-td">
265
+ <a href="<?php echo esc_attr($url) ?>" target="_blank" inline-class="posts-button-a"><?php echo $button_label ?></a>
266
+ </td>
267
+ </tr>
268
+ </table>
269
+ </td>
270
+ </tr>
271
+ </table>
272
+
273
+ </td>
274
+ </tr>
275
+ </table>
276
+
277
+ </td>
278
+ </tr>
279
+
280
+ <?php } ?>
281
 
282
  </table>
283
 
338
 
339
  <!-- TWO COLUMNS -->
340
  <table cellspacing="0" cellpadding="0" border="0" width="100%">
341
+ <?php foreach (array_chunk($posts, 2) AS $row) { ?>
342
  <tr>
343
  <td valign="top" style="padding: 10px;" class="mobile-wrapper two-columns">
344
 
347
  <tr>
348
  <td style="padding: 20px 0 40px 0;">
349
  <table cellpadding="0" cellspacing="0" border="0" width="100%">
350
+ <?php if ($show_image) { ?>
351
+ <?php
352
+ $size = array('width' => 240, 'height' => 160, "crop" => true);
353
+ $media = tnp_composer_block_posts_get_media($row[0], $size, $alternative_2);
354
+ ?>
355
  <tr>
356
  <td align="center" valign="middle" class="tnpc-row-edit" data-type="image">
357
+ <a href="<?php echo tnp_post_permalink($row[0]) ?>" target="_blank">
358
  <img src="<?php echo $media->url ?>"
359
  width="<?php echo $media->width ?>"
360
  height="<?php echo $media->height ?>"
364
  </a>
365
  </td>
366
  </tr>
367
+ <?php } ?>
368
  <tr>
369
  <td align="center"
370
  inline-class="posts-post-title"
371
  class="tnpc-row-edit tnpc-inline-editable"
372
  data-type="title" data-id="<?php echo $row[0]->ID ?>">
373
+ <?php
374
+ echo TNP_Composer::is_post_field_edited_inline($options['inline_edits'], 'title', $row[0]->ID) ?
375
+ TNP_Composer::get_edited_inline_post_field($options['inline_edits'], 'title', $row[0]->ID) :
376
+ tnp_post_title($row[0])
377
+ ?>
378
  </td>
379
  </tr>
380
+ <?php if (!empty($options['show_date'])) { ?>
381
+ <tr>
382
+ <td align="center" inline-class="posts-post-date">
383
+ <?php echo tnp_post_date($row[0]) ?>
384
+ </td>
385
+ </tr>
386
+ <?php } ?>
387
  <tr>
388
  <td align="center"
389
  inline-class="posts-post-excerpt"
390
  class="tnpc-row-edit tnpc-inline-editable"
391
  data-type="text" data-id="<?php echo $row[0]->ID ?>">
392
+ <?php
393
+ echo TNP_Composer::is_post_field_edited_inline($options['inline_edits'], 'text', $row[0]->ID) ?
394
+ TNP_Composer::get_edited_inline_post_field($options['inline_edits'], 'text', $row[0]->ID) :
395
+ tnp_post_excerpt($row[0], $excerpt_length)
396
+ ?>
397
  </td>
398
  </tr>
399
  <tr>
413
  </tr>
414
  </table>
415
 
416
+ <?php if (!empty($row[1])) { ?>
417
  <!-- RIGHT COLUMN -->
418
  <table cellpadding="0" cellspacing="0" border="0" width="47%" align="right" class="responsive-table">
419
  <tr>
420
  <td style="padding: 20px 0 40px 0;">
421
  <table cellpadding="0" cellspacing="0" border="0" width="100%">
422
  <?php if ($show_image) { ?>
423
+ <?php
424
+ $size = array('width' => 240, 'height' => 160, "crop" => true);
425
+ $media = tnp_composer_block_posts_get_media($row[1], $size, $alternative_2);
426
+ ?>
427
  <tr>
428
  <td align="center" valign="middle" class="tnpc-row-edit" data-type="image">
429
  <a href="<?php echo tnp_post_permalink($row[1]) ?>" target="_blank">
434
  </a>
435
  </td>
436
  </tr>
437
+ <?php } ?>
438
  <tr>
439
  <td align="center"
440
  inline-class="posts-post-title"
441
  class="tnpc-row-edit tnpc-inline-editable"
442
  data-type="title" data-id="<?php echo $row[1]->ID ?>">
443
+ <?php
444
+ echo TNP_Composer::is_post_field_edited_inline($options['inline_edits'], 'title', $row[1]->ID) ?
445
+ TNP_Composer::get_edited_inline_post_field($options['inline_edits'], 'title', $row[1]->ID) :
446
+ tnp_post_title($row[1])
447
+ ?>
448
  </td>
449
  </tr>
450
+ <?php if (!empty($options['show_date'])) { ?>
451
+ <tr>
452
+ <td align="center" inline-class="posts-post-date">
453
+ <?php echo tnp_post_date($row[1]) ?>
454
+ </td>
455
+ </tr>
456
+ <?php } ?>
457
  <tr>
458
  <td align="center"
459
  inline-class="posts-post-excerpt"
460
  class="tnpc-row-edit tnpc-inline-editable"
461
  data-type="text" data-id="<?php echo $row[1]->ID ?>">
462
+ <?php
463
+ echo TNP_Composer::is_post_field_edited_inline($options['inline_edits'], 'text', $row[1]->ID) ?
464
+ TNP_Composer::get_edited_inline_post_field($options['inline_edits'], 'text', $row[1]->ID) :
465
+ tnp_post_excerpt($row[1], $excerpt_length)
466
+ ?>
467
  </td>
468
  </tr>
469
  <tr>
470
+ <td align="center">
471
+ <br>
472
+ <table border="0" cellpadding="0" cellspacing="0" inline-class="posts-button-table" align="center">
473
+ <tr>
474
+ <td align="center" valign="middle" inline-class="posts-button-td">
475
+ <a href="<?php echo tnp_post_permalink($row[1]) ?>" target="_blank" inline-class="posts-button-a"><?php echo $button_label ?></a>
476
+ </td>
477
+ </tr>
478
+ </table>
479
+ </td>
480
+ </tr>
481
  </table>
482
  </td>
483
  </tr>
484
  </table>
485
+ <?php } ?>
486
 
487
  </td>
488
  </tr>
489
 
490
+ <?php } ?>
491
 
492
  </table>
493
 
emails/blocks/posts/style.css ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ @media (max-width: 480px) {
2
+ .posts-1-column {
3
+ width: 100%!important;
4
+ }
5
+ .posts-1-image {
6
+ width: 100%!important;
7
+ display: block;
8
+ }
9
+ }
10
+
emails/blocks/text/block.php CHANGED
@@ -15,6 +15,8 @@ $default_options = array(
15
  'font_color'=>'#000000',
16
  'block_padding_left'=>15,
17
  'block_padding_right'=>15,
 
 
18
  'block_background'=>'#ffffff'
19
  );
20
 
15
  'font_color'=>'#000000',
16
  'block_padding_left'=>15,
17
  'block_padding_right'=>15,
18
+ 'block_padding_top' => 20,
19
+ 'block_padding_bottom' => 20,
20
  'block_background'=>'#ffffff'
21
  );
22
 
emails/emails.php CHANGED
@@ -934,11 +934,19 @@ class NewsletterEmails extends NewsletterModule {
934
  return $css;
935
  }
936
 
 
 
 
 
 
 
937
  function send_test_email($email, $controls) {
938
  if (!$email) {
939
  $controls->errors = __('Newsletter should be saved before send a test', 'newsletter');
940
  return;
941
  }
 
 
942
  if ($email->subject == '') {
943
  $email->subject = '[TEST] Dummy subject, it was empty (remember to set it)';
944
  } else {
@@ -972,6 +980,7 @@ class NewsletterEmails extends NewsletterModule {
972
  $controls->messages .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
973
  }
974
  }
 
975
  }
976
 
977
  function restore_options_from_request() {
934
  return $css;
935
  }
936
 
937
+ /**
938
+ * Send an email to the test subscribers.
939
+ *
940
+ * @param TNP_Email $email Could be any object with the TNP_Email attributes
941
+ * @param NewsletterControls $controls
942
+ */
943
  function send_test_email($email, $controls) {
944
  if (!$email) {
945
  $controls->errors = __('Newsletter should be saved before send a test', 'newsletter');
946
  return;
947
  }
948
+ $original_subject = $email->subject;
949
+
950
  if ($email->subject == '') {
951
  $email->subject = '[TEST] Dummy subject, it was empty (remember to set it)';
952
  } else {
980
  $controls->messages .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
981
  }
982
  }
983
+ $email->subject = $original_subject;
984
  }
985
 
986
  function restore_options_from_request() {
emails/themes/default/theme.php CHANGED
@@ -44,6 +44,7 @@ if (isset($theme_options['theme_posts'])) {
44
  $filters['post_type'] = $theme_options['theme_post_types'];
45
  }
46
 
 
47
  $posts = Newsletter::instance()->get_posts($filters, $theme_options['theme_language']);
48
  }
49
 
44
  $filters['post_type'] = $theme_options['theme_post_types'];
45
  }
46
 
47
+ if (!isset($theme_options['theme_language'])) $theme_options['theme_language'] = '';
48
  $posts = Newsletter::instance()->get_posts($filters, $theme_options['theme_language']);
49
  }
50
 
includes/TNP.php CHANGED
@@ -2,12 +2,12 @@
2
 
3
  /*
4
  * TNP classes for internal API
5
- *
6
  * Error reference
7
  * 404 Object not found
8
  * 403 Not allowed (when the API key is missing or wrong)
9
  * 400 Bad request, when the parameters are not correct or required parameters are missing
10
- *
11
  */
12
 
13
  /**
@@ -21,7 +21,7 @@ class TNP {
21
  */
22
 
23
  public static function subscribe($params) {
24
-
25
  $logger = new NewsletterLogger('phpapi');
26
  $logger->debug($params);
27
 
@@ -125,20 +125,20 @@ class TNP {
125
  }
126
 
127
  apply_filters('newsletter_api_subscribe', $params);
128
-
129
  $full_name = '';
130
  if (isset($params['name'])) {
131
  $params['name'] = $newsletter->normalize_name($params['name']);
132
  $full_name .= $params['name'];
133
  }
134
-
135
  if (isset($params['surname'])) {
136
  $params['surname'] = $newsletter->normalize_name($params['surname']);
137
  $full_name .= ' ' . $params['surname'];
138
  }
139
-
140
  $ip = $newsletter->get_remote_ip();
141
-
142
  NewsletterSubscription::instance()->valid_subscription_or_die($email, $full_name, $ip);
143
 
144
  $user = TNP::add_subscriber($params);
@@ -150,7 +150,7 @@ class TNP {
150
  // Notification to admin (only for new confirmed subscriptions)
151
  if ($user->status == 'C') {
152
  do_action('newsletter_user_confirmed', $user);
153
- $subscription->notify_admin($user, 'Newsletter subscription');
154
  setcookie('newsletter', $user->id . '-' . $user->token, time() + 60 * 60 * 24 * 365, '/');
155
  }
156
 
@@ -189,8 +189,8 @@ class TNP {
189
 
190
  NewsletterUnsubscription::instance()->send_unsubscribed_email($user);
191
 
192
- NewsletterSubscription::instance()->notify_admin($user, 'Newsletter unsubscription');
193
-
194
  do_action('newsletter_unsubscribed', $user);
195
 
196
  return;
@@ -251,7 +251,7 @@ class TNP {
251
  } else {
252
  $user['status'] = 'C';
253
  }
254
-
255
  if (!empty($params['language'])) {
256
  $user['language'] = $params['language'];
257
  }
2
 
3
  /*
4
  * TNP classes for internal API
5
+ *
6
  * Error reference
7
  * 404 Object not found
8
  * 403 Not allowed (when the API key is missing or wrong)
9
  * 400 Bad request, when the parameters are not correct or required parameters are missing
10
+ *
11
  */
12
 
13
  /**
21
  */
22
 
23
  public static function subscribe($params) {
24
+
25
  $logger = new NewsletterLogger('phpapi');
26
  $logger->debug($params);
27
 
125
  }
126
 
127
  apply_filters('newsletter_api_subscribe', $params);
128
+
129
  $full_name = '';
130
  if (isset($params['name'])) {
131
  $params['name'] = $newsletter->normalize_name($params['name']);
132
  $full_name .= $params['name'];
133
  }
134
+
135
  if (isset($params['surname'])) {
136
  $params['surname'] = $newsletter->normalize_name($params['surname']);
137
  $full_name .= ' ' . $params['surname'];
138
  }
139
+
140
  $ip = $newsletter->get_remote_ip();
141
+
142
  NewsletterSubscription::instance()->valid_subscription_or_die($email, $full_name, $ip);
143
 
144
  $user = TNP::add_subscriber($params);
150
  // Notification to admin (only for new confirmed subscriptions)
151
  if ($user->status == 'C') {
152
  do_action('newsletter_user_confirmed', $user);
153
+ $subscription->notify_admin_on_subscription($user);
154
  setcookie('newsletter', $user->id . '-' . $user->token, time() + 60 * 60 * 24 * 365, '/');
155
  }
156
 
189
 
190
  NewsletterUnsubscription::instance()->send_unsubscribed_email($user);
191
 
192
+ NewsletterUnsubscription::instance()->notify_admin_on_unsubscription($user);
193
+
194
  do_action('newsletter_unsubscribed', $user);
195
 
196
  return;
251
  } else {
252
  $user['status'] = 'C';
253
  }
254
+
255
  if (!empty($params['language'])) {
256
  $user['language'] = $params['language'];
257
  }
includes/composer.php CHANGED
@@ -242,6 +242,7 @@ class TNP_Composer {
242
  * @return bool
243
  */
244
  static function is_post_field_edited_inline($inline_edit_list, $field_type, $post_id) {
 
245
  foreach ($inline_edit_list as $edit) {
246
  if ($edit['type'] == $field_type && $edit['post_id'] == $post_id) {
247
  return true;
242
  * @return bool
243
  */
244
  static function is_post_field_edited_inline($inline_edit_list, $field_type, $post_id) {
245
+ if (empty($inline_edit_list)) return false;
246
  foreach ($inline_edit_list as $edit) {
247
  if ($edit['type'] == $field_type && $edit['post_id'] == $post_id) {
248
  return true;
includes/helper.php CHANGED
@@ -42,13 +42,15 @@ function tnp_post_thumbnail_src($post, $size = 'thumbnail', $alternative = '') {
42
  return $media[0];
43
  }
44
 
 
 
 
 
 
 
45
  function tnp_post_excerpt($post, $length = 30) {
46
- if (empty($post->post_excerpt)) {
47
- $excerpt = tnp_delete_all_shordcodes_tags(wp_strip_all_tags($post->post_content));
48
- $excerpt = wp_trim_words($excerpt, $length);
49
- } else {
50
- $excerpt = wp_trim_words($post->post_excerpt, $length);
51
- }
52
 
53
  return $excerpt;
54
  }
@@ -82,12 +84,12 @@ function tnp_post_date($post, $format = null) {
82
  }
83
 
84
  /**
85
- * Tries to create a resized version of a media uploaded to the media library.
86
  * Returns an empty string if the media does not exists or generally if the attached file
87
  * cannot be found. If the resize fails for whatever reason, fall backs to the
88
- * standard image source returned by WP which is usually not exactly the
89
  * requested size.
90
- *
91
  * @param int $media_id
92
  * @param array $size
93
  * @return string
@@ -172,7 +174,7 @@ function _tnp_get_default_media($media_id, $size) {
172
 
173
  /**
174
  * Create a resized version of the media stored in the WP media library.
175
- *
176
  * @param int $media_id
177
  * @param array $size
178
  * @return TNP_Media
@@ -264,19 +266,20 @@ function tnp_resize($media_id, $size) {
264
  *
265
  * @return TNP_Media
266
  */
267
- function tnp_composer_block_posts_get_media($post, $size, $default_image_url) {
268
  $post_thumbnail_id = TNP_Composer::get_post_thumbnail_id($post);
269
 
 
 
270
  if (!empty($post_thumbnail_id)) {
271
  $media = tnp_resize($post_thumbnail_id, array_values($size));
272
- } else {
273
  Newsletter::instance()->logger->error('Thumbnail id not found');
274
  $media = new TNP_Media();
275
  $media->url = $default_image_url;
276
  $media->width = $size['width'];
277
  $media->height = $size['height'];
278
  }
279
-
280
  return $media;
281
  }
282
 
42
  return $media[0];
43
  }
44
 
45
+ /**
46
+ * @param WP_Post $post
47
+ * @param int $length
48
+ *
49
+ * @return string
50
+ */
51
  function tnp_post_excerpt($post, $length = 30) {
52
+ $excerpt = tnp_delete_all_shordcodes_tags(get_the_excerpt($post->ID));
53
+ $excerpt = wp_trim_words($excerpt, $length);
 
 
 
 
54
 
55
  return $excerpt;
56
  }
84
  }
85
 
86
  /**
87
+ * Tries to create a resized version of a media uploaded to the media library.
88
  * Returns an empty string if the media does not exists or generally if the attached file
89
  * cannot be found. If the resize fails for whatever reason, fall backs to the
90
+ * standard image source returned by WP which is usually not exactly the
91
  * requested size.
92
+ *
93
  * @param int $media_id
94
  * @param array $size
95
  * @return string
174
 
175
  /**
176
  * Create a resized version of the media stored in the WP media library.
177
+ *
178
  * @param int $media_id
179
  * @param array $size
180
  * @return TNP_Media
266
  *
267
  * @return TNP_Media
268
  */
269
+ function tnp_composer_block_posts_get_media($post, $size, $default_image_url = null) {
270
  $post_thumbnail_id = TNP_Composer::get_post_thumbnail_id($post);
271
 
272
+ $media = null;
273
+
274
  if (!empty($post_thumbnail_id)) {
275
  $media = tnp_resize($post_thumbnail_id, array_values($size));
276
+ } else if ($default_image_url) {
277
  Newsletter::instance()->logger->error('Thumbnail id not found');
278
  $media = new TNP_Media();
279
  $media->url = $default_image_url;
280
  $media->width = $size['width'];
281
  $media->height = $size['height'];
282
  }
 
283
  return $media;
284
  }
285
 
includes/module.php CHANGED
@@ -80,7 +80,7 @@ abstract class TNP_User {
80
  * @property array $options The subscriber status
81
  * */
82
  abstract class TNP_Email {
83
-
84
  }
85
 
86
  class NewsletterModule {
@@ -161,7 +161,7 @@ class NewsletterModule {
161
  }
162
 
163
  /**
164
- *
165
  * @global wpdb $wpdb
166
  * @param string $query
167
  */
@@ -188,7 +188,7 @@ class NewsletterModule {
188
  }
189
 
190
  /**
191
- *
192
  * @global wpdb $wpdb
193
  * @param string $table
194
  * @param array $data
@@ -611,7 +611,7 @@ class NewsletterModule {
611
  }
612
 
613
  function admin_menu() {
614
-
615
  }
616
 
617
  function add_menu_page($page, $title, $capability = '') {
@@ -678,9 +678,10 @@ class NewsletterModule {
678
 
679
  /**
680
  * Retrieves an email from DB and unserialize the options.
681
- *
682
  * @param mixed $id
683
  * @param string $format
 
684
  */
685
  function get_email($id, $format = OBJECT) {
686
  $email = $this->store->get_single(NEWSLETTER_EMAILS_TABLE, $id, $format);
@@ -708,7 +709,7 @@ class NewsletterModule {
708
  }
709
 
710
  /**
711
- * Save an email and provide serialization, if needed, of $email['options'].
712
  * @return TNP_Email
713
  */
714
  function save_email($email, $return_format = OBJECT) {
@@ -755,7 +756,7 @@ class NewsletterModule {
755
  }
756
 
757
  /**
758
- *
759
  * @global wpdb $wpdb
760
  * @param int|array $id
761
  * @return boolean
@@ -963,7 +964,7 @@ class NewsletterModule {
963
 
964
  /**
965
  * Accepts a user ID or a TNP_User object. Does not check if the user really exists.
966
- *
967
  * @param type $user
968
  */
969
  function get_user_edit_url($user) {
@@ -999,9 +1000,9 @@ class NewsletterModule {
999
 
1000
  /**
1001
  * Return the user identified by the "nk" parameter (POST or GET).
1002
- * If no user can be found or the token is not matching, returns null.
1003
  * If die_on_fail is true it dies instead of return null.
1004
- *
1005
  * @param bool $die_on_fail
1006
  * @return TNP_User
1007
  */
@@ -1094,7 +1095,7 @@ class NewsletterModule {
1094
  }
1095
 
1096
  /**
1097
- *
1098
  * @return TNP_List[]
1099
  */
1100
  function get_lists_public($language = '') {
@@ -1116,7 +1117,7 @@ class NewsletterModule {
1116
 
1117
  /**
1118
  * Lists to be shown on subscription form.
1119
- *
1120
  * @return TNP_List[]
1121
  */
1122
  function get_lists_for_subscription($language = '') {
@@ -1138,7 +1139,7 @@ class NewsletterModule {
1138
 
1139
  /**
1140
  * Returns the lists to be shown in the profile page.
1141
- *
1142
  * @return TNP_List[]
1143
  */
1144
  function get_lists_for_profile($language = '') {
@@ -1160,7 +1161,7 @@ class NewsletterModule {
1160
 
1161
  /**
1162
  * Returns a list as an object (with the same signature of TNP_List)
1163
- *
1164
  * @param int $id
1165
  * @return TNP_List
1166
  */
@@ -1207,7 +1208,7 @@ class NewsletterModule {
1207
 
1208
  /**
1209
  * Updates the user last activity timestamp.
1210
- *
1211
  * @global wpdb $wpdb
1212
  * @param TNP_User $user
1213
  */
@@ -1225,7 +1226,7 @@ class NewsletterModule {
1225
  /**
1226
  * Finds single style blocks and adds a style attribute to every HTML tag with a class exactly matching the rules in the style
1227
  * block. HTML tags can use the attribute "inline-class" to exact match a style rules if they need a composite class definition.
1228
- *
1229
  * @param string $content
1230
  * @param boolean $strip_style_blocks
1231
  * @return string
@@ -1266,7 +1267,7 @@ class NewsletterModule {
1266
 
1267
  /**
1268
  * Deletes a subscriber and cleans up all the stats table with his correlated data.
1269
- *
1270
  * @global wpdb $wpdb
1271
  * @param int|id[] $id
1272
  */
@@ -1289,7 +1290,7 @@ class NewsletterModule {
1289
  /**
1290
  * Add to a destination URL the parameters to identify the user, the email and to show
1291
  * an alert message, if required. The parameters are then managed by the [newsletter] shortcode.
1292
- *
1293
  * @param string $url If empty the standard newsletter page URL is used (usually it is empty, but sometime a custom URL has been specified)
1294
  * @param string $message_key The message identifier
1295
  * @param TNP_User|int $user
@@ -1333,7 +1334,7 @@ class NewsletterModule {
1333
 
1334
  /**
1335
  * Builds a standard Newsletter action URL for the specified action.
1336
- *
1337
  * @param string $action
1338
  * @param TNP_User $user
1339
  * @param TNP_Email $email
@@ -1426,7 +1427,7 @@ class NewsletterModule {
1426
 
1427
  /**
1428
  * Changes a user status. Accept a user object, user id or user email.
1429
- *
1430
  * @param TNP_User $user
1431
  * @param string $status
1432
  * @return TNP_User
@@ -1442,7 +1443,7 @@ class NewsletterModule {
1442
  }
1443
 
1444
  /**
1445
- *
1446
  * @global wpdb $wpdb
1447
  * @param TNP_User $user
1448
  * @return TNP_User
@@ -1458,8 +1459,8 @@ class NewsletterModule {
1458
  }
1459
 
1460
  /**
1461
- * Create a log entry with the meaningful user data.
1462
- *
1463
  * @global wpdb $wpdb
1464
  * @param TNP_User $user
1465
  * @param string $source
@@ -1480,7 +1481,7 @@ class NewsletterModule {
1480
  }
1481
 
1482
  /**
1483
- *
1484
  * @global wpdb $wpdb
1485
  * @param TNP_User $user
1486
  * @param int $list
@@ -1503,7 +1504,7 @@ class NewsletterModule {
1503
  }
1504
 
1505
  /**
1506
- *
1507
  * @param int $wp_user_id
1508
  * @param string $format
1509
  * @return TNP_User
@@ -1526,7 +1527,7 @@ class NewsletterModule {
1526
 
1527
  /**
1528
  * Replaces every possible Newsletter tag ({...}) in a piece of text or HTML.
1529
- *
1530
  * @global wpdb $wpdb
1531
  * @param string $text
1532
  * @param mixed $user Can be an object, associative array or id
@@ -1833,7 +1834,7 @@ class NewsletterModule {
1833
  /**
1834
  * Takes in a variable and checks if object, array or scalar and return the integer representing
1835
  * a database record id.
1836
- *
1837
  * @param mixed $var
1838
  * @return in
1839
  */
@@ -1901,7 +1902,7 @@ class NewsletterModule {
1901
  * Return the current language code. Optionally, if a user is passed and it has a language
1902
  * the user language is returned.
1903
  * If there is no language available, an empty string is returned.
1904
- *
1905
  * @param TNP_User $user
1906
  * @return string The language code
1907
  */
@@ -2017,6 +2018,40 @@ class NewsletterModule {
2017
  return $posts;
2018
  }
2019
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2020
  }
2021
 
2022
  /**
@@ -2037,7 +2072,7 @@ function newsletter_get_post_image($post_id = null, $size = 'thumbnail', $altern
2037
 
2038
  /**
2039
  * Accepts a post or a post ID.
2040
- *
2041
  * @param WP_Post $post
2042
  */
2043
  function newsletter_the_excerpt($post, $words = 30) {
80
  * @property array $options The subscriber status
81
  * */
82
  abstract class TNP_Email {
83
+
84
  }
85
 
86
  class NewsletterModule {
161
  }
162
 
163
  /**
164
+ *
165
  * @global wpdb $wpdb
166
  * @param string $query
167
  */
188
  }
189
 
190
  /**
191
+ *
192
  * @global wpdb $wpdb
193
  * @param string $table
194
  * @param array $data
611
  }
612
 
613
  function admin_menu() {
614
+
615
  }
616
 
617
  function add_menu_page($page, $title, $capability = '') {
678
 
679
  /**
680
  * Retrieves an email from DB and unserialize the options.
681
+ *
682
  * @param mixed $id
683
  * @param string $format
684
+ * @return TNP_Email An object with the same fields of TNP_Email, but not actually of that type
685
  */
686
  function get_email($id, $format = OBJECT) {
687
  $email = $this->store->get_single(NEWSLETTER_EMAILS_TABLE, $id, $format);
709
  }
710
 
711
  /**
712
+ * Save an email and provide serialization, if needed, of $email['options'].
713
  * @return TNP_Email
714
  */
715
  function save_email($email, $return_format = OBJECT) {
756
  }
757
 
758
  /**
759
+ *
760
  * @global wpdb $wpdb
761
  * @param int|array $id
762
  * @return boolean
964
 
965
  /**
966
  * Accepts a user ID or a TNP_User object. Does not check if the user really exists.
967
+ *
968
  * @param type $user
969
  */
970
  function get_user_edit_url($user) {
1000
 
1001
  /**
1002
  * Return the user identified by the "nk" parameter (POST or GET).
1003
+ * If no user can be found or the token is not matching, returns null.
1004
  * If die_on_fail is true it dies instead of return null.
1005
+ *
1006
  * @param bool $die_on_fail
1007
  * @return TNP_User
1008
  */
1095
  }
1096
 
1097
  /**
1098
+ *
1099
  * @return TNP_List[]
1100
  */
1101
  function get_lists_public($language = '') {
1117
 
1118
  /**
1119
  * Lists to be shown on subscription form.
1120
+ *
1121
  * @return TNP_List[]
1122
  */
1123
  function get_lists_for_subscription($language = '') {
1139
 
1140
  /**
1141
  * Returns the lists to be shown in the profile page.
1142
+ *
1143
  * @return TNP_List[]
1144
  */
1145
  function get_lists_for_profile($language = '') {
1161
 
1162
  /**
1163
  * Returns a list as an object (with the same signature of TNP_List)
1164
+ *
1165
  * @param int $id
1166
  * @return TNP_List
1167
  */
1208
 
1209
  /**
1210
  * Updates the user last activity timestamp.
1211
+ *
1212
  * @global wpdb $wpdb
1213
  * @param TNP_User $user
1214
  */
1226
  /**
1227
  * Finds single style blocks and adds a style attribute to every HTML tag with a class exactly matching the rules in the style
1228
  * block. HTML tags can use the attribute "inline-class" to exact match a style rules if they need a composite class definition.
1229
+ *
1230
  * @param string $content
1231
  * @param boolean $strip_style_blocks
1232
  * @return string
1267
 
1268
  /**
1269
  * Deletes a subscriber and cleans up all the stats table with his correlated data.
1270
+ *
1271
  * @global wpdb $wpdb
1272
  * @param int|id[] $id
1273
  */
1290
  /**
1291
  * Add to a destination URL the parameters to identify the user, the email and to show
1292
  * an alert message, if required. The parameters are then managed by the [newsletter] shortcode.
1293
+ *
1294
  * @param string $url If empty the standard newsletter page URL is used (usually it is empty, but sometime a custom URL has been specified)
1295
  * @param string $message_key The message identifier
1296
  * @param TNP_User|int $user
1334
 
1335
  /**
1336
  * Builds a standard Newsletter action URL for the specified action.
1337
+ *
1338
  * @param string $action
1339
  * @param TNP_User $user
1340
  * @param TNP_Email $email
1427
 
1428
  /**
1429
  * Changes a user status. Accept a user object, user id or user email.
1430
+ *
1431
  * @param TNP_User $user
1432
  * @param string $status
1433
  * @return TNP_User
1443
  }
1444
 
1445
  /**
1446
+ *
1447
  * @global wpdb $wpdb
1448
  * @param TNP_User $user
1449
  * @return TNP_User
1459
  }
1460
 
1461
  /**
1462
+ * Create a log entry with the meaningful user data.
1463
+ *
1464
  * @global wpdb $wpdb
1465
  * @param TNP_User $user
1466
  * @param string $source
1481
  }
1482
 
1483
  /**
1484
+ *
1485
  * @global wpdb $wpdb
1486
  * @param TNP_User $user
1487
  * @param int $list
1504
  }
1505
 
1506
  /**
1507
+ *
1508
  * @param int $wp_user_id
1509
  * @param string $format
1510
  * @return TNP_User
1527
 
1528
  /**
1529
  * Replaces every possible Newsletter tag ({...}) in a piece of text or HTML.
1530
+ *
1531
  * @global wpdb $wpdb
1532
  * @param string $text
1533
  * @param mixed $user Can be an object, associative array or id
1834
  /**
1835
  * Takes in a variable and checks if object, array or scalar and return the integer representing
1836
  * a database record id.
1837
+ *
1838
  * @param mixed $var
1839
  * @return in
1840
  */
1902
  * Return the current language code. Optionally, if a user is passed and it has a language
1903
  * the user language is returned.
1904
  * If there is no language available, an empty string is returned.
1905
+ *
1906
  * @param TNP_User $user
1907
  * @return string The language code
1908
  */
2018
  return $posts;
2019
  }
2020
 
2021
+ protected function generate_admin_notification_message( $user ) {
2022
+
2023
+ $message = "Subscriber details:\n\n" .
2024
+ "email: " . $user->email . "\n" .
2025
+ "first name: " . $user->name . "\n" .
2026
+ "last name: " . $user->surname . "\n" .
2027
+ "gender: " . $user->sex . "\n";
2028
+
2029
+ $lists = $this->get_lists();
2030
+ foreach ( $lists as $list ) {
2031
+ $field = 'list_' . $list->id;
2032
+ $message .= $list->name . ': ' . ( empty( $user->$field ) ? "NO" : "YES" ) . "\n";
2033
+ }
2034
+
2035
+ for ( $i = 0; $i < NEWSLETTER_PROFILE_MAX; $i ++ ) {
2036
+ if ( empty( $this->options_profile[ 'profile_' . $i ] ) ) {
2037
+ continue;
2038
+ }
2039
+ $field = 'profile_' . $i;
2040
+ $message .= $this->options_profile[ 'profile_' . $i ] . ': ' . $user->$field . "\n";
2041
+ }
2042
+
2043
+ $message .= "token: " . $user->token . "\n" .
2044
+ "status: " . $user->status . "\n";
2045
+
2046
+ return $message;
2047
+ }
2048
+
2049
+ protected function generate_admin_notification_subject( $subject ) {
2050
+ $blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
2051
+
2052
+ return '[' . $blogname . '] ' . $subject;
2053
+ }
2054
+
2055
  }
2056
 
2057
  /**
2072
 
2073
  /**
2074
  * Accepts a post or a post ID.
2075
+ *
2076
  * @param WP_Post $post
2077
  */
2078
  function newsletter_the_excerpt($post, $words = 30) {
plugin.php CHANGED
@@ -4,7 +4,7 @@
4
  Plugin Name: Newsletter
5
  Plugin URI: https://www.thenewsletterplugin.com/plugins/newsletter
6
  Description: Newsletter is a cool plugin to create your own subscriber list, to send newsletters, to build your business. <strong>Before update give a look to <a href="https://www.thenewsletterplugin.com/category/release">this page</a> to know what's changed.</strong>
7
- Version: 6.5.8
8
  Author: Stefano Lissa & The Newsletter Team
9
  Author URI: https://www.thenewsletterplugin.com
10
  Disclaimer: Use at your own risk. No warranty expressed or implied is provided.
@@ -35,7 +35,7 @@ if (version_compare(phpversion(), '5.6', '<')) {
35
  return;
36
  }
37
 
38
- define('NEWSLETTER_VERSION', '6.5.8');
39
 
40
  global $newsletter, $wpdb;
41
 
4
  Plugin Name: Newsletter
5
  Plugin URI: https://www.thenewsletterplugin.com/plugins/newsletter
6
  Description: Newsletter is a cool plugin to create your own subscriber list, to send newsletters, to build your business. <strong>Before update give a look to <a href="https://www.thenewsletterplugin.com/category/release">this page</a> to know what's changed.</strong>
7
+ Version: 6.5.9
8
  Author: Stefano Lissa & The Newsletter Team
9
  Author URI: https://www.thenewsletterplugin.com
10
  Disclaimer: Use at your own risk. No warranty expressed or implied is provided.
35
  return;
36
  }
37
 
38
+ define('NEWSLETTER_VERSION', '6.5.9');
39
 
40
  global $newsletter, $wpdb;
41
 
readme.txt CHANGED
@@ -1,8 +1,8 @@
1
  === Newsletter ===
2
  Tags: email, email marketing, newsletter, newsletter subscribers, welcome email, signup forms, contact, lead generation, popup, marketing automation
3
  Requires at least: 3.4.0
4
- Tested up to: 5.3.2
5
- Stable tag: 6.5.8
6
  Requires PHP: 5.6
7
  Contributors: satollo,webagile,michael-travan
8
 
@@ -109,6 +109,13 @@ Thank you, The Newsletter Team
109
 
110
  == Changelog ==
111
 
 
 
 
 
 
 
 
112
  = 6.5.8 =
113
 
114
  * Improvements on controls
1
  === Newsletter ===
2
  Tags: email, email marketing, newsletter, newsletter subscribers, welcome email, signup forms, contact, lead generation, popup, marketing automation
3
  Requires at least: 3.4.0
4
+ Tested up to: 5.4
5
+ Stable tag: 6.5.9
6
  Requires PHP: 5.6
7
  Contributors: satollo,webagile,michael-travan
8
 
109
 
110
  == Changelog ==
111
 
112
+ = 6.5.9 =
113
+
114
+ * Revisited the posts block
115
+ * Support for the new Reports addon styles
116
+ * Improved the excerpt extraction
117
+ * Cancellation administrative notifications on/off switch
118
+
119
  = 6.5.8 =
120
 
121
  * Improvements on controls
subscription/subscription.php CHANGED
@@ -11,12 +11,12 @@ class NewsletterSubscription extends NewsletterModule {
11
  static $instance;
12
 
13
  /**
14
- * @var array
15
  */
16
  var $options_profile;
17
 
18
  /**
19
- * @var array
20
  */
21
  var $options_lists;
22
 
@@ -182,11 +182,11 @@ class NewsletterSubscription extends NewsletterModule {
182
  if (stripos($text, 'www.') !== false) {
183
  return true;
184
  }
185
- // Blocks address like patterns
186
  // if (preg_match('/[^\s]+\.[^\s]+/m', $text)) {
187
  // return true;
188
  // }
189
-
190
  return false;
191
  }
192
 
@@ -221,22 +221,22 @@ class NewsletterSubscription extends NewsletterModule {
221
 
222
  /**
223
  * $email must be cleaned using the is_email() function.
224
- *
225
  * @param type $email
226
  * @param type $full_name
227
  * @param type $ip
228
  */
229
  function valid_subscription_or_die($email, $full_name, $ip) {
230
  $antibot_logger = new NewsletterLogger('antibot');
231
-
232
  $antibot_logger->info($_REQUEST);
233
-
234
  if (empty($email)) {
235
  echo 'Wrong email';
236
  header("HTTP/1.0 400 Bad request");
237
  die();
238
  }
239
-
240
  if ($this->is_spam_text($full_name)) {
241
  $antibot_logger->fatal($email . ' - ' . $ip . ' - Name with http: ' . $full_name);
242
  header("HTTP/1.0 404 Not Found");
@@ -277,7 +277,7 @@ class NewsletterSubscription extends NewsletterModule {
277
  }
278
 
279
  /**
280
- *
281
  * @global wpdb $wpdb
282
  * @return mixed
283
  */
@@ -494,7 +494,7 @@ class NewsletterSubscription extends NewsletterModule {
494
  }
495
 
496
  function first_install() {
497
-
498
  }
499
 
500
  function admin_menu() {
@@ -609,7 +609,7 @@ class NewsletterSubscription extends NewsletterModule {
609
 
610
  /**
611
  * Create a subscription using the $_REQUEST data. Does security checks.
612
- *
613
  * @param string $status The status to use for this subscription (confirmed, not confirmed, ...)
614
  * @param bool $emails If the confirmation/welcome email should be sent or the subscription should be silent
615
  * @return TNP_User
@@ -627,7 +627,7 @@ class NewsletterSubscription extends NewsletterModule {
627
  die();
628
  }
629
  */
630
-
631
  // Validation
632
  $ip = $this->get_remote_ip();
633
  $email = $this->normalize_email(stripslashes($_REQUEST['ne']));
@@ -657,7 +657,7 @@ class NewsletterSubscription extends NewsletterModule {
657
 
658
  if ($status != null) {
659
  // If a status is forced and it is requested to be "confirmed" is like a single opt in
660
- // $status here can only be confirmed or not confirmed
661
  // TODO: Add a check on status values
662
  if ($status == Newsletter::STATUS_CONFIRMED) {
663
  $opt_in = self::OPTIN_SINGLE;
@@ -754,7 +754,7 @@ class NewsletterSubscription extends NewsletterModule {
754
  // Notification to admin (only for new confirmed subscriptions)
755
  if ($user->status == Newsletter::STATUS_CONFIRMED) {
756
  do_action('newsletter_user_confirmed', $user);
757
- $this->notify_admin($user, 'Newsletter subscription');
758
  setcookie('newsletter', $user->id . '-' . $user->token, time() + 60 * 60 * 24 * 365, '/');
759
  }
760
 
@@ -772,7 +772,7 @@ class NewsletterSubscription extends NewsletterModule {
772
  /**
773
  * Processes the request and fill in the *array* representing a subscriber with submitted values
774
  * (filtering when necessary).
775
- *
776
  * @param array $user An array partially filled with subscriber data
777
  * @return array The filled array representing a subscriber
778
  */
@@ -865,7 +865,7 @@ class NewsletterSubscription extends NewsletterModule {
865
 
866
  /**
867
  * Sends a service message applying the template.
868
- *
869
  * @param TNP_User $user
870
  * @param string $subject
871
  * @param string $message
@@ -894,7 +894,7 @@ class NewsletterSubscription extends NewsletterModule {
894
  /**
895
  * Confirms a subscription changing the user status and, possibly, merging the
896
  * temporary data if present.
897
- *
898
  * @param int $user_id Optional. If null the user is extracted from the request.
899
  * @return TNP_User
900
  */
@@ -937,7 +937,7 @@ class NewsletterSubscription extends NewsletterModule {
937
  $this->add_user_log($user, 'activate');
938
 
939
  do_action('newsletter_user_confirmed', $user);
940
- $this->notify_admin($user, 'Newsletter subscription');
941
 
942
  if ($emails) {
943
  $this->send_message('confirmed', $user);
@@ -947,9 +947,9 @@ class NewsletterSubscription extends NewsletterModule {
947
  }
948
 
949
  /**
950
- * Sends a message (activation, welcome, cancellation, ...) with the correct template
951
  * and checking if the message itself is disabled
952
- *
953
  * @param string $type
954
  * @param TNP_User $user
955
  */
@@ -972,7 +972,7 @@ class NewsletterSubscription extends NewsletterModule {
972
 
973
  /**
974
  * Saves the subscriber data.
975
- *
976
  * @return type
977
  */
978
  function save_profile() {
@@ -985,7 +985,7 @@ class NewsletterSubscription extends NewsletterModule {
985
 
986
  /**
987
  * Sends the activation email without conditions.
988
- *
989
  * @param stdClass $user
990
  * @return bool
991
  */
@@ -1394,7 +1394,7 @@ class NewsletterSubscription extends NewsletterModule {
1394
 
1395
  /**
1396
  * The new standard form.
1397
- *
1398
  * @param type $referrer
1399
  * @param type $action
1400
  * @param type $attrs
@@ -1536,7 +1536,7 @@ class NewsletterSubscription extends NewsletterModule {
1536
  $buffer .= '<div class="tnp-field tnp-field-profile"><label>' .
1537
  esc_html($options_profile['profile_' . $i]) . '</label>';
1538
 
1539
- // Text field
1540
  if ($options_profile['profile_' . $i . '_type'] == 'text') {
1541
  $buffer .= '<input class="tnp-profile tnp-profile-' . $i . '" type="text"' . ($options_profile['profile_' . $i . '_rules'] == 1 ? ' required' : '') . ' name="np' . $i . '">';
1542
  }
@@ -1649,39 +1649,19 @@ class NewsletterSubscription extends NewsletterModule {
1649
  return $buffer;
1650
  }
1651
 
1652
- function notify_admin($user, $subject) {
1653
 
1654
- if (empty($this->options['notify'])) {
1655
- return;
1656
- }
1657
 
1658
- $message = "Subscriber details:\n\n" .
1659
- "email: " . $user->email . "\n" .
1660
- "first name: " . $user->name . "\n" .
1661
- "last name: " . $user->surname . "\n" .
1662
- "gender: " . $user->sex . "\n";
1663
 
1664
- $lists = $this->get_lists();
1665
- foreach ($lists as $list) {
1666
- $field = 'list_' . $list->id;
1667
- $message .= $list->name . ': ' . (empty($user->$field) ? "NO" : "YES") . "\n";
1668
- }
1669
 
1670
- for ($i = 0; $i < NEWSLETTER_PROFILE_MAX; $i++) {
1671
- if (empty($this->options_profile['profile_' . $i])) {
1672
- continue;
1673
- }
1674
- $field = 'profile_' . $i;
1675
- $message .= $this->options_profile['profile_' . $i] . ': ' . $user->$field . "\n";
1676
- }
1677
-
1678
- $message .= "token: " . $user->token . "\n" .
1679
- "status: " . $user->status . "\n";
1680
- $email = trim($this->options['notify_email']);
1681
-
1682
- $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
1683
- Newsletter::instance()->mail($email, '[' . $blogname . '] ' . $subject, array('text' => $message));
1684
- }
1685
 
1686
  function get_subscription_form_minimal($attrs) {
1687
 
11
  static $instance;
12
 
13
  /**
14
+ * @var array
15
  */
16
  var $options_profile;
17
 
18
  /**
19
+ * @var array
20
  */
21
  var $options_lists;
22
 
182
  if (stripos($text, 'www.') !== false) {
183
  return true;
184
  }
185
+ // Blocks address like patterns
186
  // if (preg_match('/[^\s]+\.[^\s]+/m', $text)) {
187
  // return true;
188
  // }
189
+
190
  return false;
191
  }
192
 
221
 
222
  /**
223
  * $email must be cleaned using the is_email() function.
224
+ *
225
  * @param type $email
226
  * @param type $full_name
227
  * @param type $ip
228
  */
229
  function valid_subscription_or_die($email, $full_name, $ip) {
230
  $antibot_logger = new NewsletterLogger('antibot');
231
+
232
  $antibot_logger->info($_REQUEST);
233
+
234
  if (empty($email)) {
235
  echo 'Wrong email';
236
  header("HTTP/1.0 400 Bad request");
237
  die();
238
  }
239
+
240
  if ($this->is_spam_text($full_name)) {
241
  $antibot_logger->fatal($email . ' - ' . $ip . ' - Name with http: ' . $full_name);
242
  header("HTTP/1.0 404 Not Found");
277
  }
278
 
279
  /**
280
+ *
281
  * @global wpdb $wpdb
282
  * @return mixed
283
  */
494
  }
495
 
496
  function first_install() {
497
+
498
  }
499
 
500
  function admin_menu() {
609
 
610
  /**
611
  * Create a subscription using the $_REQUEST data. Does security checks.
612
+ *
613
  * @param string $status The status to use for this subscription (confirmed, not confirmed, ...)
614
  * @param bool $emails If the confirmation/welcome email should be sent or the subscription should be silent
615
  * @return TNP_User
627
  die();
628
  }
629
  */
630
+
631
  // Validation
632
  $ip = $this->get_remote_ip();
633
  $email = $this->normalize_email(stripslashes($_REQUEST['ne']));
657
 
658
  if ($status != null) {
659
  // If a status is forced and it is requested to be "confirmed" is like a single opt in
660
+ // $status here can only be confirmed or not confirmed
661
  // TODO: Add a check on status values
662
  if ($status == Newsletter::STATUS_CONFIRMED) {
663
  $opt_in = self::OPTIN_SINGLE;
754
  // Notification to admin (only for new confirmed subscriptions)
755
  if ($user->status == Newsletter::STATUS_CONFIRMED) {
756
  do_action('newsletter_user_confirmed', $user);
757
+ $this->notify_admin_on_subscription($user);
758
  setcookie('newsletter', $user->id . '-' . $user->token, time() + 60 * 60 * 24 * 365, '/');
759
  }
760
 
772
  /**
773
  * Processes the request and fill in the *array* representing a subscriber with submitted values
774
  * (filtering when necessary).
775
+ *
776
  * @param array $user An array partially filled with subscriber data
777
  * @return array The filled array representing a subscriber
778
  */
865
 
866
  /**
867
  * Sends a service message applying the template.
868
+ *
869
  * @param TNP_User $user
870
  * @param string $subject
871
  * @param string $message
894
  /**
895
  * Confirms a subscription changing the user status and, possibly, merging the
896
  * temporary data if present.
897
+ *
898
  * @param int $user_id Optional. If null the user is extracted from the request.
899
  * @return TNP_User
900
  */
937
  $this->add_user_log($user, 'activate');
938
 
939
  do_action('newsletter_user_confirmed', $user);
940
+ $this->notify_admin_on_subscription($user);
941
 
942
  if ($emails) {
943
  $this->send_message('confirmed', $user);
947
  }
948
 
949
  /**
950
+ * Sends a message (activation, welcome, cancellation, ...) with the correct template
951
  * and checking if the message itself is disabled
952
+ *
953
  * @param string $type
954
  * @param TNP_User $user
955
  */
972
 
973
  /**
974
  * Saves the subscriber data.
975
+ *
976
  * @return type
977
  */
978
  function save_profile() {
985
 
986
  /**
987
  * Sends the activation email without conditions.
988
+ *
989
  * @param stdClass $user
990
  * @return bool
991
  */
1394
 
1395
  /**
1396
  * The new standard form.
1397
+ *
1398
  * @param type $referrer
1399
  * @param type $action
1400
  * @param type $attrs
1536
  $buffer .= '<div class="tnp-field tnp-field-profile"><label>' .
1537
  esc_html($options_profile['profile_' . $i]) . '</label>';
1538
 
1539
+ // Text field
1540
  if ($options_profile['profile_' . $i . '_type'] == 'text') {
1541
  $buffer .= '<input class="tnp-profile tnp-profile-' . $i . '" type="text"' . ($options_profile['profile_' . $i . '_rules'] == 1 ? ' required' : '') . ' name="np' . $i . '">';
1542
  }
1649
  return $buffer;
1650
  }
1651
 
1652
+ function notify_admin_on_subscription( $user ) {
1653
 
1654
+ if ( empty( $this->options['notify'] ) ) {
1655
+ return;
1656
+ }
1657
 
1658
+ $message = $this->generate_admin_notification_message( $user );
1659
+ $email = trim( $this->options['notify_email'] );
1660
+ $subject = $this->generate_admin_notification_subject( 'Newsletter subscription' );
 
 
1661
 
1662
+ Newsletter::instance()->mail( $email, $subject, array( 'text' => $message ) );
 
 
 
 
1663
 
1664
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1665
 
1666
  function get_subscription_form_minimal($attrs) {
1667
 
unsubscription/index.php CHANGED
@@ -44,7 +44,7 @@ if (!$controls->is_action()) {
44
 
45
  </div>
46
 
47
- <div id="tnp-body">
48
 
49
  <form method="post" action="">
50
  <?php $controls->init(); ?>
@@ -60,6 +60,12 @@ if (!$controls->is_action()) {
60
  </ul>
61
  <div id="tabs-cancellation">
62
  <table class="form-table">
 
 
 
 
 
 
63
  <tr>
64
  <th><?php _e('Cancellation message', 'newsletter') ?></th>
65
  <td>
@@ -92,13 +98,13 @@ if (!$controls->is_action()) {
92
  <td>
93
  <?php $controls->wp_editor('error_text', array('editor_height'=>150)); ?>
94
  <p class="description">
95
-
96
  </p>
97
  </td>
98
- </tr>
99
  </table>
100
  </div>
101
-
102
  <div id="tabs-reactivation">
103
  <table class="form-table">
104
  <tr>
@@ -122,4 +128,4 @@ if (!$controls->is_action()) {
122
 
123
  <?php include NEWSLETTER_DIR . '/tnp-footer.php'; ?>
124
 
125
- </div>
44
 
45
  </div>
46
 
47
+ <div id="tnp-body">
48
 
49
  <form method="post" action="">
50
  <?php $controls->init(); ?>
60
  </ul>
61
  <div id="tabs-cancellation">
62
  <table class="form-table">
63
+ <tr>
64
+ <th><?php _e('Notify admin on unsubscription', 'newsletter') ?></th>
65
+ <td>
66
+ <?php $controls->yesno('notify_admin_on_unsubscription'); ?>
67
+ </td>
68
+ </tr>
69
  <tr>
70
  <th><?php _e('Cancellation message', 'newsletter') ?></th>
71
  <td>
98
  <td>
99
  <?php $controls->wp_editor('error_text', array('editor_height'=>150)); ?>
100
  <p class="description">
101
+
102
  </p>
103
  </td>
104
+ </tr>
105
  </table>
106
  </div>
107
+
108
  <div id="tabs-reactivation">
109
  <table class="form-table">
110
  <tr>
128
 
129
  <?php include NEWSLETTER_DIR . '/tnp-footer.php'; ?>
130
 
131
+ </div>
unsubscription/unsubscription.php CHANGED
@@ -95,7 +95,7 @@ class NewsletterUnsubscription extends NewsletterModule {
95
 
96
  $this->send_unsubscribed_email($user);
97
 
98
- NewsletterSubscription::instance()->notify_admin($user, 'Newsletter unsubscription');
99
 
100
  return $user;
101
  }
@@ -112,10 +112,24 @@ class NewsletterUnsubscription extends NewsletterModule {
112
  return NewsletterSubscription::instance()->mail($user, $subject, $message);
113
  }
114
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  /**
116
- * Reactivate the subscriber extracted from the request setting his status
117
  * to confirmed and logging. No email are sent. Dies on subscriber extraction failure.
118
- *
119
  * @return TNP_User
120
  */
121
  function reactivate() {
95
 
96
  $this->send_unsubscribed_email($user);
97
 
98
+ $this->notify_admin_on_unsubscription($user);
99
 
100
  return $user;
101
  }
112
  return NewsletterSubscription::instance()->mail($user, $subject, $message);
113
  }
114
 
115
+ function notify_admin_on_unsubscription( $user ) {
116
+
117
+ if ( empty( $this->options['notify_admin_on_unsubscription'] ) ) {
118
+ return;
119
+ }
120
+
121
+ $message = $this->generate_admin_notification_message( $user );
122
+ $email = trim( get_option( 'admin_email' ) );
123
+ $subject = $this->generate_admin_notification_subject( 'Newsletter unsubscription' );
124
+
125
+ Newsletter::instance()->mail( $email, $subject, array( 'text' => $message ) );
126
+
127
+ }
128
+
129
  /**
130
+ * Reactivate the subscriber extracted from the request setting his status
131
  * to confirmed and logging. No email are sent. Dies on subscriber extraction failure.
132
+ *
133
  * @return TNP_User
134
  */
135
  function reactivate() {