Version Description
- Check on ctype_space function (there are installation without it)
- Improved the html-2-text conversion
- Added language to the export
- Status labels fixed on subscriber search and edit panel
- Stripped HTML tags on block generated subjects
Download this release
Release Info
Developer | satollo |
Plugin | Newsletter |
Version | 7.5.7 |
Comparing to | |
See all releases |
Code changes from version 7.5.6 to 7.5.7
- emails/blocks/posts/layout-one.php +139 -135
- emails/blocks/posts/layout-two.php +142 -136
- emails/emails.php +1365 -1365
- includes/composer.php +1008 -987
- plugin.php +2 -2
- readme.txt +10 -2
- tnp-header.php +349 -349
- users/index.php +226 -225
- users/users.php +253 -252
emails/blocks/posts/layout-one.php
CHANGED
@@ -1,135 +1,139 @@
|
|
1 |
-
<?php
|
2 |
-
$size = ['width' => 600, 'height' => 0];
|
3 |
-
$total_width = 600 - $options['block_padding_left'] - $options['block_padding_right'];
|
4 |
-
$column_width = $total_width / 2 - 10;
|
5 |
-
|
6 |
-
$title_style = TNP_Composer::get_style($options, 'title', $composer, 'title', ['scale' => .8]);
|
7 |
-
$text_style = TNP_Composer::get_style($options, '', $composer, 'text');
|
8 |
-
?>
|
9 |
-
<style>
|
10 |
-
.title {
|
11 |
-
<?php $title_style->echo_css()?>
|
12 |
-
line-height: normal !important;
|
13 |
-
padding: 0 0 5px 0;
|
14 |
-
}
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
font-
|
26 |
-
|
27 |
-
font-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
$
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
</
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
$size = ['width' => 600, 'height' => 0];
|
3 |
+
$total_width = 600 - $options['block_padding_left'] - $options['block_padding_right'];
|
4 |
+
$column_width = $total_width / 2 - 10;
|
5 |
+
|
6 |
+
$title_style = TNP_Composer::get_style($options, 'title', $composer, 'title', ['scale' => .8]);
|
7 |
+
$text_style = TNP_Composer::get_style($options, '', $composer, 'text');
|
8 |
+
?>
|
9 |
+
<style>
|
10 |
+
.title {
|
11 |
+
<?php $title_style->echo_css()?>
|
12 |
+
line-height: normal !important;
|
13 |
+
padding: 0 0 5px 0;
|
14 |
+
}
|
15 |
+
.excerpt-td {
|
16 |
+
padding: 10px 0 15px 0;
|
17 |
+
}
|
18 |
+
.excerpt {
|
19 |
+
<?php $text_style->echo_css()?>
|
20 |
+
line-height: 1.5em !important;
|
21 |
+
|
22 |
+
}
|
23 |
+
|
24 |
+
.meta {
|
25 |
+
font-family: <?php echo $text_style->font_family ?>;
|
26 |
+
color: <?php echo $text_style->font_color ?>;
|
27 |
+
font-size: <?php echo round($text_style->font_size * 0.9) ?>px;
|
28 |
+
font-weight: <?php echo $text_style->font_weight ?>;
|
29 |
+
font-style: italic;
|
30 |
+
padding: 0 0 10px 0;
|
31 |
+
line-height: normal !important;
|
32 |
+
}
|
33 |
+
.button {
|
34 |
+
padding: 15px 0;
|
35 |
+
}
|
36 |
+
</style>
|
37 |
+
|
38 |
+
|
39 |
+
<table border="0" cellpadding="0" cellspacing="0" width="100%" class="responsive">
|
40 |
+
|
41 |
+
<?php foreach ($posts as $post) { ?>
|
42 |
+
<?php
|
43 |
+
$url = tnp_post_permalink($post);
|
44 |
+
|
45 |
+
$media = null;
|
46 |
+
if ($show_image) {
|
47 |
+
$media = tnp_composer_block_posts_get_media($post, $size);
|
48 |
+
if ($media) {
|
49 |
+
$media->link = $url;
|
50 |
+
$media->set_width($column_width);
|
51 |
+
}
|
52 |
+
}
|
53 |
+
|
54 |
+
$meta = [];
|
55 |
+
|
56 |
+
if ($show_date) {
|
57 |
+
$meta[] = tnp_post_date($post);
|
58 |
+
}
|
59 |
+
|
60 |
+
if ($show_author) {
|
61 |
+
$author_object = get_user_by('id', $post->post_author);
|
62 |
+
if ($author_object) {
|
63 |
+
$meta[] = $author_object->display_name;
|
64 |
+
}
|
65 |
+
}
|
66 |
+
|
67 |
+
$button_options['button_url'] = $url;
|
68 |
+
$button_options['button_align'] = 'left';
|
69 |
+
?>
|
70 |
+
|
71 |
+
<tr>
|
72 |
+
<td valign="top" style="padding: 20px 0 0 0;">
|
73 |
+
|
74 |
+
<?php if ($media) { ?>
|
75 |
+
<table width="<?php echo $column_width ?>" cellpadding="0" cellspacing="0" border="0" align="left" class="responsive">
|
76 |
+
<tr>
|
77 |
+
<td style="padding-bottom: 20px;" width="100%">
|
78 |
+
<?php echo TNP_Composer::image($media, ['class' => 'fluid']) ?>
|
79 |
+
</td>
|
80 |
+
</tr>
|
81 |
+
</table>
|
82 |
+
<?php } ?>
|
83 |
+
|
84 |
+
<table width="<?php echo $media ? $column_width : '100%' ?>" cellpadding="0" cellspacing="0" border="0" class="responsive" align="right"><tr><td>
|
85 |
+
|
86 |
+
<table border="0" cellspacing="0" cellpadding="0" width="100%">
|
87 |
+
<?php if ($meta) { ?>
|
88 |
+
<tr>
|
89 |
+
<td inline-class="meta" dir="<?php echo $dir ?>" align="<?php echo $align_left ?>">
|
90 |
+
<?php echo esc_html(implode(' - ', $meta)) ?>
|
91 |
+
</td>
|
92 |
+
</tr>
|
93 |
+
<?php } ?>
|
94 |
+
|
95 |
+
<tr>
|
96 |
+
<td align="<?php echo $align_left ?>" inline-class="title" class="title tnpc-row-edit tnpc-inline-editable"
|
97 |
+
data-type="title" data-id="<?php echo $post->ID ?>" dir="<?php echo $dir ?>">
|
98 |
+
<span>
|
99 |
+
<?php
|
100 |
+
echo TNP_Composer::is_post_field_edited_inline($options['inline_edits'], 'title', $post->ID) ?
|
101 |
+
TNP_Composer::get_edited_inline_post_field($options['inline_edits'], 'title', $post->ID) :
|
102 |
+
tnp_post_title($post)
|
103 |
+
?>
|
104 |
+
</span>
|
105 |
+
</td>
|
106 |
+
</tr>
|
107 |
+
|
108 |
+
<?php if ($excerpt_length) { ?>
|
109 |
+
<tr>
|
110 |
+
<td align="<?php echo $align_left ?>" inline-class="excerpt-td">
|
111 |
+
<a href="<?php echo $url?>" inline-class="excerpt" class="tnpc-row-edit tnpc-inline-editable"
|
112 |
+
data-type="text" data-id="<?php echo $post->ID ?>" dir="<?php echo $dir ?>">
|
113 |
+
<?php
|
114 |
+
echo TNP_Composer::is_post_field_edited_inline($options['inline_edits'], 'text', $post->ID) ?
|
115 |
+
TNP_Composer::get_edited_inline_post_field($options['inline_edits'], 'text', $post->ID) :
|
116 |
+
tnp_post_excerpt($post, $excerpt_length)
|
117 |
+
?>
|
118 |
+
</a>
|
119 |
+
</td>
|
120 |
+
</tr>
|
121 |
+
<?php } ?>
|
122 |
+
|
123 |
+
<?php if ($show_read_more_button) { ?>
|
124 |
+
<tr>
|
125 |
+
<td align="<?php echo $align_left ?>" inline-class="button">
|
126 |
+
<?php echo TNP_Composer::button($button_options) ?>
|
127 |
+
</td>
|
128 |
+
</tr>
|
129 |
+
<?php } ?>
|
130 |
+
</table>
|
131 |
+
|
132 |
+
</td></tr></table>
|
133 |
+
|
134 |
+
</td>
|
135 |
+
</tr>
|
136 |
+
|
137 |
+
<?php } ?>
|
138 |
+
|
139 |
+
</table>
|
emails/blocks/posts/layout-two.php
CHANGED
@@ -1,136 +1,142 @@
|
|
1 |
-
<?php
|
2 |
-
$size = array('width' => 600, 'height' => 400, "crop" => true);
|
3 |
-
$total_width = 600 - $options['block_padding_left'] - $options['block_padding_right'];
|
4 |
-
$column_width = $total_width / 2 - 20;
|
5 |
-
|
6 |
-
$title_style = TNP_Composer::get_style($options, 'title', $composer, 'title', ['scale' => .8]);
|
7 |
-
$text_style = TNP_Composer::get_style($options, '', $composer, 'text');
|
8 |
-
|
9 |
-
$items = [];
|
10 |
-
?>
|
11 |
-
<style>
|
12 |
-
.title {
|
13 |
-
font-family: <?php echo $title_style->font_family ?>;
|
14 |
-
font-size: <?php echo $title_style->font_size ?>px;
|
15 |
-
font-weight: <?php echo $title_style->font_weight ?>;
|
16 |
-
color: <?php echo $title_style->font_color ?>;
|
17 |
-
line-height: 1.3em;
|
18 |
-
padding: 15px 0 0 0;
|
19 |
-
}
|
20 |
-
|
21 |
-
.excerpt {
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
font-
|
35 |
-
|
36 |
-
font-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
}
|
42 |
-
.
|
43 |
-
padding
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
padding-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
if ($
|
72 |
-
$
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
?>
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
<?php
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
<?php
|
134 |
-
|
135 |
-
|
136 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
$size = array('width' => 600, 'height' => 400, "crop" => true);
|
3 |
+
$total_width = 600 - $options['block_padding_left'] - $options['block_padding_right'];
|
4 |
+
$column_width = $total_width / 2 - 20;
|
5 |
+
|
6 |
+
$title_style = TNP_Composer::get_style($options, 'title', $composer, 'title', ['scale' => .8]);
|
7 |
+
$text_style = TNP_Composer::get_style($options, '', $composer, 'text');
|
8 |
+
|
9 |
+
$items = [];
|
10 |
+
?>
|
11 |
+
<style>
|
12 |
+
.title {
|
13 |
+
font-family: <?php echo $title_style->font_family ?>;
|
14 |
+
font-size: <?php echo $title_style->font_size ?>px;
|
15 |
+
font-weight: <?php echo $title_style->font_weight ?>;
|
16 |
+
color: <?php echo $title_style->font_color ?>;
|
17 |
+
line-height: 1.3em;
|
18 |
+
padding: 15px 0 0 0;
|
19 |
+
}
|
20 |
+
|
21 |
+
.excerpt-td {
|
22 |
+
padding: 5px 0 0 0;
|
23 |
+
}
|
24 |
+
.excerpt {
|
25 |
+
font-family: <?php echo $text_style->font_family ?>;
|
26 |
+
font-size: <?php echo $text_style->font_size ?>px;
|
27 |
+
font-weight: <?php echo $text_style->font_weight ?>;
|
28 |
+
color: <?php echo $text_style->font_color ?>;
|
29 |
+
line-height: 1.4em;
|
30 |
+
text-decoration: none;
|
31 |
+
}
|
32 |
+
|
33 |
+
.meta {
|
34 |
+
font-family: <?php echo $text_style->font_family ?>;
|
35 |
+
color: <?php echo $text_style->font_color ?>;
|
36 |
+
font-size: <?php echo round($text_style->font_size * 0.9) ?>px;
|
37 |
+
font-weight: <?php echo $text_style->font_weight ?>;
|
38 |
+
padding: 10px 0 0 0;
|
39 |
+
font-style: italic;
|
40 |
+
line-height: normal !important;
|
41 |
+
}
|
42 |
+
.button {
|
43 |
+
padding: 15px 0;
|
44 |
+
}
|
45 |
+
.column-left {
|
46 |
+
padding-right: 10px;
|
47 |
+
padding-bottom: 20px;
|
48 |
+
}
|
49 |
+
.column-right {
|
50 |
+
padding-left: 10px;
|
51 |
+
padding-bottom: 20px;
|
52 |
+
}
|
53 |
+
|
54 |
+
</style>
|
55 |
+
|
56 |
+
|
57 |
+
<?php foreach ($posts AS $p) { ?>
|
58 |
+
<?php
|
59 |
+
$url = tnp_post_permalink($p);
|
60 |
+
$media = null;
|
61 |
+
if ($show_image) {
|
62 |
+
$media = tnp_composer_block_posts_get_media($p, $size, $image_placeholder_url);
|
63 |
+
if ($media) {
|
64 |
+
$media->link = $url;
|
65 |
+
$media->set_width($column_width);
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
+
$meta = [];
|
70 |
+
|
71 |
+
if ($show_date) {
|
72 |
+
$meta[] = tnp_post_date($p);
|
73 |
+
}
|
74 |
+
|
75 |
+
if ($show_author) {
|
76 |
+
$author_object = get_user_by('id', $p->post_author);
|
77 |
+
if ($author_object) {
|
78 |
+
$meta[] = $author_object->display_name;
|
79 |
+
}
|
80 |
+
}
|
81 |
+
|
82 |
+
$button_options['button_url'] = $url;
|
83 |
+
ob_start();
|
84 |
+
?>
|
85 |
+
<table cellpadding="0" cellspacing="0" border="0" width="100%">
|
86 |
+
<?php if ($media) { ?>
|
87 |
+
<tr>
|
88 |
+
<td align="center" valign="middle">
|
89 |
+
<?php echo TNP_Composer::image($media, ['class' => 'fluid']) ?>
|
90 |
+
</td>
|
91 |
+
</tr>
|
92 |
+
<?php } ?>
|
93 |
+
<tr>
|
94 |
+
<td align="center" inline-class="title" class="title tnpc-row-edit tnpc-inline-editable" data-type="title" data-id="<?php echo $p->ID ?>">
|
95 |
+
<?php
|
96 |
+
echo TNP_Composer::is_post_field_edited_inline($options['inline_edits'], 'title', $p->ID) ?
|
97 |
+
TNP_Composer::get_edited_inline_post_field($options['inline_edits'], 'title', $p->ID) :
|
98 |
+
tnp_post_title($p)
|
99 |
+
?>
|
100 |
+
</td>
|
101 |
+
</tr>
|
102 |
+
<?php if ($meta) { ?>
|
103 |
+
<tr>
|
104 |
+
<td align="center" inline-class="meta" class="meta">
|
105 |
+
<?php echo esc_html(implode(' - ', $meta)) ?>
|
106 |
+
</td>
|
107 |
+
</tr>
|
108 |
+
<?php } ?>
|
109 |
+
|
110 |
+
|
111 |
+
<?php if ($excerpt_length) { ?>
|
112 |
+
<tr>
|
113 |
+
<td align="center" inline-class="excerpt-td">
|
114 |
+
<a href="<?php echo $url?>" inline-class="excerpt" class="title tnpc-row-edit tnpc-inline-editable" data-type="text" data-id="<?php echo $p->ID ?>" dir="<?php echo $dir ?>">
|
115 |
+
<?php
|
116 |
+
echo TNP_Composer::is_post_field_edited_inline($options['inline_edits'], 'text', $p->ID) ?
|
117 |
+
TNP_Composer::get_edited_inline_post_field($options['inline_edits'], 'text', $p->ID) :
|
118 |
+
tnp_post_excerpt($p, $excerpt_length)
|
119 |
+
?>
|
120 |
+
</a>
|
121 |
+
</td>
|
122 |
+
</tr>
|
123 |
+
<?php } ?>
|
124 |
+
|
125 |
+
<?php if ($show_read_more_button) { ?>
|
126 |
+
<tr>
|
127 |
+
<td align="center" inline-class="button">
|
128 |
+
<?php echo TNP_Composer::button($button_options) ?>
|
129 |
+
</td>
|
130 |
+
</tr>
|
131 |
+
<?php } ?>
|
132 |
+
</table>
|
133 |
+
<?php
|
134 |
+
$items[] = ob_get_clean();
|
135 |
+
}
|
136 |
+
?>
|
137 |
+
|
138 |
+
|
139 |
+
<?php echo TNP_Composer::grid($items, ['width' => $total_width, 'responsive' => true, 'padding' => 5]) ?>
|
140 |
+
|
141 |
+
|
142 |
+
|
emails/emails.php
CHANGED
@@ -1,1365 +1,1365 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
defined('ABSPATH') || exit;
|
4 |
-
|
5 |
-
class NewsletterEmails extends NewsletterModule {
|
6 |
-
|
7 |
-
static $instance;
|
8 |
-
|
9 |
-
const EDITOR_COMPOSER = 2;
|
10 |
-
const EDITOR_HTML = 1;
|
11 |
-
const EDITOR_TINYMCE = 0;
|
12 |
-
|
13 |
-
static $PRESETS_LIST;
|
14 |
-
|
15 |
-
const PRESET_EMAIL_TYPE = 'composer_template';
|
16 |
-
|
17 |
-
// Cache
|
18 |
-
var $blocks = null;
|
19 |
-
|
20 |
-
/**
|
21 |
-
* @return NewsletterEmails
|
22 |
-
*/
|
23 |
-
static function instance() {
|
24 |
-
if (self::$instance == null) {
|
25 |
-
self::$instance = new NewsletterEmails();
|
26 |
-
}
|
27 |
-
|
28 |
-
return self::$instance;
|
29 |
-
}
|
30 |
-
|
31 |
-
function __construct() {
|
32 |
-
self::$PRESETS_LIST = array("cta", "invite", "announcement", "posts", "sales", "product", "tour", "simple");
|
33 |
-
$this->themes = new NewsletterThemes('emails');
|
34 |
-
parent::__construct('emails', '1.1.5');
|
35 |
-
add_action('newsletter_action', array($this, 'hook_newsletter_action'), 13, 3);
|
36 |
-
add_action('newsletter_init', [$this, 'hook_newsletter_init']);
|
37 |
-
|
38 |
-
if (is_admin()) {
|
39 |
-
// Thank you to plugins which add the WP editor on other admin plugin pages...
|
40 |
-
if (isset($_GET['page']) && $_GET['page'] == 'newsletter_emails_edit') {
|
41 |
-
global $wp_actions;
|
42 |
-
$wp_actions['wp_enqueue_editor'] = 1;
|
43 |
-
}
|
44 |
-
}
|
45 |
-
}
|
46 |
-
|
47 |
-
function hook_newsletter_init() {
|
48 |
-
if (is_admin()) {
|
49 |
-
if (defined('DOING_AJAX') && DOING_AJAX) {
|
50 |
-
if (Newsletter::instance()->is_allowed()) {
|
51 |
-
add_action('wp_ajax_tnpc_render', array($this, 'tnpc_render_callback'));
|
52 |
-
add_action('wp_ajax_tnpc_preview', array($this, 'tnpc_preview_callback'));
|
53 |
-
add_action('wp_ajax_tnpc_css', array($this, 'tnpc_css_callback'));
|
54 |
-
add_action('wp_ajax_tnpc_options', array($this, 'hook_wp_ajax_tnpc_options'));
|
55 |
-
add_action('wp_ajax_tnpc_get_all_presets', array($this, 'ajax_get_all_presets'));
|
56 |
-
add_action('wp_ajax_tnpc_get_preset', array($this, 'ajax_get_preset'));
|
57 |
-
add_action('wp_ajax_tnpc_delete_preset', array($this, 'hook_wp_ajax_tnpc_delete_preset'));
|
58 |
-
add_action('wp_ajax_tnpc_regenerate_email', array($this, 'hook_wp_ajax_tnpc_regenerate_email'));
|
59 |
-
}
|
60 |
-
}
|
61 |
-
}
|
62 |
-
}
|
63 |
-
|
64 |
-
function options_decode($options) {
|
65 |
-
// Old "query string" format
|
66 |
-
if (is_string($options) && strpos($options, 'options[') !== false) {
|
67 |
-
$opts = [];
|
68 |
-
parse_str($options, $opts);
|
69 |
-
$options = $opts['options'];
|
70 |
-
}
|
71 |
-
|
72 |
-
if (is_array($options)) {
|
73 |
-
return $options;
|
74 |
-
}
|
75 |
-
|
76 |
-
// Json data should be base64 encoded, but for short time it wasn't
|
77 |
-
$tmp = json_decode($options, true);
|
78 |
-
if (is_null($tmp)) {
|
79 |
-
return json_decode(base64_decode($options), true);
|
80 |
-
} else {
|
81 |
-
return $tmp;
|
82 |
-
}
|
83 |
-
}
|
84 |
-
|
85 |
-
/**
|
86 |
-
*
|
87 |
-
* @param array $options Options array
|
88 |
-
*/
|
89 |
-
function options_encode($options) {
|
90 |
-
return base64_encode(json_encode($options, JSON_HEX_TAG | JSON_HEX_AMP));
|
91 |
-
}
|
92 |
-
|
93 |
-
/**
|
94 |
-
* Builds and returns the HTML with the form fields of a specific block.
|
95 |
-
*
|
96 |
-
* @global wpdb $wpdb
|
97 |
-
*/
|
98 |
-
function hook_wp_ajax_tnpc_options() {
|
99 |
-
global $wpdb;
|
100 |
-
|
101 |
-
$block = $this->get_block($_REQUEST['id']);
|
102 |
-
if (!$block) {
|
103 |
-
die('Block not found with id ' . esc_html($_REQUEST['id']));
|
104 |
-
}
|
105 |
-
|
106 |
-
if (!class_exists('NewsletterControls')) {
|
107 |
-
include NEWSLETTER_INCLUDES_DIR . '/controls.php';
|
108 |
-
}
|
109 |
-
|
110 |
-
$options = $this->options_decode(stripslashes_deep($_REQUEST['options']));
|
111 |
-
$composer = isset($_POST['composer']) ? $_POST['composer'] : [];
|
112 |
-
|
113 |
-
$context = array('type' => '');
|
114 |
-
if (isset($_REQUEST['context_type'])) {
|
115 |
-
$context['type'] = $_REQUEST['context_type'];
|
116 |
-
}
|
117 |
-
|
118 |
-
$controls = new NewsletterControls($options);
|
119 |
-
$fields = new NewsletterFields($controls);
|
120 |
-
|
121 |
-
$controls->init();
|
122 |
-
echo '<input type="hidden" name="action" value="tnpc_render">';
|
123 |
-
echo '<input type="hidden" name="id" value="' . esc_attr($_REQUEST['id']) . '">';
|
124 |
-
echo '<input type="hidden" name="context_type" value="' . esc_attr($context['type']) . '">';
|
125 |
-
$inline_edits = '';
|
126 |
-
if (isset($controls->data['inline_edits'])) {
|
127 |
-
$inline_edits = $controls->data['inline_edits'];
|
128 |
-
}
|
129 |
-
echo '<input type="hidden" name="options[inline_edits]" value="', esc_attr($this->options_encode($inline_edits)), '">';
|
130 |
-
echo "<h2>", esc_html($block["name"]), "</h2>";
|
131 |
-
include $block['dir'] . '/options.php';
|
132 |
-
wp_die();
|
133 |
-
}
|
134 |
-
|
135 |
-
/**
|
136 |
-
* Retrieves the presets list (no id in GET) or a specific preset id in GET)
|
137 |
-
*/
|
138 |
-
public function ajax_get_all_presets() {
|
139 |
-
wp_send_json_success($this->get_all_preset());
|
140 |
-
}
|
141 |
-
|
142 |
-
public function ajax_get_preset() {
|
143 |
-
|
144 |
-
if (empty($_REQUEST['id'])) {
|
145 |
-
wp_send_json_error([
|
146 |
-
'msg' => __('Invalid preset ID')
|
147 |
-
]);
|
148 |
-
}
|
149 |
-
|
150 |
-
$preset_id = $_REQUEST['id'];
|
151 |
-
$preset_content = $this->get_preset_content($preset_id);
|
152 |
-
$global_options = $this->get_preset_global_options($preset_id);
|
153 |
-
|
154 |
-
wp_send_json_success([
|
155 |
-
'content' => $preset_content,
|
156 |
-
'globalOptions' => $global_options,
|
157 |
-
]);
|
158 |
-
}
|
159 |
-
|
160 |
-
private function get_preset_content($preset_id) {
|
161 |
-
|
162 |
-
$content = '';
|
163 |
-
|
164 |
-
if ($this->is_a_tnp_default_preset($preset_id)) {
|
165 |
-
|
166 |
-
// Get preset from file
|
167 |
-
$preset = $this->get_preset_from_file($preset_id);
|
168 |
-
|
169 |
-
foreach ($preset->blocks as $item) {
|
170 |
-
ob_start();
|
171 |
-
$this->render_block($item->block, true, (array) $item->options);
|
172 |
-
$content .= trim(ob_get_clean());
|
173 |
-
}
|
174 |
-
} else {
|
175 |
-
|
176 |
-
// Get preset from db
|
177 |
-
$preset_email = $this->get_email(intval($preset_id));
|
178 |
-
$global_options = $this->extract_global_options_from($preset_email);
|
179 |
-
$content = $this->regenerate_email_blocks($preset_email->message, $global_options);
|
180 |
-
}
|
181 |
-
|
182 |
-
return $content;
|
183 |
-
}
|
184 |
-
|
185 |
-
private function get_preset_global_options($preset_id) {
|
186 |
-
|
187 |
-
if ($this->is_a_tnp_default_preset($preset_id)) {
|
188 |
-
return [];
|
189 |
-
}
|
190 |
-
|
191 |
-
// Get preset from db
|
192 |
-
$preset_email = $this->get_email(intval($preset_id));
|
193 |
-
$global_options = $this->extract_global_options_from($preset_email);
|
194 |
-
|
195 |
-
return $global_options;
|
196 |
-
}
|
197 |
-
|
198 |
-
private function extract_global_options_from($email) {
|
199 |
-
$global_options = [];
|
200 |
-
foreach ($email->options as $global_option_name => $global_option) {
|
201 |
-
if (strpos($global_option_name, 'composer_') === 0) {
|
202 |
-
$global_options[str_replace('composer_', '', $global_option_name)] = $global_option;
|
203 |
-
}
|
204 |
-
}
|
205 |
-
|
206 |
-
return $global_options;
|
207 |
-
}
|
208 |
-
|
209 |
-
private function is_a_tnp_default_preset($preset_id) {
|
210 |
-
return in_array($preset_id, self::$PRESETS_LIST);
|
211 |
-
}
|
212 |
-
|
213 |
-
private function get_all_preset() {
|
214 |
-
|
215 |
-
$content = "<div class='tnpc-preset-container'>";
|
216 |
-
|
217 |
-
if ($this->is_normal_context_request()) {
|
218 |
-
$content .= "<div class='tnpc-preset-legacy-themes'><a href='" . $this->get_admin_page_url('theme') . "'>" . __('Looking for legacy themes?', 'newsletter') . "</a></div>";
|
219 |
-
}
|
220 |
-
|
221 |
-
// LOAD USER PRESETS
|
222 |
-
$user_preset_list = $this->get_emails(self::PRESET_EMAIL_TYPE);
|
223 |
-
|
224 |
-
foreach ($user_preset_list as $user_preset) {
|
225 |
-
|
226 |
-
$default_icon_url = NEWSLETTER_URL . "/emails/presets/default-icon.png?ver=2";
|
227 |
-
$preset_name = $user_preset->subject;
|
228 |
-
$delete_preset_text = __('Delete', 'newsletter');
|
229 |
-
$edit_preset_text = __('Edit', 'newsletter');
|
230 |
-
|
231 |
-
// esc_js() assumes the string will be in single quote (arghhh!!!)
|
232 |
-
$onclick_edit = 'tnpc_edit_preset(' . ((int) $user_preset->id) . ', \'' . esc_js($preset_name) . '\', event)';
|
233 |
-
$onclick_delete = 'tnpc_delete_preset(' . ((int) $user_preset->id) . ', \'' . esc_js($preset_name) . '\', event)';
|
234 |
-
$onclick_load = 'tnpc_load_preset(' . ((int) $user_preset->id) . ', \'' . esc_js($preset_name) . '\', event)';
|
235 |
-
|
236 |
-
$content .= "<div class='tnpc-preset' onclick='" . esc_attr($onclick_load) . "'>\n";
|
237 |
-
$content .= "<img src='$default_icon_url' title='" . esc_attr($preset_name) . "' alt='" . esc_attr($preset_name) . "'>\n";
|
238 |
-
$content .= "<span class='tnpc-preset-label'>" . esc_html($user_preset->subject) . "</span>\n";
|
239 |
-
$content .= "<span class='tnpc-delete-preset' onclick='" . esc_attr($onclick_delete) . "' title='" . esc_attr($delete_preset_text) . "'><i class='fas fa-times'></i></span>\n";
|
240 |
-
$content .= "<span class='tnpc-edit-preset' onclick='" . esc_attr($onclick_edit) . "' title='" . esc_attr($edit_preset_text) . "'><i class='fas fa-pencil-alt'></i></span>\n";
|
241 |
-
$content .= "</div>";
|
242 |
-
}
|
243 |
-
|
244 |
-
// LOAD TNP PRESETS
|
245 |
-
foreach (self::$PRESETS_LIST as $id) {
|
246 |
-
$preset = $this->get_preset_from_file($id);
|
247 |
-
$preset_name = esc_html($preset->name);
|
248 |
-
$content .= "<div class='tnpc-preset' onclick='tnpc_load_preset(\"$id\")'>";
|
249 |
-
$content .= "<img src='$preset->icon' title='$preset_name' alt='$preset_name'/>";
|
250 |
-
$content .= "<span class='tnpc-preset-label'>$preset_name</span>";
|
251 |
-
$content .= "</div>";
|
252 |
-
}
|
253 |
-
|
254 |
-
if ($this->is_normal_context_request()) {
|
255 |
-
$content .= $this->get_automated_spot_element();
|
256 |
-
$content .= $this->get_autoresponder_spot_element();
|
257 |
-
$content .= $this->get_raw_html_preset_element();
|
258 |
-
}
|
259 |
-
|
260 |
-
return $content;
|
261 |
-
}
|
262 |
-
|
263 |
-
private function is_normal_context_request() {
|
264 |
-
return empty($_REQUEST['context_type']);
|
265 |
-
}
|
266 |
-
|
267 |
-
private function is_automated_context_request() {
|
268 |
-
return isset($_REQUEST['context_type']) && $_REQUEST['context_type'] === 'automated';
|
269 |
-
}
|
270 |
-
|
271 |
-
private function is_autoresponder_context_request() {
|
272 |
-
return isset($_REQUEST['context_type']) && $_REQUEST['context_type'] === 'autoresponder';
|
273 |
-
}
|
274 |
-
|
275 |
-
private function get_automated_spot_element() {
|
276 |
-
$result = "<div class='tnpc-preset'>";
|
277 |
-
if (class_exists('NewsletterAutomated')) {
|
278 |
-
$result .= "<a href='?page=newsletter_automated_index'>";
|
279 |
-
} else {
|
280 |
-
$result .= "<a href='https://www.thenewsletterplugin.com/automated?utm_source=composer&utm_campaign=plugin&utm_medium=automated'>";
|
281 |
-
}
|
282 |
-
$result .= "<img src='" . plugins_url('newsletter') . "/emails/images/automated.png' title='Automated addon' alt='Automated'/>";
|
283 |
-
$result .= "<span class='tnpc-preset-label'>Daily, weekly and monthly newsletters</span></a>";
|
284 |
-
$result .= "</div>";
|
285 |
-
|
286 |
-
return $result;
|
287 |
-
}
|
288 |
-
|
289 |
-
private function get_autoresponder_spot_element() {
|
290 |
-
$result = "<div class='tnpc-preset'>";
|
291 |
-
if (class_exists('NewsletterAutoresponder')) {
|
292 |
-
$result .= "<a href='?page=newsletter_autoresponder_index'>";
|
293 |
-
} else {
|
294 |
-
$result .= "<a href='https://www.thenewsletterplugin.com/autoresponder?utm_source=composer&utm_campaign=plugin&utm_medium=autoresponder' target='_blank'>";
|
295 |
-
}
|
296 |
-
$result .= "<img src='" . plugins_url('newsletter') . "/emails/images/autoresponder.png' title='Autoresponder addon' alt='Autoresponder'/>";
|
297 |
-
$result .= "<span class='tnpc-preset-label'>Autoresponders</span></a>";
|
298 |
-
$result .= "</div>";
|
299 |
-
|
300 |
-
return $result;
|
301 |
-
}
|
302 |
-
|
303 |
-
private function get_raw_html_preset_element() {
|
304 |
-
|
305 |
-
$result = "<div class='tnpc-preset tnpc-preset-html' onclick='location.href=\"" . wp_nonce_url('admin.php?page=newsletter_emails_new&id=rawhtml', 'newsletter-new') . "\"'>";
|
306 |
-
$result .= "<img src='" . plugins_url('newsletter') . "/emails/images/rawhtml.png' title='RAW HTML' alt='RAW'/>";
|
307 |
-
$result .= "<span class='tnpc-preset-label'>Raw HTML</span>";
|
308 |
-
$result .= "</div>";
|
309 |
-
|
310 |
-
$result .= "<div class='clear'></div>";
|
311 |
-
$result .= "</div>";
|
312 |
-
|
313 |
-
return $result;
|
314 |
-
}
|
315 |
-
|
316 |
-
function has_dynamic_blocks($theme) {
|
317 |
-
preg_match_all('/data-json="(.*?)"/m', $theme, $matches, PREG_PATTERN_ORDER);
|
318 |
-
foreach ($matches[1] as $match) {
|
319 |
-
$a = html_entity_decode($match, ENT_QUOTES, 'UTF-8');
|
320 |
-
$options = $this->options_decode($a);
|
321 |
-
|
322 |
-
$block = $this->get_block($options['block_id']);
|
323 |
-
if (!$block) {
|
324 |
-
continue;
|
325 |
-
}
|
326 |
-
if ($block['type'] == 'dynamic') {
|
327 |
-
return true;
|
328 |
-
}
|
329 |
-
}
|
330 |
-
return false;
|
331 |
-
}
|
332 |
-
|
333 |
-
/**
|
334 |
-
* Regenerates a saved composed email rendering each block. Regeneration is
|
335 |
-
* conditioned (possibly) by the context. The context is usually passed to blocks
|
336 |
-
* so they can act in the right manner.
|
337 |
-
*
|
338 |
-
* $context contains a type and, for automated, the last_run.
|
339 |
-
*
|
340 |
-
* $email can actually be even a string containing the full newsletter HTML code.
|
341 |
-
*
|
342 |
-
* @param TNP_Email $email
|
343 |
-
* @return string
|
344 |
-
*/
|
345 |
-
function regenerate($email, $context = []) {
|
346 |
-
|
347 |
-
$context = array_merge(['last_run' => 0, 'type' => ''], $context);
|
348 |
-
|
349 |
-
$composer = [];
|
350 |
-
foreach ($email->options as $k=>$v) {
|
351 |
-
if (strpos($k, 'composer_') !== 0) continue;
|
352 |
-
$composer[substr($k, 9)] = $v;
|
353 |
-
}
|
354 |
-
|
355 |
-
|
356 |
-
preg_match_all('/data-json="(.*?)"/m', $email->message, $matches, PREG_PATTERN_ORDER);
|
357 |
-
|
358 |
-
$result = '';
|
359 |
-
$subject = '';
|
360 |
-
|
361 |
-
foreach ($matches[1] as $match) {
|
362 |
-
$a = html_entity_decode($match, ENT_QUOTES, 'UTF-8');
|
363 |
-
$options = $this->options_decode($a);
|
364 |
-
|
365 |
-
$block = $this->get_block($options['block_id']);
|
366 |
-
if (!$block) {
|
367 |
-
$this->logger->debug('Unable to load the block ' . $options['block_id']);
|
368 |
-
//continue;
|
369 |
-
}
|
370 |
-
|
371 |
-
ob_start();
|
372 |
-
$out = $this->render_block($options['block_id'], true, $options, $context, $composer);
|
373 |
-
if (is_array($out)) {
|
374 |
-
if ($out['return_empty_message'] || $out['stop']) {
|
375 |
-
return false;
|
376 |
-
}
|
377 |
-
if ($out['skip']) {
|
378 |
-
continue;
|
379 |
-
}
|
380 |
-
if (empty($subject) && !empty($out['subject'])) {
|
381 |
-
$subject = $out['subject'];
|
382 |
-
}
|
383 |
-
}
|
384 |
-
$block_html = ob_get_clean();
|
385 |
-
$result .= $block_html;
|
386 |
-
}
|
387 |
-
|
388 |
-
$email->message = TNP_Composer::get_html_open($email) . TNP_Composer::get_main_wrapper_open($email) .
|
389 |
-
$result . TNP_Composer::get_main_wrapper_close($email) . TNP_Composer::get_html_close($email);
|
390 |
-
$email->subject = $subject;
|
391 |
-
return true;
|
392 |
-
}
|
393 |
-
|
394 |
-
function remove_block_data($text) {
|
395 |
-
// TODO: Lavorare!
|
396 |
-
return $text;
|
397 |
-
}
|
398 |
-
|
399 |
-
static function get_outlook_wrapper_open($width = 600) {
|
400 |
-
return '<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" align="center" cellspacing="0" width="' . $width . '"><tr><td width="' . $width . '" style="vertical-align:top;width:' . $width . 'px;"><![endif]-->';
|
401 |
-
}
|
402 |
-
|
403 |
-
static function get_outlook_wrapper_close() {
|
404 |
-
return "<!--[if mso | IE]></td></tr></table><![endif]-->";
|
405 |
-
}
|
406 |
-
|
407 |
-
function hook_safe_style_css($rules) {
|
408 |
-
$rules[] = 'display';
|
409 |
-
return $rules;
|
410 |
-
}
|
411 |
-
|
412 |
-
/**
|
413 |
-
* Renders a block identified by its id, using the block options and adding a wrapper
|
414 |
-
* if required (for the first block rendering).
|
415 |
-
*
|
416 |
-
* @param string $block_id
|
417 |
-
* @param boolean $wrapper
|
418 |
-
* @param array $options
|
419 |
-
* @param array $context
|
420 |
-
* @param array $composer
|
421 |
-
*/
|
422 |
-
function render_block($block_id = null, $wrapper = false, $options = [], $context = [], $composer = []) {
|
423 |
-
static $kses_style_filter = false;
|
424 |
-
include_once NEWSLETTER_INCLUDES_DIR . '/helper.php';
|
425 |
-
|
426 |
-
//Remove 'options_composer_' prefix
|
427 |
-
$composer_defaults = [];
|
428 |
-
foreach (TNP_Composer::get_global_style_defaults() as $global_option_name => $global_option) {
|
429 |
-
$composer_defaults[str_replace('options_composer_', '', $global_option_name)] = $global_option;
|
430 |
-
}
|
431 |
-
$composer = array_merge($composer_defaults, $composer);
|
432 |
-
|
433 |
-
$width = 600;
|
434 |
-
$font_family = 'Helvetica, Arial, sans-serif';
|
435 |
-
|
436 |
-
$global_title_font_family = $composer['title_font_family'];
|
437 |
-
$global_title_font_size = $composer['title_font_size'];
|
438 |
-
$global_title_font_color = $composer['title_font_color'];
|
439 |
-
$global_title_font_weight = $composer['title_font_weight'];
|
440 |
-
|
441 |
-
$global_text_font_family = $composer['text_font_family'];
|
442 |
-
$global_text_font_size = $composer['text_font_size'];
|
443 |
-
$global_text_font_color = $composer['text_font_color'];
|
444 |
-
$global_text_font_weight = $composer['text_font_weight'];
|
445 |
-
|
446 |
-
$global_button_font_family = $composer['button_font_family'];
|
447 |
-
$global_button_font_size = $composer['button_font_size'];
|
448 |
-
$global_button_font_color = $composer['button_font_color'];
|
449 |
-
$global_button_font_weight = $composer['button_font_weight'];
|
450 |
-
$global_button_background_color = $composer['button_background_color'];
|
451 |
-
|
452 |
-
$global_block_background = $composer['block_background'];
|
453 |
-
|
454 |
-
$info = Newsletter::instance()->get_options('info');
|
455 |
-
|
456 |
-
// Just in case...
|
457 |
-
if (!is_array($options)) {
|
458 |
-
$options = array();
|
459 |
-
}
|
460 |
-
|
461 |
-
// This code filters the HTML to remove javascript and unsecure attributes and enable the
|
462 |
-
// "display" rule for CSS which is needed in blocks to force specific "block" or "inline" or "table".
|
463 |
-
add_filter('safe_style_css', [$this, 'hook_safe_style_css'], 9999);
|
464 |
-
$options = wp_kses_post_deep($options);
|
465 |
-
remove_filter('safe_style_css', [$this, 'hook_safe_style_css']);
|
466 |
-
|
467 |
-
$block_options = get_option('newsletter_main');
|
468 |
-
|
469 |
-
$block = $this->get_block($block_id);
|
470 |
-
|
471 |
-
if (!isset($context['type']))
|
472 |
-
$context['type'] = '';
|
473 |
-
|
474 |
-
// Block not found
|
475 |
-
if (!$block) {
|
476 |
-
if ($wrapper) {
|
477 |
-
echo '<table border="0" cellpadding="0" cellspacing="0" align="center" width="100%" style="border-collapse: collapse; width: 100%;" class="tnpc-row tnpc-row-block" data-id="', esc_attr($block_id), '">';
|
478 |
-
echo '<tr>';
|
479 |
-
echo '<td data-options="" bgcolor="#ffffff" align="center" style="padding: 0; font-family: Helvetica, Arial, sans-serif;" class="edit-block">';
|
480 |
-
}
|
481 |
-
echo $this->get_outlook_wrapper_open($width);
|
482 |
-
|
483 |
-
echo '<p>Ops, this block type is not avalable.</p>';
|
484 |
-
|
485 |
-
echo $this->get_outlook_wrapper_close();
|
486 |
-
|
487 |
-
if ($wrapper) {
|
488 |
-
echo '</td></tr></table>';
|
489 |
-
}
|
490 |
-
return;
|
491 |
-
}
|
492 |
-
|
493 |
-
$out = ['subject' => '', 'return_empty_message' => false, 'stop' => false, 'skip' => false];
|
494 |
-
|
495 |
-
$dir = is_rtl() ? 'rtl' : 'ltr';
|
496 |
-
$align_left = is_rtl() ? 'right' : 'left';
|
497 |
-
$align_right = is_rtl() ? 'left' : 'right';
|
498 |
-
|
499 |
-
ob_start();
|
500 |
-
$logger = $this->logger;
|
501 |
-
include $block['dir'] . '/block.php';
|
502 |
-
$content = trim(ob_get_clean());
|
503 |
-
|
504 |
-
if (empty($content)) {
|
505 |
-
return $out;
|
506 |
-
}
|
507 |
-
|
508 |
-
$common_defaults = array(
|
509 |
-
'block_padding_top' => 0,
|
510 |
-
'block_padding_bottom' => 0,
|
511 |
-
'block_padding_right' => 0,
|
512 |
-
'block_padding_left' => 0,
|
513 |
-
'block_background' => '',
|
514 |
-
'block_background_2' => '',
|
515 |
-
'block_width' => 600,
|
516 |
-
'block_align' => 'center'
|
517 |
-
);
|
518 |
-
|
519 |
-
$options = array_merge($common_defaults, $options);
|
520 |
-
|
521 |
-
// Obsolete
|
522 |
-
$content = str_replace('{width}', $width, $content);
|
523 |
-
|
524 |
-
$content = $this->inline_css($content, true);
|
525 |
-
|
526 |
-
// CSS driven by the block
|
527 |
-
// Requited for the server side parsing and rendering
|
528 |
-
$options['block_id'] = $block_id;
|
529 |
-
|
530 |
-
$options['block_padding_top'] = (int) str_replace('px', '', $options['block_padding_top']);
|
531 |
-
$options['block_padding_bottom'] = (int) str_replace('px', '', $options['block_padding_bottom']);
|
532 |
-
$options['block_padding_right'] = (int) str_replace('px', '', $options['block_padding_right']);
|
533 |
-
$options['block_padding_left'] = (int) str_replace('px', '', $options['block_padding_left']);
|
534 |
-
|
535 |
-
$block_background = empty($options['block_background']) ? $global_block_background : $options['block_background'];
|
536 |
-
|
537 |
-
// Internal TD wrapper
|
538 |
-
$style = 'text-align: center; ';
|
539 |
-
$style .= 'width: 100% !important; ';
|
540 |
-
$style .= 'line-height: normal !important; ';
|
541 |
-
$style .= 'letter-spacing: normal; ';
|
542 |
-
$style .= 'padding-top: ' . $options['block_padding_top'] . 'px; ';
|
543 |
-
$style .= 'padding-left: ' . $options['block_padding_left'] . 'px; ';
|
544 |
-
$style .= 'padding-right: ' . $options['block_padding_right'] . 'px; ';
|
545 |
-
$style .= 'padding-bottom: ' . $options['block_padding_bottom'] . 'px; ';
|
546 |
-
$style .= 'background-color: ' . $block_background . ';';
|
547 |
-
|
548 |
-
if (isset($options['block_background_gradient'])) {
|
549 |
-
$style .= 'background: linear-gradient(180deg, ' . $block_background . ' 0%, ' . $options['block_background_2'] . ' 100%);';
|
550 |
-
}
|
551 |
-
|
552 |
-
$data = $this->options_encode($options);
|
553 |
-
// First time block creation wrapper
|
554 |
-
if ($wrapper) {
|
555 |
-
echo '<table border="0" cellpadding="0" cellspacing="0" align="center" width="100%" style="border-collapse: collapse; width: 100%;" class="tnpc-row tnpc-row-block" data-id="', esc_attr($block_id), '">', "\n";
|
556 |
-
echo "<tr>";
|
557 |
-
echo '<td align="center" style="padding: 0;" class="edit-block">', "\n";
|
558 |
-
}
|
559 |
-
|
560 |
-
// Container that fixes the width and makes the block responsive
|
561 |
-
echo $this->get_outlook_wrapper_open($options['block_width']);
|
562 |
-
|
563 |
-
echo '<table type="options" data-json="', esc_attr($data), '" class="tnpc-block-content" border="0" cellpadding="0" align="center" cellspacing="0" width="100%" style="width: 100%!important; max-width: ', $options['block_width'], 'px!important">', "\n";
|
564 |
-
echo "<tr>";
|
565 |
-
echo '<td align="', esc_attr($options['block_align']), '" style="', esc_attr($style), '" bgcolor="', esc_attr($block_background), '" width="100%">';
|
566 |
-
|
567 |
-
//echo "<!-- block generated content -->\n";
|
568 |
-
echo trim($content);
|
569 |
-
//echo "\n<!-- /block generated content -->\n";
|
570 |
-
|
571 |
-
echo "</td></tr></table>";
|
572 |
-
echo $this->get_outlook_wrapper_close();
|
573 |
-
|
574 |
-
// First time block creation wrapper
|
575 |
-
if ($wrapper) {
|
576 |
-
echo "</td></tr></table>";
|
577 |
-
}
|
578 |
-
|
579 |
-
return $out;
|
580 |
-
}
|
581 |
-
|
582 |
-
/**
|
583 |
-
* Ajax call to render a block with a new set of options after the settings popup
|
584 |
-
* has been saved.
|
585 |
-
*
|
586 |
-
* @param type $block_id
|
587 |
-
* @param type $wrapper
|
588 |
-
*/
|
589 |
-
function tnpc_render_callback() {
|
590 |
-
if (!check_ajax_referer('save')) {
|
591 |
-
$this->dienow('Expired request');
|
592 |
-
}
|
593 |
-
|
594 |
-
$block_id = $_POST['id'];
|
595 |
-
$wrapper = isset($_POST['full']);
|
596 |
-
$options = $this->restore_options_from_request();
|
597 |
-
|
598 |
-
$this->render_block($block_id, $wrapper, $options, [], $_POST['composer']);
|
599 |
-
wp_die();
|
600 |
-
}
|
601 |
-
|
602 |
-
function hook_wp_ajax_tnpc_regenerate_email() {
|
603 |
-
|
604 |
-
$content = stripslashes($_POST['content']);
|
605 |
-
$global_options = $_POST['composer'];
|
606 |
-
|
607 |
-
$regenerated_content = $this->regenerate_email_blocks($content, $global_options);
|
608 |
-
|
609 |
-
wp_send_json_success([
|
610 |
-
'content' => $regenerated_content,
|
611 |
-
'message' => __('Successfully updated', 'newsletter')
|
612 |
-
]);
|
613 |
-
}
|
614 |
-
|
615 |
-
private function regenerate_email_blocks($content, $global_options) {
|
616 |
-
|
617 |
-
$raw_block_options = $this->extract_encoded_blocks_options($content);
|
618 |
-
|
619 |
-
$regenerated_content = '';
|
620 |
-
|
621 |
-
foreach ($raw_block_options as $raw_block_option) {
|
622 |
-
|
623 |
-
/* $a = html_entity_decode( $raw_block_option, ENT_QUOTES, 'UTF-8' );
|
624 |
-
$block_options = $this->options_decode( $a ); */
|
625 |
-
|
626 |
-
$block_options = $this->options_decode($raw_block_option);
|
627 |
-
|
628 |
-
$block = $this->get_block($block_options['block_id']);
|
629 |
-
if (!$block) {
|
630 |
-
$this->logger->debug('Unable to load the block ' . $block_options['block_id']);
|
631 |
-
}
|
632 |
-
|
633 |
-
ob_start();
|
634 |
-
$this->render_block($block_options['block_id'], true, $block_options, [], $global_options);
|
635 |
-
$block_html = ob_get_clean();
|
636 |
-
|
637 |
-
$regenerated_content .= $block_html;
|
638 |
-
}
|
639 |
-
|
640 |
-
return $regenerated_content;
|
641 |
-
}
|
642 |
-
|
643 |
-
/**
|
644 |
-
* @param string $html_email_content Email html content
|
645 |
-
*
|
646 |
-
* @return string[] Encoded options of email blocks
|
647 |
-
*/
|
648 |
-
private function extract_encoded_blocks_options($html_email_content) {
|
649 |
-
|
650 |
-
preg_match_all('/data-json="(.*?)"/m', $html_email_content, $raw_block_options, PREG_PATTERN_ORDER);
|
651 |
-
|
652 |
-
return $raw_block_options[1];
|
653 |
-
}
|
654 |
-
|
655 |
-
function tnpc_preview_callback() {
|
656 |
-
$email = Newsletter::instance()->get_email($_REQUEST['id'], ARRAY_A);
|
657 |
-
|
658 |
-
if (empty($email)) {
|
659 |
-
echo 'Wrong email identifier';
|
660 |
-
return;
|
661 |
-
}
|
662 |
-
|
663 |
-
echo $email['message'];
|
664 |
-
|
665 |
-
wp_die();
|
666 |
-
}
|
667 |
-
|
668 |
-
function tnpc_css_callback() {
|
669 |
-
include NEWSLETTER_DIR . '/emails/tnp-composer/css/newsletter.css';
|
670 |
-
wp_die();
|
671 |
-
}
|
672 |
-
|
673 |
-
/** Returns the correct admin page to edit the newsletter with the correct editor. */
|
674 |
-
function get_editor_url($email_id, $editor_type) {
|
675 |
-
switch ($editor_type) {
|
676 |
-
case NewsletterEmails::EDITOR_COMPOSER:
|
677 |
-
return admin_url("admin.php") . '?page=newsletter_emails_composer&id=' . $email_id;
|
678 |
-
case NewsletterEmails::EDITOR_HTML:
|
679 |
-
return admin_url("admin.php") . '?page=newsletter_emails_editorhtml&id=' . $email_id;
|
680 |
-
case NewsletterEmails::EDITOR_TINYMCE:
|
681 |
-
return admin_url("admin.php") . '?page=newsletter_emails_editortinymce&id=' . $email_id;
|
682 |
-
}
|
683 |
-
}
|
684 |
-
|
685 |
-
/**
|
686 |
-
* Returns the button linked to the correct "edit" page for the passed newsletter. The edit page can be an editor
|
687 |
-
* or the targeting page (it depends on newsletter status).
|
688 |
-
*
|
689 |
-
* @param TNP_Email $email
|
690 |
-
*/
|
691 |
-
function get_edit_button($email, $only_icon = false) {
|
692 |
-
|
693 |
-
$editor_type = $this->get_editor_type($email);
|
694 |
-
if ($email->status == 'new') {
|
695 |
-
$edit_url = $this->get_editor_url($email->id, $editor_type);
|
696 |
-
} else {
|
697 |
-
$edit_url = 'admin.php?page=newsletter_emails_edit&id=' . $email->id;
|
698 |
-
}
|
699 |
-
switch ($editor_type) {
|
700 |
-
case NewsletterEmails::EDITOR_COMPOSER:
|
701 |
-
$icon_class = 'th-large';
|
702 |
-
break;
|
703 |
-
case NewsletterEmails::EDITOR_HTML:
|
704 |
-
$icon_class = 'code';
|
705 |
-
break;
|
706 |
-
default:
|
707 |
-
$icon_class = 'edit';
|
708 |
-
break;
|
709 |
-
}
|
710 |
-
if ($only_icon) {
|
711 |
-
return '<a class="button-primary" href="' . $edit_url . '" title="' . esc_attr__('Edit', 'newsletter') . '">' .
|
712 |
-
'<i class="fas fa-' . $icon_class . '"></i></a>';
|
713 |
-
} else {
|
714 |
-
return '<a class="button-primary" href="' . $edit_url . '" title="' . esc_attr__('Edit', 'newsletter') . '">' .
|
715 |
-
'<i class="fas fa-' . $icon_class . '"></i> ' . __('Edit', 'newsletter') . '</a>';
|
716 |
-
}
|
717 |
-
}
|
718 |
-
|
719 |
-
/** Returns the correct editor type for the provided newsletter. Contains backward compatibility code. */
|
720 |
-
function get_editor_type($email) {
|
721 |
-
$email = (object) $email;
|
722 |
-
$editor_type = $email->editor;
|
723 |
-
|
724 |
-
// Backward compatibility
|
725 |
-
$email_options = maybe_unserialize($email->options);
|
726 |
-
if (isset($email_options['composer'])) {
|
727 |
-
$editor_type = NewsletterEmails::EDITOR_COMPOSER;
|
728 |
-
}
|
729 |
-
// End backward compatibility
|
730 |
-
|
731 |
-
return $editor_type;
|
732 |
-
}
|
733 |
-
|
734 |
-
/**
|
735 |
-
*
|
736 |
-
* @param type $action
|
737 |
-
* @param type $user
|
738 |
-
* @param type $email
|
739 |
-
* @return type
|
740 |
-
* @global wpdb $wpdb
|
741 |
-
*/
|
742 |
-
function hook_newsletter_action($action, $user, $email) {
|
743 |
-
global $wpdb;
|
744 |
-
|
745 |
-
switch ($action) {
|
746 |
-
case 'v':
|
747 |
-
case 'view':
|
748 |
-
$id = $_GET['id'];
|
749 |
-
if ($id == 'last') {
|
750 |
-
$email = $wpdb->get_row("select * from " . NEWSLETTER_EMAILS_TABLE . " where private=0 and type='message' and status='sent' order by send_on desc limit 1");
|
751 |
-
} else {
|
752 |
-
$email = $this->get_email($_GET['id']);
|
753 |
-
}
|
754 |
-
if (empty($email)) {
|
755 |
-
header("HTTP/1.0 404 Not Found");
|
756 |
-
die('Email not found');
|
757 |
-
}
|
758 |
-
|
759 |
-
if (!Newsletter::instance()->is_allowed()) {
|
760 |
-
|
761 |
-
if ($email->status == 'new') {
|
762 |
-
header("HTTP/1.0 404 Not Found");
|
763 |
-
die('Not sent yet');
|
764 |
-
}
|
765 |
-
|
766 |
-
if ($email->private == 1) {
|
767 |
-
if (!$user) {
|
768 |
-
header("HTTP/1.0 404 Not Found");
|
769 |
-
die('No available for online view');
|
770 |
-
}
|
771 |
-
$sent = $wpdb->get_row($wpdb->prepare("select * from " . NEWSLETTER_SENT_TABLE . " where email_id=%d and user_id=%d limit 1", $email->id, $user->id));
|
772 |
-
if (!$sent) {
|
773 |
-
header("HTTP/1.0 404 Not Found");
|
774 |
-
die('No available for online view');
|
775 |
-
}
|
776 |
-
}
|
777 |
-
}
|
778 |
-
|
779 |
-
|
780 |
-
header('Content-Type: text/html;charset=UTF-8');
|
781 |
-
header('X-Robots-Tag: noindex,nofollow,noarchive');
|
782 |
-
header('Cache-Control: no-cache,no-store,private');
|
783 |
-
|
784 |
-
echo $this->replace($email->message, $user, $email);
|
785 |
-
|
786 |
-
die();
|
787 |
-
break;
|
788 |
-
|
789 |
-
case 'emails-css':
|
790 |
-
$email_id = (int) $_GET['id'];
|
791 |
-
|
792 |
-
$body = Newsletter::instance()->get_email_field($email_id, 'message');
|
793 |
-
|
794 |
-
$x = strpos($body, '<style');
|
795 |
-
if ($x === false)
|
796 |
-
return;
|
797 |
-
|
798 |
-
$x = strpos($body, '>', $x);
|
799 |
-
$y = strpos($body, '</style>');
|
800 |
-
|
801 |
-
header('Content-Type: text/css;charset=UTF-8');
|
802 |
-
|
803 |
-
echo substr($body, $x + 1, $y - $x - 1);
|
804 |
-
|
805 |
-
die();
|
806 |
-
break;
|
807 |
-
|
808 |
-
case 'emails-composer-css':
|
809 |
-
header('Cache: no-cache');
|
810 |
-
header('Content-Type: text/css');
|
811 |
-
echo $this->get_composer_css();
|
812 |
-
die();
|
813 |
-
break;
|
814 |
-
|
815 |
-
case 'emails-preview':
|
816 |
-
if (!Newsletter::instance()->is_allowed()) {
|
817 |
-
die('Not enough privileges');
|
818 |
-
}
|
819 |
-
|
820 |
-
if (!check_admin_referer('view')) {
|
821 |
-
die();
|
822 |
-
}
|
823 |
-
|
824 |
-
$theme_id = $_GET['id'];
|
825 |
-
$theme = $this->themes->get_theme($theme_id);
|
826 |
-
|
827 |
-
// Used by theme code
|
828 |
-
$theme_options = $this->themes->get_options($theme_id);
|
829 |
-
|
830 |
-
$theme_url = $theme['url'];
|
831 |
-
|
832 |
-
header('Content-Type: text/html;charset=UTF-8');
|
833 |
-
|
834 |
-
include $theme['dir'] . '/theme.php';
|
835 |
-
|
836 |
-
die();
|
837 |
-
break;
|
838 |
-
|
839 |
-
case 'emails-preview-text':
|
840 |
-
header('Content-Type: text/plain;charset=UTF-8');
|
841 |
-
if (!Newsletter::instance()->is_allowed()) {
|
842 |
-
die('Not enough privileges');
|
843 |
-
}
|
844 |
-
|
845 |
-
if (!check_admin_referer('view')) {
|
846 |
-
die();
|
847 |
-
}
|
848 |
-
|
849 |
-
// Used by theme code
|
850 |
-
$theme_options = $this->get_current_theme_options();
|
851 |
-
|
852 |
-
$file = include $theme['dir'] . '/theme-text.php';
|
853 |
-
|
854 |
-
if (is_file($file)) {
|
855 |
-
include $file;
|
856 |
-
}
|
857 |
-
|
858 |
-
die();
|
859 |
-
break;
|
860 |
-
|
861 |
-
case 'emails-create':
|
862 |
-
// Newsletter from themes are created on frontend context because sometime WP themes change the way the content,
|
863 |
-
// excerpt, thumbnail are extracted.
|
864 |
-
if (!Newsletter::instance()->is_allowed()) {
|
865 |
-
die('Not enough privileges');
|
866 |
-
}
|
867 |
-
|
868 |
-
require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
|
869 |
-
$controls = new NewsletterControls();
|
870 |
-
|
871 |
-
if (!$controls->is_action('create')) {
|
872 |
-
die('Wrong call');
|
873 |
-
}
|
874 |
-
|
875 |
-
$theme_id = $controls->data['id'];
|
876 |
-
$theme = $this->themes->get_theme($theme_id);
|
877 |
-
|
878 |
-
if (!$theme) {
|
879 |
-
die('invalid theme');
|
880 |
-
}
|
881 |
-
|
882 |
-
$this->themes->save_options($theme_id, $controls->data);
|
883 |
-
|
884 |
-
$email = array();
|
885 |
-
$email['status'] = 'new';
|
886 |
-
$email['subject'] = ''; //__('Here the email subject', 'newsletter');
|
887 |
-
$email['track'] = Newsletter::instance()->options['track'];
|
888 |
-
$email['send_on'] = time();
|
889 |
-
$email['editor'] = NewsletterEmails::EDITOR_TINYMCE;
|
890 |
-
$email['type'] = 'message';
|
891 |
-
|
892 |
-
$theme_options = $this->themes->get_options($theme_id);
|
893 |
-
|
894 |
-
$theme_url = $theme['url'];
|
895 |
-
$theme_subject = '';
|
896 |
-
|
897 |
-
ob_start();
|
898 |
-
include $theme['dir'] . '/theme.php';
|
899 |
-
$email['message'] = ob_get_clean();
|
900 |
-
|
901 |
-
if (!empty($theme_subject)) {
|
902 |
-
$email['subject'] = $theme_subject;
|
903 |
-
}
|
904 |
-
|
905 |
-
if (file_exists($theme['dir'] . '/theme-text.php')) {
|
906 |
-
ob_start();
|
907 |
-
include $theme['dir'] . '/theme-text.php';
|
908 |
-
$email['message_text'] = ob_get_clean();
|
909 |
-
} else {
|
910 |
-
$email['message_text'] = 'You need a modern email client to read this email. Read it online: {email_url}.';
|
911 |
-
}
|
912 |
-
|
913 |
-
$email = $this->save_email($email);
|
914 |
-
|
915 |
-
$edit_url = $this->get_editor_url($email->id, $email->editor);
|
916 |
-
|
917 |
-
header('Location: ' . $edit_url);
|
918 |
-
|
919 |
-
die();
|
920 |
-
break;
|
921 |
-
}
|
922 |
-
}
|
923 |
-
|
924 |
-
function admin_menu() {
|
925 |
-
$this->add_menu_page('index', 'Newsletters');
|
926 |
-
$this->add_admin_page('list', 'Email List');
|
927 |
-
$this->add_admin_page('new', 'Email New');
|
928 |
-
$this->add_admin_page('edit', 'Email Edit');
|
929 |
-
$this->add_admin_page('theme', 'Email Themes');
|
930 |
-
$this->add_admin_page('composer', 'The Composer');
|
931 |
-
$this->add_admin_page('editorhtml', 'HTML Editor');
|
932 |
-
$this->add_admin_page('editortinymce', 'TinyMCE Editor');
|
933 |
-
}
|
934 |
-
|
935 |
-
/**
|
936 |
-
* Builds a block data structure starting from the folder containing the block
|
937 |
-
* files.
|
938 |
-
*
|
939 |
-
* @param string $dir
|
940 |
-
* @return array | WP_Error
|
941 |
-
*/
|
942 |
-
function build_block($dir) {
|
943 |
-
$dir = realpath($dir);
|
944 |
-
$dir = wp_normalize_path($dir);
|
945 |
-
$full_file = $dir . '/block.php';
|
946 |
-
if (!is_file($full_file)) {
|
947 |
-
return new WP_Error('1', 'Missing block.php file in ' . $dir);
|
948 |
-
}
|
949 |
-
|
950 |
-
$wp_content_dir = wp_normalize_path(realpath(WP_CONTENT_DIR));
|
951 |
-
|
952 |
-
$relative_dir = substr($dir, strlen($wp_content_dir));
|
953 |
-
$file = basename($dir);
|
954 |
-
|
955 |
-
$data = get_file_data($full_file, ['name' => 'Name', 'section' => 'Section', 'description' => 'Description', 'type' => 'Type']);
|
956 |
-
$defaults = ['section' => 'content', 'name' => ucfirst($file), 'descritpion' => '', 'icon' => plugins_url('newsletter') . '/admin/images/block-icon.png'];
|
957 |
-
$data = array_merge($defaults, $data);
|
958 |
-
|
959 |
-
if (is_file($dir . '/icon.png')) {
|
960 |
-
$data['icon'] = content_url($relative_dir . '/icon.png');
|
961 |
-
}
|
962 |
-
|
963 |
-
$data['id'] = sanitize_key($file);
|
964 |
-
|
965 |
-
// Absolute path of the block files
|
966 |
-
$data['dir'] = $dir;
|
967 |
-
$data['url'] = content_url($relative_dir);
|
968 |
-
|
969 |
-
return $data;
|
970 |
-
}
|
971 |
-
|
972 |
-
/**
|
973 |
-
*
|
974 |
-
* @param type $dir
|
975 |
-
* @return type
|
976 |
-
*/
|
977 |
-
function scan_blocks_dir($dir) {
|
978 |
-
$dir = realpath($dir);
|
979 |
-
if (!$dir) {
|
980 |
-
return [];
|
981 |
-
}
|
982 |
-
$dir = wp_normalize_path($dir);
|
983 |
-
|
984 |
-
$list = [];
|
985 |
-
$handle = opendir($dir);
|
986 |
-
while ($file = readdir($handle)) {
|
987 |
-
|
988 |
-
$data = $this->build_block($dir . '/' . $file);
|
989 |
-
|
990 |
-
if (is_wp_error($data)) {
|
991 |
-
$this->logger->error($data);
|
992 |
-
continue;
|
993 |
-
}
|
994 |
-
$list[$data['id']] = $data;
|
995 |
-
}
|
996 |
-
closedir($handle);
|
997 |
-
return $list;
|
998 |
-
}
|
999 |
-
|
1000 |
-
/**
|
1001 |
-
* Array of arrays with every registered block and legacy block converted to the new
|
1002 |
-
* format.
|
1003 |
-
*
|
1004 |
-
* @return array
|
1005 |
-
*/
|
1006 |
-
function get_blocks() {
|
1007 |
-
|
1008 |
-
if (!is_null($this->blocks)) {
|
1009 |
-
return $this->blocks;
|
1010 |
-
}
|
1011 |
-
|
1012 |
-
$this->blocks = $this->scan_blocks_dir(__DIR__ . '/blocks');
|
1013 |
-
|
1014 |
-
$extended = $this->scan_blocks_dir(WP_CONTENT_DIR . '/extensions/newsletter/blocks');
|
1015 |
-
|
1016 |
-
$this->blocks = array_merge($extended, $this->blocks);
|
1017 |
-
|
1018 |
-
$dirs = apply_filters('newsletter_blocks_dir', array());
|
1019 |
-
|
1020 |
-
//$this->logger->debug('Block dirs:');
|
1021 |
-
//$this->logger->debug($dirs);
|
1022 |
-
|
1023 |
-
foreach ($dirs as $dir) {
|
1024 |
-
$list = $this->scan_blocks_dir($dir);
|
1025 |
-
$this->blocks = array_merge($list, $this->blocks);
|
1026 |
-
}
|
1027 |
-
|
1028 |
-
do_action('newsletter_register_blocks');
|
1029 |
-
|
1030 |
-
foreach (TNP_Composer::$block_dirs as $dir) {
|
1031 |
-
$block = $this->build_block($dir);
|
1032 |
-
if (is_wp_error($block)) {
|
1033 |
-
$this->logger->error($block);
|
1034 |
-
continue;
|
1035 |
-
}
|
1036 |
-
if (!isset($this->blocks[$block['id']])) {
|
1037 |
-
$this->blocks[$block['id']] = $block;
|
1038 |
-
} else {
|
1039 |
-
$this->logger->error('The block "' . $block['id'] . '" has already been registered');
|
1040 |
-
}
|
1041 |
-
}
|
1042 |
-
|
1043 |
-
$this->blocks = array_reverse($this->blocks);
|
1044 |
-
return $this->blocks;
|
1045 |
-
}
|
1046 |
-
|
1047 |
-
/**
|
1048 |
-
* Return a single block (associative array) checking for legacy ID as well.
|
1049 |
-
*
|
1050 |
-
* @param string $id
|
1051 |
-
* @return array
|
1052 |
-
*/
|
1053 |
-
function get_block($id) {
|
1054 |
-
switch ($id) {
|
1055 |
-
case 'content-03-text.block':
|
1056 |
-
$id = 'text';
|
1057 |
-
break;
|
1058 |
-
case 'footer-03-social.block':
|
1059 |
-
$id = 'social';
|
1060 |
-
break;
|
1061 |
-
case 'footer-02-canspam.block':
|
1062 |
-
$id = 'canspam';
|
1063 |
-
break;
|
1064 |
-
case 'content-05-image.block':
|
1065 |
-
$id = 'image';
|
1066 |
-
break;
|
1067 |
-
case 'header-01-header.block':
|
1068 |
-
$id = 'header';
|
1069 |
-
break;
|
1070 |
-
case 'footer-01-footer.block':
|
1071 |
-
$id = 'footer';
|
1072 |
-
break;
|
1073 |
-
case 'content-02-heading.block':
|
1074 |
-
$id = 'heading';
|
1075 |
-
break;
|
1076 |
-
case 'content-07-twocols.block':
|
1077 |
-
case 'content-06-posts.block':
|
1078 |
-
$id = 'posts';
|
1079 |
-
break;
|
1080 |
-
case 'content-04-cta.block':
|
1081 |
-
$id = 'cta';
|
1082 |
-
break;
|
1083 |
-
case 'content-01-hero.block':
|
1084 |
-
$id = 'hero';
|
1085 |
-
break;
|
1086 |
-
// case 'content-02-heading.block': $id = '/plugins/newsletter/emails/blocks/heading';
|
1087 |
-
// break;
|
1088 |
-
}
|
1089 |
-
|
1090 |
-
// Conversion for old full path ID
|
1091 |
-
$id = sanitize_key(basename($id));
|
1092 |
-
|
1093 |
-
// TODO: Correct id for compatibility
|
1094 |
-
$blocks = $this->get_blocks();
|
1095 |
-
if (!isset($blocks[$id])) {
|
1096 |
-
return null;
|
1097 |
-
}
|
1098 |
-
return $blocks[$id];
|
1099 |
-
}
|
1100 |
-
|
1101 |
-
function scan_presets_dir($dir = null) {
|
1102 |
-
|
1103 |
-
if (is_null($dir)) {
|
1104 |
-
$dir = __DIR__ . '/presets';
|
1105 |
-
}
|
1106 |
-
|
1107 |
-
if (!is_dir($dir)) {
|
1108 |
-
return array();
|
1109 |
-
}
|
1110 |
-
|
1111 |
-
$handle = opendir($dir);
|
1112 |
-
$list = array();
|
1113 |
-
$relative_dir = substr($dir, strlen(WP_CONTENT_DIR));
|
1114 |
-
while ($file = readdir($handle)) {
|
1115 |
-
|
1116 |
-
if ($file == '.' || $file == '..')
|
1117 |
-
continue;
|
1118 |
-
|
1119 |
-
// The block unique key, we should find out how to build it, maybe an hash of the (relative) dir?
|
1120 |
-
$preset_id = sanitize_key($file);
|
1121 |
-
|
1122 |
-
$full_file = $dir . '/' . $file . '/preset.json';
|
1123 |
-
|
1124 |
-
if (!is_file($full_file)) {
|
1125 |
-
continue;
|
1126 |
-
}
|
1127 |
-
|
1128 |
-
$icon = content_url($relative_dir . '/' . $file . '/icon.png');
|
1129 |
-
|
1130 |
-
$list[$preset_id] = $icon;
|
1131 |
-
}
|
1132 |
-
closedir($handle);
|
1133 |
-
return $list;
|
1134 |
-
}
|
1135 |
-
|
1136 |
-
function get_preset_from_file($id, $dir = null) {
|
1137 |
-
|
1138 |
-
if (is_null($dir)) {
|
1139 |
-
$dir = __DIR__ . '/presets';
|
1140 |
-
}
|
1141 |
-
|
1142 |
-
$id = $this->sanitize_file_name($id);
|
1143 |
-
|
1144 |
-
if (!is_dir($dir . '/' . $id) || !in_array($id, self::$PRESETS_LIST)) {
|
1145 |
-
return array();
|
1146 |
-
}
|
1147 |
-
|
1148 |
-
$json_content = file_get_contents("$dir/$id/preset.json");
|
1149 |
-
$json_content = str_replace("{placeholder_base_url}", plugins_url('newsletter') . '/emails/presets', $json_content);
|
1150 |
-
$json = json_decode($json_content);
|
1151 |
-
$json->icon = NEWSLETTER_URL . "/emails/presets/$id/icon.png?ver=2";
|
1152 |
-
|
1153 |
-
return $json;
|
1154 |
-
}
|
1155 |
-
|
1156 |
-
function get_composer_css() {
|
1157 |
-
$css = file_get_contents(__DIR__ . '/tnp-composer/css/newsletter.css');
|
1158 |
-
$blocks = $this->get_blocks();
|
1159 |
-
foreach ($blocks as $block) {
|
1160 |
-
if (!file_exists($block['dir'] . '/style.css')) {
|
1161 |
-
continue;
|
1162 |
-
}
|
1163 |
-
$css .= "\n\n";
|
1164 |
-
$css .= "/* " . $block['name'] . " */\n";
|
1165 |
-
$css .= file_get_contents($block['dir'] . '/style.css');
|
1166 |
-
}
|
1167 |
-
return $css;
|
1168 |
-
}
|
1169 |
-
|
1170 |
-
function get_composer_backend_css() {
|
1171 |
-
$css = file_get_contents(__DIR__ . '/tnp-composer/css/backend.css');
|
1172 |
-
$css .= "\n\n";
|
1173 |
-
$css .= $this->get_composer_css();
|
1174 |
-
return $css;
|
1175 |
-
}
|
1176 |
-
|
1177 |
-
/**
|
1178 |
-
* Send an email to the test subscribers.
|
1179 |
-
*
|
1180 |
-
* @param TNP_Email $email Could be any object with the TNP_Email attributes
|
1181 |
-
* @param NewsletterControls $controls
|
1182 |
-
*/
|
1183 |
-
function send_test_email($email, $controls) {
|
1184 |
-
if (!$email) {
|
1185 |
-
$controls->errors = __('Newsletter should be saved before send a test', 'newsletter');
|
1186 |
-
return;
|
1187 |
-
}
|
1188 |
-
|
1189 |
-
$original_subject = $email->subject;
|
1190 |
-
$this->set_test_subject_to($email);
|
1191 |
-
|
1192 |
-
$users = NewsletterUsers::instance()->get_test_users();
|
1193 |
-
if (count($users) == 0) {
|
1194 |
-
$controls->errors = '' . __('There are no test subscribers to send to', 'newsletter') .
|
1195 |
-
'. <a href="https://www.thenewsletterplugin.com/plugins/newsletter/subscribers-module#test" target="_blank"><strong>' .
|
1196 |
-
__('Read more', 'newsletter') . '</strong></a>.';
|
1197 |
-
} else {
|
1198 |
-
$r = Newsletter::instance()->send($email, $users, true);
|
1199 |
-
$emails = array();
|
1200 |
-
foreach ($users as $user) {
|
1201 |
-
$emails[] = '<a href="admin.php?page=newsletter_users_edit&id=' . $user->id . '" target="_blank">' . $user->email . '</a>';
|
1202 |
-
}
|
1203 |
-
if (is_wp_error($r)) {
|
1204 |
-
$controls->errors = 'Something went wrong. Check the error logs on status page.<br>';
|
1205 |
-
$controls->errors .= __('Test subscribers:', 'newsletter');
|
1206 |
-
$controls->errors .= ' ' . implode(', ', $emails);
|
1207 |
-
$controls->errors .= '<br>';
|
1208 |
-
$controls->errors .= '<strong>' . esc_html($r->get_error_message()) . '</strong><br>';
|
1209 |
-
$controls->errors .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
|
1210 |
-
} else {
|
1211 |
-
$controls->messages = __('Test subscribers:', 'newsletter');
|
1212 |
-
|
1213 |
-
$controls->messages .= ' ' . implode(', ', $emails);
|
1214 |
-
$controls->messages .= '.<br>';
|
1215 |
-
$controls->messages .= '<a href="https://www.thenewsletterplugin.com/documentation/subscribers#test" target="_blank"><strong>' .
|
1216 |
-
__('Read more about test subscribers', 'newsletter') . '</strong></a>.<br>';
|
1217 |
-
$controls->messages .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
|
1218 |
-
}
|
1219 |
-
}
|
1220 |
-
$email->subject = $original_subject;
|
1221 |
-
}
|
1222 |
-
|
1223 |
-
/**
|
1224 |
-
* Send an email to the test subscribers.
|
1225 |
-
*
|
1226 |
-
* @param TNP_Email $email Could be any object with the TNP_Email attributes
|
1227 |
-
* @param string $email_address
|
1228 |
-
*
|
1229 |
-
* @throws Exception
|
1230 |
-
*/
|
1231 |
-
function send_test_newsletter_to_email_address($email, $email_address) {
|
1232 |
-
|
1233 |
-
if (!$email) {
|
1234 |
-
throw new Exception(__('Newsletter should be saved before send a test', 'newsletter'));
|
1235 |
-
}
|
1236 |
-
|
1237 |
-
$this->set_test_subject_to($email);
|
1238 |
-
|
1239 |
-
$dummy_subscriber = $this->make_dummy_subscriber();
|
1240 |
-
$dummy_subscriber->email = $email_address;
|
1241 |
-
|
1242 |
-
$result = Newsletter::instance()->send($email, [$dummy_subscriber], true);
|
1243 |
-
|
1244 |
-
$email = '<a href="admin.php?page=newsletter_users_edit&id=' . $dummy_subscriber->id . '" target="_blank">' . $dummy_subscriber->email . '</a>';
|
1245 |
-
|
1246 |
-
if (is_wp_error($result)) {
|
1247 |
-
$error_message = 'Something went wrong. Check the error logs on status page.<br>';
|
1248 |
-
$error_message .= __('Test subscribers:', 'newsletter');
|
1249 |
-
$error_message .= ' ' . $email;
|
1250 |
-
$error_message .= '<br>';
|
1251 |
-
$error_message .= '<strong>' . esc_html($result->get_error_message()) . '</strong><br>';
|
1252 |
-
$error_message .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
|
1253 |
-
throw new Exception($error_message);
|
1254 |
-
}
|
1255 |
-
|
1256 |
-
$messages = __('Test subscribers:', 'newsletter');
|
1257 |
-
|
1258 |
-
$messages .= ' ' . $email;
|
1259 |
-
$messages .= '.<br>';
|
1260 |
-
$messages .= '<a href="https://www.thenewsletterplugin.com/documentation/subscribers#test" target="_blank"><strong>' .
|
1261 |
-
__('Read more about test subscribers', 'newsletter') . '</strong></a>.<br>';
|
1262 |
-
$messages .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
|
1263 |
-
|
1264 |
-
return $messages;
|
1265 |
-
}
|
1266 |
-
|
1267 |
-
private function set_test_subject_to($email) {
|
1268 |
-
if ($email->subject == '') {
|
1269 |
-
$email->subject = '[TEST] Dummy subject, it was empty (remember to set it)';
|
1270 |
-
} else {
|
1271 |
-
$email->subject = $email->subject . ' (TEST)';
|
1272 |
-
}
|
1273 |
-
}
|
1274 |
-
|
1275 |
-
private function make_dummy_subscriber() {
|
1276 |
-
$dummy_user = new TNP_User();
|
1277 |
-
$dummy_user->id = 0;
|
1278 |
-
$dummy_user->email = 'john.doe@example.org';
|
1279 |
-
$dummy_user->name = 'John';
|
1280 |
-
$dummy_user->surname = 'Doe';
|
1281 |
-
$dummy_user->sex = 'n';
|
1282 |
-
$dummy_user->language = '';
|
1283 |
-
$dummy_user->ip = '';
|
1284 |
-
|
1285 |
-
for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
|
1286 |
-
$profile_key = "profile_$i";
|
1287 |
-
$dummy_user->$profile_key = '';
|
1288 |
-
}
|
1289 |
-
|
1290 |
-
return $dummy_user;
|
1291 |
-
}
|
1292 |
-
|
1293 |
-
function restore_options_from_request() {
|
1294 |
-
|
1295 |
-
require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
|
1296 |
-
$controls = new NewsletterControls();
|
1297 |
-
$options = $controls->data;
|
1298 |
-
|
1299 |
-
if (isset($_POST['options']) && is_array($_POST['options'])) {
|
1300 |
-
// Get all block options
|
1301 |
-
//$options = stripslashes_deep($_POST['options']);
|
1302 |
-
// Deserialize inline edits when
|
1303 |
-
// render is preformed on saving block options
|
1304 |
-
if (isset($options['inline_edits']) && !is_array($options['inline_edits'])) {
|
1305 |
-
$options['inline_edits'] = $this->options_decode($options['inline_edits']);
|
1306 |
-
}
|
1307 |
-
|
1308 |
-
// Restore inline edits from data-json
|
1309 |
-
// coming from inline editing
|
1310 |
-
// and merge with current inline edit
|
1311 |
-
if (isset($_POST['encoded_options'])) {
|
1312 |
-
$decoded_options = $this->options_decode($_POST['encoded_options']);
|
1313 |
-
|
1314 |
-
$to_merge_inline_edits = [];
|
1315 |
-
|
1316 |
-
if (isset($decoded_options['inline_edits'])) {
|
1317 |
-
foreach ($decoded_options['inline_edits'] as $decoded_inline_edit) {
|
1318 |
-
$to_merge_inline_edits[$decoded_inline_edit['post_id'] . $decoded_inline_edit['type']] = $decoded_inline_edit;
|
1319 |
-
}
|
1320 |
-
}
|
1321 |
-
|
1322 |
-
//Overwrite with new edited content
|
1323 |
-
if (isset($options['inline_edits'])) {
|
1324 |
-
foreach ($options['inline_edits'] as $inline_edit) {
|
1325 |
-
$to_merge_inline_edits[$inline_edit['post_id'] . $inline_edit['type']] = $inline_edit;
|
1326 |
-
}
|
1327 |
-
}
|
1328 |
-
|
1329 |
-
$options['inline_edits'] = array_values($to_merge_inline_edits);
|
1330 |
-
$options = array_merge($decoded_options, $options);
|
1331 |
-
}
|
1332 |
-
|
1333 |
-
return $options;
|
1334 |
-
}
|
1335 |
-
|
1336 |
-
return array();
|
1337 |
-
}
|
1338 |
-
|
1339 |
-
public function hook_wp_ajax_tnpc_delete_preset() {
|
1340 |
-
|
1341 |
-
if (!wp_verify_nonce($_POST['_wpnonce'], 'preset')) {
|
1342 |
-
wp_send_json_error('Expired request');
|
1343 |
-
}
|
1344 |
-
|
1345 |
-
$preset_id = (int) $_REQUEST['presetId'];
|
1346 |
-
|
1347 |
-
$newsletter = Newsletter::instance();
|
1348 |
-
|
1349 |
-
if ($preset_id > 0) {
|
1350 |
-
$preset = $newsletter->get_email($preset_id);
|
1351 |
-
|
1352 |
-
if ($preset && $preset->type === self::PRESET_EMAIL_TYPE) {
|
1353 |
-
Newsletter::instance()->delete_email($preset_id);
|
1354 |
-
wp_send_json_success();
|
1355 |
-
} else {
|
1356 |
-
wp_send_json_error(__('Is not a preset!', 'newsletter'));
|
1357 |
-
}
|
1358 |
-
} else {
|
1359 |
-
wp_send_json_error();
|
1360 |
-
}
|
1361 |
-
}
|
1362 |
-
|
1363 |
-
}
|
1364 |
-
|
1365 |
-
NewsletterEmails::instance();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
defined('ABSPATH') || exit;
|
4 |
+
|
5 |
+
class NewsletterEmails extends NewsletterModule {
|
6 |
+
|
7 |
+
static $instance;
|
8 |
+
|
9 |
+
const EDITOR_COMPOSER = 2;
|
10 |
+
const EDITOR_HTML = 1;
|
11 |
+
const EDITOR_TINYMCE = 0;
|
12 |
+
|
13 |
+
static $PRESETS_LIST;
|
14 |
+
|
15 |
+
const PRESET_EMAIL_TYPE = 'composer_template';
|
16 |
+
|
17 |
+
// Cache
|
18 |
+
var $blocks = null;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @return NewsletterEmails
|
22 |
+
*/
|
23 |
+
static function instance() {
|
24 |
+
if (self::$instance == null) {
|
25 |
+
self::$instance = new NewsletterEmails();
|
26 |
+
}
|
27 |
+
|
28 |
+
return self::$instance;
|
29 |
+
}
|
30 |
+
|
31 |
+
function __construct() {
|
32 |
+
self::$PRESETS_LIST = array("cta", "invite", "announcement", "posts", "sales", "product", "tour", "simple");
|
33 |
+
$this->themes = new NewsletterThemes('emails');
|
34 |
+
parent::__construct('emails', '1.1.5');
|
35 |
+
add_action('newsletter_action', array($this, 'hook_newsletter_action'), 13, 3);
|
36 |
+
add_action('newsletter_init', [$this, 'hook_newsletter_init']);
|
37 |
+
|
38 |
+
if (is_admin()) {
|
39 |
+
// Thank you to plugins which add the WP editor on other admin plugin pages...
|
40 |
+
if (isset($_GET['page']) && $_GET['page'] == 'newsletter_emails_edit') {
|
41 |
+
global $wp_actions;
|
42 |
+
$wp_actions['wp_enqueue_editor'] = 1;
|
43 |
+
}
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
function hook_newsletter_init() {
|
48 |
+
if (is_admin()) {
|
49 |
+
if (defined('DOING_AJAX') && DOING_AJAX) {
|
50 |
+
if (Newsletter::instance()->is_allowed()) {
|
51 |
+
add_action('wp_ajax_tnpc_render', array($this, 'tnpc_render_callback'));
|
52 |
+
add_action('wp_ajax_tnpc_preview', array($this, 'tnpc_preview_callback'));
|
53 |
+
add_action('wp_ajax_tnpc_css', array($this, 'tnpc_css_callback'));
|
54 |
+
add_action('wp_ajax_tnpc_options', array($this, 'hook_wp_ajax_tnpc_options'));
|
55 |
+
add_action('wp_ajax_tnpc_get_all_presets', array($this, 'ajax_get_all_presets'));
|
56 |
+
add_action('wp_ajax_tnpc_get_preset', array($this, 'ajax_get_preset'));
|
57 |
+
add_action('wp_ajax_tnpc_delete_preset', array($this, 'hook_wp_ajax_tnpc_delete_preset'));
|
58 |
+
add_action('wp_ajax_tnpc_regenerate_email', array($this, 'hook_wp_ajax_tnpc_regenerate_email'));
|
59 |
+
}
|
60 |
+
}
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
function options_decode($options) {
|
65 |
+
// Old "query string" format
|
66 |
+
if (is_string($options) && strpos($options, 'options[') !== false) {
|
67 |
+
$opts = [];
|
68 |
+
parse_str($options, $opts);
|
69 |
+
$options = $opts['options'];
|
70 |
+
}
|
71 |
+
|
72 |
+
if (is_array($options)) {
|
73 |
+
return $options;
|
74 |
+
}
|
75 |
+
|
76 |
+
// Json data should be base64 encoded, but for short time it wasn't
|
77 |
+
$tmp = json_decode($options, true);
|
78 |
+
if (is_null($tmp)) {
|
79 |
+
return json_decode(base64_decode($options), true);
|
80 |
+
} else {
|
81 |
+
return $tmp;
|
82 |
+
}
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
*
|
87 |
+
* @param array $options Options array
|
88 |
+
*/
|
89 |
+
function options_encode($options) {
|
90 |
+
return base64_encode(json_encode($options, JSON_HEX_TAG | JSON_HEX_AMP));
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Builds and returns the HTML with the form fields of a specific block.
|
95 |
+
*
|
96 |
+
* @global wpdb $wpdb
|
97 |
+
*/
|
98 |
+
function hook_wp_ajax_tnpc_options() {
|
99 |
+
global $wpdb;
|
100 |
+
|
101 |
+
$block = $this->get_block($_REQUEST['id']);
|
102 |
+
if (!$block) {
|
103 |
+
die('Block not found with id ' . esc_html($_REQUEST['id']));
|
104 |
+
}
|
105 |
+
|
106 |
+
if (!class_exists('NewsletterControls')) {
|
107 |
+
include NEWSLETTER_INCLUDES_DIR . '/controls.php';
|
108 |
+
}
|
109 |
+
|
110 |
+
$options = $this->options_decode(stripslashes_deep($_REQUEST['options']));
|
111 |
+
$composer = isset($_POST['composer']) ? $_POST['composer'] : [];
|
112 |
+
|
113 |
+
$context = array('type' => '');
|
114 |
+
if (isset($_REQUEST['context_type'])) {
|
115 |
+
$context['type'] = $_REQUEST['context_type'];
|
116 |
+
}
|
117 |
+
|
118 |
+
$controls = new NewsletterControls($options);
|
119 |
+
$fields = new NewsletterFields($controls);
|
120 |
+
|
121 |
+
$controls->init();
|
122 |
+
echo '<input type="hidden" name="action" value="tnpc_render">';
|
123 |
+
echo '<input type="hidden" name="id" value="' . esc_attr($_REQUEST['id']) . '">';
|
124 |
+
echo '<input type="hidden" name="context_type" value="' . esc_attr($context['type']) . '">';
|
125 |
+
$inline_edits = '';
|
126 |
+
if (isset($controls->data['inline_edits'])) {
|
127 |
+
$inline_edits = $controls->data['inline_edits'];
|
128 |
+
}
|
129 |
+
echo '<input type="hidden" name="options[inline_edits]" value="', esc_attr($this->options_encode($inline_edits)), '">';
|
130 |
+
echo "<h2>", esc_html($block["name"]), "</h2>";
|
131 |
+
include $block['dir'] . '/options.php';
|
132 |
+
wp_die();
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Retrieves the presets list (no id in GET) or a specific preset id in GET)
|
137 |
+
*/
|
138 |
+
public function ajax_get_all_presets() {
|
139 |
+
wp_send_json_success($this->get_all_preset());
|
140 |
+
}
|
141 |
+
|
142 |
+
public function ajax_get_preset() {
|
143 |
+
|
144 |
+
if (empty($_REQUEST['id'])) {
|
145 |
+
wp_send_json_error([
|
146 |
+
'msg' => __('Invalid preset ID')
|
147 |
+
]);
|
148 |
+
}
|
149 |
+
|
150 |
+
$preset_id = $_REQUEST['id'];
|
151 |
+
$preset_content = $this->get_preset_content($preset_id);
|
152 |
+
$global_options = $this->get_preset_global_options($preset_id);
|
153 |
+
|
154 |
+
wp_send_json_success([
|
155 |
+
'content' => $preset_content,
|
156 |
+
'globalOptions' => $global_options,
|
157 |
+
]);
|
158 |
+
}
|
159 |
+
|
160 |
+
private function get_preset_content($preset_id) {
|
161 |
+
|
162 |
+
$content = '';
|
163 |
+
|
164 |
+
if ($this->is_a_tnp_default_preset($preset_id)) {
|
165 |
+
|
166 |
+
// Get preset from file
|
167 |
+
$preset = $this->get_preset_from_file($preset_id);
|
168 |
+
|
169 |
+
foreach ($preset->blocks as $item) {
|
170 |
+
ob_start();
|
171 |
+
$this->render_block($item->block, true, (array) $item->options);
|
172 |
+
$content .= trim(ob_get_clean());
|
173 |
+
}
|
174 |
+
} else {
|
175 |
+
|
176 |
+
// Get preset from db
|
177 |
+
$preset_email = $this->get_email(intval($preset_id));
|
178 |
+
$global_options = $this->extract_global_options_from($preset_email);
|
179 |
+
$content = $this->regenerate_email_blocks($preset_email->message, $global_options);
|
180 |
+
}
|
181 |
+
|
182 |
+
return $content;
|
183 |
+
}
|
184 |
+
|
185 |
+
private function get_preset_global_options($preset_id) {
|
186 |
+
|
187 |
+
if ($this->is_a_tnp_default_preset($preset_id)) {
|
188 |
+
return [];
|
189 |
+
}
|
190 |
+
|
191 |
+
// Get preset from db
|
192 |
+
$preset_email = $this->get_email(intval($preset_id));
|
193 |
+
$global_options = $this->extract_global_options_from($preset_email);
|
194 |
+
|
195 |
+
return $global_options;
|
196 |
+
}
|
197 |
+
|
198 |
+
private function extract_global_options_from($email) {
|
199 |
+
$global_options = [];
|
200 |
+
foreach ($email->options as $global_option_name => $global_option) {
|
201 |
+
if (strpos($global_option_name, 'composer_') === 0) {
|
202 |
+
$global_options[str_replace('composer_', '', $global_option_name)] = $global_option;
|
203 |
+
}
|
204 |
+
}
|
205 |
+
|
206 |
+
return $global_options;
|
207 |
+
}
|
208 |
+
|
209 |
+
private function is_a_tnp_default_preset($preset_id) {
|
210 |
+
return in_array($preset_id, self::$PRESETS_LIST);
|
211 |
+
}
|
212 |
+
|
213 |
+
private function get_all_preset() {
|
214 |
+
|
215 |
+
$content = "<div class='tnpc-preset-container'>";
|
216 |
+
|
217 |
+
if ($this->is_normal_context_request()) {
|
218 |
+
$content .= "<div class='tnpc-preset-legacy-themes'><a href='" . $this->get_admin_page_url('theme') . "'>" . __('Looking for legacy themes?', 'newsletter') . "</a></div>";
|
219 |
+
}
|
220 |
+
|
221 |
+
// LOAD USER PRESETS
|
222 |
+
$user_preset_list = $this->get_emails(self::PRESET_EMAIL_TYPE);
|
223 |
+
|
224 |
+
foreach ($user_preset_list as $user_preset) {
|
225 |
+
|
226 |
+
$default_icon_url = NEWSLETTER_URL . "/emails/presets/default-icon.png?ver=2";
|
227 |
+
$preset_name = $user_preset->subject;
|
228 |
+
$delete_preset_text = __('Delete', 'newsletter');
|
229 |
+
$edit_preset_text = __('Edit', 'newsletter');
|
230 |
+
|
231 |
+
// esc_js() assumes the string will be in single quote (arghhh!!!)
|
232 |
+
$onclick_edit = 'tnpc_edit_preset(' . ((int) $user_preset->id) . ', \'' . esc_js($preset_name) . '\', event)';
|
233 |
+
$onclick_delete = 'tnpc_delete_preset(' . ((int) $user_preset->id) . ', \'' . esc_js($preset_name) . '\', event)';
|
234 |
+
$onclick_load = 'tnpc_load_preset(' . ((int) $user_preset->id) . ', \'' . esc_js($preset_name) . '\', event)';
|
235 |
+
|
236 |
+
$content .= "<div class='tnpc-preset' onclick='" . esc_attr($onclick_load) . "'>\n";
|
237 |
+
$content .= "<img src='$default_icon_url' title='" . esc_attr($preset_name) . "' alt='" . esc_attr($preset_name) . "'>\n";
|
238 |
+
$content .= "<span class='tnpc-preset-label'>" . esc_html($user_preset->subject) . "</span>\n";
|
239 |
+
$content .= "<span class='tnpc-delete-preset' onclick='" . esc_attr($onclick_delete) . "' title='" . esc_attr($delete_preset_text) . "'><i class='fas fa-times'></i></span>\n";
|
240 |
+
$content .= "<span class='tnpc-edit-preset' onclick='" . esc_attr($onclick_edit) . "' title='" . esc_attr($edit_preset_text) . "'><i class='fas fa-pencil-alt'></i></span>\n";
|
241 |
+
$content .= "</div>";
|
242 |
+
}
|
243 |
+
|
244 |
+
// LOAD TNP PRESETS
|
245 |
+
foreach (self::$PRESETS_LIST as $id) {
|
246 |
+
$preset = $this->get_preset_from_file($id);
|
247 |
+
$preset_name = esc_html($preset->name);
|
248 |
+
$content .= "<div class='tnpc-preset' onclick='tnpc_load_preset(\"$id\")'>";
|
249 |
+
$content .= "<img src='$preset->icon' title='$preset_name' alt='$preset_name'/>";
|
250 |
+
$content .= "<span class='tnpc-preset-label'>$preset_name</span>";
|
251 |
+
$content .= "</div>";
|
252 |
+
}
|
253 |
+
|
254 |
+
if ($this->is_normal_context_request()) {
|
255 |
+
$content .= $this->get_automated_spot_element();
|
256 |
+
$content .= $this->get_autoresponder_spot_element();
|
257 |
+
$content .= $this->get_raw_html_preset_element();
|
258 |
+
}
|
259 |
+
|
260 |
+
return $content;
|
261 |
+
}
|
262 |
+
|
263 |
+
private function is_normal_context_request() {
|
264 |
+
return empty($_REQUEST['context_type']);
|
265 |
+
}
|
266 |
+
|
267 |
+
private function is_automated_context_request() {
|
268 |
+
return isset($_REQUEST['context_type']) && $_REQUEST['context_type'] === 'automated';
|
269 |
+
}
|
270 |
+
|
271 |
+
private function is_autoresponder_context_request() {
|
272 |
+
return isset($_REQUEST['context_type']) && $_REQUEST['context_type'] === 'autoresponder';
|
273 |
+
}
|
274 |
+
|
275 |
+
private function get_automated_spot_element() {
|
276 |
+
$result = "<div class='tnpc-preset'>";
|
277 |
+
if (class_exists('NewsletterAutomated')) {
|
278 |
+
$result .= "<a href='?page=newsletter_automated_index'>";
|
279 |
+
} else {
|
280 |
+
$result .= "<a href='https://www.thenewsletterplugin.com/automated?utm_source=composer&utm_campaign=plugin&utm_medium=automated'>";
|
281 |
+
}
|
282 |
+
$result .= "<img src='" . plugins_url('newsletter') . "/emails/images/automated.png' title='Automated addon' alt='Automated'/>";
|
283 |
+
$result .= "<span class='tnpc-preset-label'>Daily, weekly and monthly newsletters</span></a>";
|
284 |
+
$result .= "</div>";
|
285 |
+
|
286 |
+
return $result;
|
287 |
+
}
|
288 |
+
|
289 |
+
private function get_autoresponder_spot_element() {
|
290 |
+
$result = "<div class='tnpc-preset'>";
|
291 |
+
if (class_exists('NewsletterAutoresponder')) {
|
292 |
+
$result .= "<a href='?page=newsletter_autoresponder_index'>";
|
293 |
+
} else {
|
294 |
+
$result .= "<a href='https://www.thenewsletterplugin.com/autoresponder?utm_source=composer&utm_campaign=plugin&utm_medium=autoresponder' target='_blank'>";
|
295 |
+
}
|
296 |
+
$result .= "<img src='" . plugins_url('newsletter') . "/emails/images/autoresponder.png' title='Autoresponder addon' alt='Autoresponder'/>";
|
297 |
+
$result .= "<span class='tnpc-preset-label'>Autoresponders</span></a>";
|
298 |
+
$result .= "</div>";
|
299 |
+
|
300 |
+
return $result;
|
301 |
+
}
|
302 |
+
|
303 |
+
private function get_raw_html_preset_element() {
|
304 |
+
|
305 |
+
$result = "<div class='tnpc-preset tnpc-preset-html' onclick='location.href=\"" . wp_nonce_url('admin.php?page=newsletter_emails_new&id=rawhtml', 'newsletter-new') . "\"'>";
|
306 |
+
$result .= "<img src='" . plugins_url('newsletter') . "/emails/images/rawhtml.png' title='RAW HTML' alt='RAW'/>";
|
307 |
+
$result .= "<span class='tnpc-preset-label'>Raw HTML</span>";
|
308 |
+
$result .= "</div>";
|
309 |
+
|
310 |
+
$result .= "<div class='clear'></div>";
|
311 |
+
$result .= "</div>";
|
312 |
+
|
313 |
+
return $result;
|
314 |
+
}
|
315 |
+
|
316 |
+
function has_dynamic_blocks($theme) {
|
317 |
+
preg_match_all('/data-json="(.*?)"/m', $theme, $matches, PREG_PATTERN_ORDER);
|
318 |
+
foreach ($matches[1] as $match) {
|
319 |
+
$a = html_entity_decode($match, ENT_QUOTES, 'UTF-8');
|
320 |
+
$options = $this->options_decode($a);
|
321 |
+
|
322 |
+
$block = $this->get_block($options['block_id']);
|
323 |
+
if (!$block) {
|
324 |
+
continue;
|
325 |
+
}
|
326 |
+
if ($block['type'] == 'dynamic') {
|
327 |
+
return true;
|
328 |
+
}
|
329 |
+
}
|
330 |
+
return false;
|
331 |
+
}
|
332 |
+
|
333 |
+
/**
|
334 |
+
* Regenerates a saved composed email rendering each block. Regeneration is
|
335 |
+
* conditioned (possibly) by the context. The context is usually passed to blocks
|
336 |
+
* so they can act in the right manner.
|
337 |
+
*
|
338 |
+
* $context contains a type and, for automated, the last_run.
|
339 |
+
*
|
340 |
+
* $email can actually be even a string containing the full newsletter HTML code.
|
341 |
+
*
|
342 |
+
* @param TNP_Email $email
|
343 |
+
* @return string
|
344 |
+
*/
|
345 |
+
function regenerate($email, $context = []) {
|
346 |
+
|
347 |
+
$context = array_merge(['last_run' => 0, 'type' => ''], $context);
|
348 |
+
|
349 |
+
$composer = [];
|
350 |
+
foreach ($email->options as $k=>$v) {
|
351 |
+
if (strpos($k, 'composer_') !== 0) continue;
|
352 |
+
$composer[substr($k, 9)] = $v;
|
353 |
+
}
|
354 |
+
|
355 |
+
|
356 |
+
preg_match_all('/data-json="(.*?)"/m', $email->message, $matches, PREG_PATTERN_ORDER);
|
357 |
+
|
358 |
+
$result = '';
|
359 |
+
$subject = '';
|
360 |
+
|
361 |
+
foreach ($matches[1] as $match) {
|
362 |
+
$a = html_entity_decode($match, ENT_QUOTES, 'UTF-8');
|
363 |
+
$options = $this->options_decode($a);
|
364 |
+
|
365 |
+
$block = $this->get_block($options['block_id']);
|
366 |
+
if (!$block) {
|
367 |
+
$this->logger->debug('Unable to load the block ' . $options['block_id']);
|
368 |
+
//continue;
|
369 |
+
}
|
370 |
+
|
371 |
+
ob_start();
|
372 |
+
$out = $this->render_block($options['block_id'], true, $options, $context, $composer);
|
373 |
+
if (is_array($out)) {
|
374 |
+
if ($out['return_empty_message'] || $out['stop']) {
|
375 |
+
return false;
|
376 |
+
}
|
377 |
+
if ($out['skip']) {
|
378 |
+
continue;
|
379 |
+
}
|
380 |
+
if (empty($subject) && !empty($out['subject'])) {
|
381 |
+
$subject = strip_tags($out['subject']);
|
382 |
+
}
|
383 |
+
}
|
384 |
+
$block_html = ob_get_clean();
|
385 |
+
$result .= $block_html;
|
386 |
+
}
|
387 |
+
|
388 |
+
$email->message = TNP_Composer::get_html_open($email) . TNP_Composer::get_main_wrapper_open($email) .
|
389 |
+
$result . TNP_Composer::get_main_wrapper_close($email) . TNP_Composer::get_html_close($email);
|
390 |
+
$email->subject = $subject;
|
391 |
+
return true;
|
392 |
+
}
|
393 |
+
|
394 |
+
function remove_block_data($text) {
|
395 |
+
// TODO: Lavorare!
|
396 |
+
return $text;
|
397 |
+
}
|
398 |
+
|
399 |
+
static function get_outlook_wrapper_open($width = 600) {
|
400 |
+
return '<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" align="center" cellspacing="0" width="' . $width . '"><tr><td width="' . $width . '" style="vertical-align:top;width:' . $width . 'px;"><![endif]-->';
|
401 |
+
}
|
402 |
+
|
403 |
+
static function get_outlook_wrapper_close() {
|
404 |
+
return "<!--[if mso | IE]></td></tr></table><![endif]-->";
|
405 |
+
}
|
406 |
+
|
407 |
+
function hook_safe_style_css($rules) {
|
408 |
+
$rules[] = 'display';
|
409 |
+
return $rules;
|
410 |
+
}
|
411 |
+
|
412 |
+
/**
|
413 |
+
* Renders a block identified by its id, using the block options and adding a wrapper
|
414 |
+
* if required (for the first block rendering).
|
415 |
+
*
|
416 |
+
* @param string $block_id
|
417 |
+
* @param boolean $wrapper
|
418 |
+
* @param array $options
|
419 |
+
* @param array $context
|
420 |
+
* @param array $composer
|
421 |
+
*/
|
422 |
+
function render_block($block_id = null, $wrapper = false, $options = [], $context = [], $composer = []) {
|
423 |
+
static $kses_style_filter = false;
|
424 |
+
include_once NEWSLETTER_INCLUDES_DIR . '/helper.php';
|
425 |
+
|
426 |
+
//Remove 'options_composer_' prefix
|
427 |
+
$composer_defaults = [];
|
428 |
+
foreach (TNP_Composer::get_global_style_defaults() as $global_option_name => $global_option) {
|
429 |
+
$composer_defaults[str_replace('options_composer_', '', $global_option_name)] = $global_option;
|
430 |
+
}
|
431 |
+
$composer = array_merge($composer_defaults, $composer);
|
432 |
+
|
433 |
+
$width = 600;
|
434 |
+
$font_family = 'Helvetica, Arial, sans-serif';
|
435 |
+
|
436 |
+
$global_title_font_family = $composer['title_font_family'];
|
437 |
+
$global_title_font_size = $composer['title_font_size'];
|
438 |
+
$global_title_font_color = $composer['title_font_color'];
|
439 |
+
$global_title_font_weight = $composer['title_font_weight'];
|
440 |
+
|
441 |
+
$global_text_font_family = $composer['text_font_family'];
|
442 |
+
$global_text_font_size = $composer['text_font_size'];
|
443 |
+
$global_text_font_color = $composer['text_font_color'];
|
444 |
+
$global_text_font_weight = $composer['text_font_weight'];
|
445 |
+
|
446 |
+
$global_button_font_family = $composer['button_font_family'];
|
447 |
+
$global_button_font_size = $composer['button_font_size'];
|
448 |
+
$global_button_font_color = $composer['button_font_color'];
|
449 |
+
$global_button_font_weight = $composer['button_font_weight'];
|
450 |
+
$global_button_background_color = $composer['button_background_color'];
|
451 |
+
|
452 |
+
$global_block_background = $composer['block_background'];
|
453 |
+
|
454 |
+
$info = Newsletter::instance()->get_options('info');
|
455 |
+
|
456 |
+
// Just in case...
|
457 |
+
if (!is_array($options)) {
|
458 |
+
$options = array();
|
459 |
+
}
|
460 |
+
|
461 |
+
// This code filters the HTML to remove javascript and unsecure attributes and enable the
|
462 |
+
// "display" rule for CSS which is needed in blocks to force specific "block" or "inline" or "table".
|
463 |
+
add_filter('safe_style_css', [$this, 'hook_safe_style_css'], 9999);
|
464 |
+
$options = wp_kses_post_deep($options);
|
465 |
+
remove_filter('safe_style_css', [$this, 'hook_safe_style_css']);
|
466 |
+
|
467 |
+
$block_options = get_option('newsletter_main');
|
468 |
+
|
469 |
+
$block = $this->get_block($block_id);
|
470 |
+
|
471 |
+
if (!isset($context['type']))
|
472 |
+
$context['type'] = '';
|
473 |
+
|
474 |
+
// Block not found
|
475 |
+
if (!$block) {
|
476 |
+
if ($wrapper) {
|
477 |
+
echo '<table border="0" cellpadding="0" cellspacing="0" align="center" width="100%" style="border-collapse: collapse; width: 100%;" class="tnpc-row tnpc-row-block" data-id="', esc_attr($block_id), '">';
|
478 |
+
echo '<tr>';
|
479 |
+
echo '<td data-options="" bgcolor="#ffffff" align="center" style="padding: 0; font-family: Helvetica, Arial, sans-serif;" class="edit-block">';
|
480 |
+
}
|
481 |
+
echo $this->get_outlook_wrapper_open($width);
|
482 |
+
|
483 |
+
echo '<p>Ops, this block type is not avalable.</p>';
|
484 |
+
|
485 |
+
echo $this->get_outlook_wrapper_close();
|
486 |
+
|
487 |
+
if ($wrapper) {
|
488 |
+
echo '</td></tr></table>';
|
489 |
+
}
|
490 |
+
return;
|
491 |
+
}
|
492 |
+
|
493 |
+
$out = ['subject' => '', 'return_empty_message' => false, 'stop' => false, 'skip' => false];
|
494 |
+
|
495 |
+
$dir = is_rtl() ? 'rtl' : 'ltr';
|
496 |
+
$align_left = is_rtl() ? 'right' : 'left';
|
497 |
+
$align_right = is_rtl() ? 'left' : 'right';
|
498 |
+
|
499 |
+
ob_start();
|
500 |
+
$logger = $this->logger;
|
501 |
+
include $block['dir'] . '/block.php';
|
502 |
+
$content = trim(ob_get_clean());
|
503 |
+
|
504 |
+
if (empty($content)) {
|
505 |
+
return $out;
|
506 |
+
}
|
507 |
+
|
508 |
+
$common_defaults = array(
|
509 |
+
'block_padding_top' => 0,
|
510 |
+
'block_padding_bottom' => 0,
|
511 |
+
'block_padding_right' => 0,
|
512 |
+
'block_padding_left' => 0,
|
513 |
+
'block_background' => '',
|
514 |
+
'block_background_2' => '',
|
515 |
+
'block_width' => 600,
|
516 |
+
'block_align' => 'center'
|
517 |
+
);
|
518 |
+
|
519 |
+
$options = array_merge($common_defaults, $options);
|
520 |
+
|
521 |
+
// Obsolete
|
522 |
+
$content = str_replace('{width}', $width, $content);
|
523 |
+
|
524 |
+
$content = $this->inline_css($content, true);
|
525 |
+
|
526 |
+
// CSS driven by the block
|
527 |
+
// Requited for the server side parsing and rendering
|
528 |
+
$options['block_id'] = $block_id;
|
529 |
+
|
530 |
+
$options['block_padding_top'] = (int) str_replace('px', '', $options['block_padding_top']);
|
531 |
+
$options['block_padding_bottom'] = (int) str_replace('px', '', $options['block_padding_bottom']);
|
532 |
+
$options['block_padding_right'] = (int) str_replace('px', '', $options['block_padding_right']);
|
533 |
+
$options['block_padding_left'] = (int) str_replace('px', '', $options['block_padding_left']);
|
534 |
+
|
535 |
+
$block_background = empty($options['block_background']) ? $global_block_background : $options['block_background'];
|
536 |
+
|
537 |
+
// Internal TD wrapper
|
538 |
+
$style = 'text-align: center; ';
|
539 |
+
$style .= 'width: 100% !important; ';
|
540 |
+
$style .= 'line-height: normal !important; ';
|
541 |
+
$style .= 'letter-spacing: normal; ';
|
542 |
+
$style .= 'padding-top: ' . $options['block_padding_top'] . 'px; ';
|
543 |
+
$style .= 'padding-left: ' . $options['block_padding_left'] . 'px; ';
|
544 |
+
$style .= 'padding-right: ' . $options['block_padding_right'] . 'px; ';
|
545 |
+
$style .= 'padding-bottom: ' . $options['block_padding_bottom'] . 'px; ';
|
546 |
+
$style .= 'background-color: ' . $block_background . ';';
|
547 |
+
|
548 |
+
if (isset($options['block_background_gradient'])) {
|
549 |
+
$style .= 'background: linear-gradient(180deg, ' . $block_background . ' 0%, ' . $options['block_background_2'] . ' 100%);';
|
550 |
+
}
|
551 |
+
|
552 |
+
$data = $this->options_encode($options);
|
553 |
+
// First time block creation wrapper
|
554 |
+
if ($wrapper) {
|
555 |
+
echo '<table border="0" cellpadding="0" cellspacing="0" align="center" width="100%" style="border-collapse: collapse; width: 100%;" class="tnpc-row tnpc-row-block" data-id="', esc_attr($block_id), '">', "\n";
|
556 |
+
echo "<tr>";
|
557 |
+
echo '<td align="center" style="padding: 0;" class="edit-block">', "\n";
|
558 |
+
}
|
559 |
+
|
560 |
+
// Container that fixes the width and makes the block responsive
|
561 |
+
echo $this->get_outlook_wrapper_open($options['block_width']);
|
562 |
+
|
563 |
+
echo '<table type="options" data-json="', esc_attr($data), '" class="tnpc-block-content" border="0" cellpadding="0" align="center" cellspacing="0" width="100%" style="width: 100%!important; max-width: ', $options['block_width'], 'px!important">', "\n";
|
564 |
+
echo "<tr>";
|
565 |
+
echo '<td align="', esc_attr($options['block_align']), '" style="', esc_attr($style), '" bgcolor="', esc_attr($block_background), '" width="100%">';
|
566 |
+
|
567 |
+
//echo "<!-- block generated content -->\n";
|
568 |
+
echo trim($content);
|
569 |
+
//echo "\n<!-- /block generated content -->\n";
|
570 |
+
|
571 |
+
echo "</td></tr></table>";
|
572 |
+
echo $this->get_outlook_wrapper_close();
|
573 |
+
|
574 |
+
// First time block creation wrapper
|
575 |
+
if ($wrapper) {
|
576 |
+
echo "</td></tr></table>";
|
577 |
+
}
|
578 |
+
|
579 |
+
return $out;
|
580 |
+
}
|
581 |
+
|
582 |
+
/**
|
583 |
+
* Ajax call to render a block with a new set of options after the settings popup
|
584 |
+
* has been saved.
|
585 |
+
*
|
586 |
+
* @param type $block_id
|
587 |
+
* @param type $wrapper
|
588 |
+
*/
|
589 |
+
function tnpc_render_callback() {
|
590 |
+
if (!check_ajax_referer('save')) {
|
591 |
+
$this->dienow('Expired request');
|
592 |
+
}
|
593 |
+
|
594 |
+
$block_id = $_POST['id'];
|
595 |
+
$wrapper = isset($_POST['full']);
|
596 |
+
$options = $this->restore_options_from_request();
|
597 |
+
|
598 |
+
$this->render_block($block_id, $wrapper, $options, [], $_POST['composer']);
|
599 |
+
wp_die();
|
600 |
+
}
|
601 |
+
|
602 |
+
function hook_wp_ajax_tnpc_regenerate_email() {
|
603 |
+
|
604 |
+
$content = stripslashes($_POST['content']);
|
605 |
+
$global_options = $_POST['composer'];
|
606 |
+
|
607 |
+
$regenerated_content = $this->regenerate_email_blocks($content, $global_options);
|
608 |
+
|
609 |
+
wp_send_json_success([
|
610 |
+
'content' => $regenerated_content,
|
611 |
+
'message' => __('Successfully updated', 'newsletter')
|
612 |
+
]);
|
613 |
+
}
|
614 |
+
|
615 |
+
private function regenerate_email_blocks($content, $global_options) {
|
616 |
+
|
617 |
+
$raw_block_options = $this->extract_encoded_blocks_options($content);
|
618 |
+
|
619 |
+
$regenerated_content = '';
|
620 |
+
|
621 |
+
foreach ($raw_block_options as $raw_block_option) {
|
622 |
+
|
623 |
+
/* $a = html_entity_decode( $raw_block_option, ENT_QUOTES, 'UTF-8' );
|
624 |
+
$block_options = $this->options_decode( $a ); */
|
625 |
+
|
626 |
+
$block_options = $this->options_decode($raw_block_option);
|
627 |
+
|
628 |
+
$block = $this->get_block($block_options['block_id']);
|
629 |
+
if (!$block) {
|
630 |
+
$this->logger->debug('Unable to load the block ' . $block_options['block_id']);
|
631 |
+
}
|
632 |
+
|
633 |
+
ob_start();
|
634 |
+
$this->render_block($block_options['block_id'], true, $block_options, [], $global_options);
|
635 |
+
$block_html = ob_get_clean();
|
636 |
+
|
637 |
+
$regenerated_content .= $block_html;
|
638 |
+
}
|
639 |
+
|
640 |
+
return $regenerated_content;
|
641 |
+
}
|
642 |
+
|
643 |
+
/**
|
644 |
+
* @param string $html_email_content Email html content
|
645 |
+
*
|
646 |
+
* @return string[] Encoded options of email blocks
|
647 |
+
*/
|
648 |
+
private function extract_encoded_blocks_options($html_email_content) {
|
649 |
+
|
650 |
+
preg_match_all('/data-json="(.*?)"/m', $html_email_content, $raw_block_options, PREG_PATTERN_ORDER);
|
651 |
+
|
652 |
+
return $raw_block_options[1];
|
653 |
+
}
|
654 |
+
|
655 |
+
function tnpc_preview_callback() {
|
656 |
+
$email = Newsletter::instance()->get_email($_REQUEST['id'], ARRAY_A);
|
657 |
+
|
658 |
+
if (empty($email)) {
|
659 |
+
echo 'Wrong email identifier';
|
660 |
+
return;
|
661 |
+
}
|
662 |
+
|
663 |
+
echo $email['message'];
|
664 |
+
|
665 |
+
wp_die();
|
666 |
+
}
|
667 |
+
|
668 |
+
function tnpc_css_callback() {
|
669 |
+
include NEWSLETTER_DIR . '/emails/tnp-composer/css/newsletter.css';
|
670 |
+
wp_die();
|
671 |
+
}
|
672 |
+
|
673 |
+
/** Returns the correct admin page to edit the newsletter with the correct editor. */
|
674 |
+
function get_editor_url($email_id, $editor_type) {
|
675 |
+
switch ($editor_type) {
|
676 |
+
case NewsletterEmails::EDITOR_COMPOSER:
|
677 |
+
return admin_url("admin.php") . '?page=newsletter_emails_composer&id=' . $email_id;
|
678 |
+
case NewsletterEmails::EDITOR_HTML:
|
679 |
+
return admin_url("admin.php") . '?page=newsletter_emails_editorhtml&id=' . $email_id;
|
680 |
+
case NewsletterEmails::EDITOR_TINYMCE:
|
681 |
+
return admin_url("admin.php") . '?page=newsletter_emails_editortinymce&id=' . $email_id;
|
682 |
+
}
|
683 |
+
}
|
684 |
+
|
685 |
+
/**
|
686 |
+
* Returns the button linked to the correct "edit" page for the passed newsletter. The edit page can be an editor
|
687 |
+
* or the targeting page (it depends on newsletter status).
|
688 |
+
*
|
689 |
+
* @param TNP_Email $email
|
690 |
+
*/
|
691 |
+
function get_edit_button($email, $only_icon = false) {
|
692 |
+
|
693 |
+
$editor_type = $this->get_editor_type($email);
|
694 |
+
if ($email->status == 'new') {
|
695 |
+
$edit_url = $this->get_editor_url($email->id, $editor_type);
|
696 |
+
} else {
|
697 |
+
$edit_url = 'admin.php?page=newsletter_emails_edit&id=' . $email->id;
|
698 |
+
}
|
699 |
+
switch ($editor_type) {
|
700 |
+
case NewsletterEmails::EDITOR_COMPOSER:
|
701 |
+
$icon_class = 'th-large';
|
702 |
+
break;
|
703 |
+
case NewsletterEmails::EDITOR_HTML:
|
704 |
+
$icon_class = 'code';
|
705 |
+
break;
|
706 |
+
default:
|
707 |
+
$icon_class = 'edit';
|
708 |
+
break;
|
709 |
+
}
|
710 |
+
if ($only_icon) {
|
711 |
+
return '<a class="button-primary" href="' . $edit_url . '" title="' . esc_attr__('Edit', 'newsletter') . '">' .
|
712 |
+
'<i class="fas fa-' . $icon_class . '"></i></a>';
|
713 |
+
} else {
|
714 |
+
return '<a class="button-primary" href="' . $edit_url . '" title="' . esc_attr__('Edit', 'newsletter') . '">' .
|
715 |
+
'<i class="fas fa-' . $icon_class . '"></i> ' . __('Edit', 'newsletter') . '</a>';
|
716 |
+
}
|
717 |
+
}
|
718 |
+
|
719 |
+
/** Returns the correct editor type for the provided newsletter. Contains backward compatibility code. */
|
720 |
+
function get_editor_type($email) {
|
721 |
+
$email = (object) $email;
|
722 |
+
$editor_type = $email->editor;
|
723 |
+
|
724 |
+
// Backward compatibility
|
725 |
+
$email_options = maybe_unserialize($email->options);
|
726 |
+
if (isset($email_options['composer'])) {
|
727 |
+
$editor_type = NewsletterEmails::EDITOR_COMPOSER;
|
728 |
+
}
|
729 |
+
// End backward compatibility
|
730 |
+
|
731 |
+
return $editor_type;
|
732 |
+
}
|
733 |
+
|
734 |
+
/**
|
735 |
+
*
|
736 |
+
* @param type $action
|
737 |
+
* @param type $user
|
738 |
+
* @param type $email
|
739 |
+
* @return type
|
740 |
+
* @global wpdb $wpdb
|
741 |
+
*/
|
742 |
+
function hook_newsletter_action($action, $user, $email) {
|
743 |
+
global $wpdb;
|
744 |
+
|
745 |
+
switch ($action) {
|
746 |
+
case 'v':
|
747 |
+
case 'view':
|
748 |
+
$id = $_GET['id'];
|
749 |
+
if ($id == 'last') {
|
750 |
+
$email = $wpdb->get_row("select * from " . NEWSLETTER_EMAILS_TABLE . " where private=0 and type='message' and status='sent' order by send_on desc limit 1");
|
751 |
+
} else {
|
752 |
+
$email = $this->get_email($_GET['id']);
|
753 |
+
}
|
754 |
+
if (empty($email)) {
|
755 |
+
header("HTTP/1.0 404 Not Found");
|
756 |
+
die('Email not found');
|
757 |
+
}
|
758 |
+
|
759 |
+
if (!Newsletter::instance()->is_allowed()) {
|
760 |
+
|
761 |
+
if ($email->status == 'new') {
|
762 |
+
header("HTTP/1.0 404 Not Found");
|
763 |
+
die('Not sent yet');
|
764 |
+
}
|
765 |
+
|
766 |
+
if ($email->private == 1) {
|
767 |
+
if (!$user) {
|
768 |
+
header("HTTP/1.0 404 Not Found");
|
769 |
+
die('No available for online view');
|
770 |
+
}
|
771 |
+
$sent = $wpdb->get_row($wpdb->prepare("select * from " . NEWSLETTER_SENT_TABLE . " where email_id=%d and user_id=%d limit 1", $email->id, $user->id));
|
772 |
+
if (!$sent) {
|
773 |
+
header("HTTP/1.0 404 Not Found");
|
774 |
+
die('No available for online view');
|
775 |
+
}
|
776 |
+
}
|
777 |
+
}
|
778 |
+
|
779 |
+
|
780 |
+
header('Content-Type: text/html;charset=UTF-8');
|
781 |
+
header('X-Robots-Tag: noindex,nofollow,noarchive');
|
782 |
+
header('Cache-Control: no-cache,no-store,private');
|
783 |
+
|
784 |
+
echo $this->replace($email->message, $user, $email);
|
785 |
+
|
786 |
+
die();
|
787 |
+
break;
|
788 |
+
|
789 |
+
case 'emails-css':
|
790 |
+
$email_id = (int) $_GET['id'];
|
791 |
+
|
792 |
+
$body = Newsletter::instance()->get_email_field($email_id, 'message');
|
793 |
+
|
794 |
+
$x = strpos($body, '<style');
|
795 |
+
if ($x === false)
|
796 |
+
return;
|
797 |
+
|
798 |
+
$x = strpos($body, '>', $x);
|
799 |
+
$y = strpos($body, '</style>');
|
800 |
+
|
801 |
+
header('Content-Type: text/css;charset=UTF-8');
|
802 |
+
|
803 |
+
echo substr($body, $x + 1, $y - $x - 1);
|
804 |
+
|
805 |
+
die();
|
806 |
+
break;
|
807 |
+
|
808 |
+
case 'emails-composer-css':
|
809 |
+
header('Cache: no-cache');
|
810 |
+
header('Content-Type: text/css');
|
811 |
+
echo $this->get_composer_css();
|
812 |
+
die();
|
813 |
+
break;
|
814 |
+
|
815 |
+
case 'emails-preview':
|
816 |
+
if (!Newsletter::instance()->is_allowed()) {
|
817 |
+
die('Not enough privileges');
|
818 |
+
}
|
819 |
+
|
820 |
+
if (!check_admin_referer('view')) {
|
821 |
+
die();
|
822 |
+
}
|
823 |
+
|
824 |
+
$theme_id = $_GET['id'];
|
825 |
+
$theme = $this->themes->get_theme($theme_id);
|
826 |
+
|
827 |
+
// Used by theme code
|
828 |
+
$theme_options = $this->themes->get_options($theme_id);
|
829 |
+
|
830 |
+
$theme_url = $theme['url'];
|
831 |
+
|
832 |
+
header('Content-Type: text/html;charset=UTF-8');
|
833 |
+
|
834 |
+
include $theme['dir'] . '/theme.php';
|
835 |
+
|
836 |
+
die();
|
837 |
+
break;
|
838 |
+
|
839 |
+
case 'emails-preview-text':
|
840 |
+
header('Content-Type: text/plain;charset=UTF-8');
|
841 |
+
if (!Newsletter::instance()->is_allowed()) {
|
842 |
+
die('Not enough privileges');
|
843 |
+
}
|
844 |
+
|
845 |
+
if (!check_admin_referer('view')) {
|
846 |
+
die();
|
847 |
+
}
|
848 |
+
|
849 |
+
// Used by theme code
|
850 |
+
$theme_options = $this->get_current_theme_options();
|
851 |
+
|
852 |
+
$file = include $theme['dir'] . '/theme-text.php';
|
853 |
+
|
854 |
+
if (is_file($file)) {
|
855 |
+
include $file;
|
856 |
+
}
|
857 |
+
|
858 |
+
die();
|
859 |
+
break;
|
860 |
+
|
861 |
+
case 'emails-create':
|
862 |
+
// Newsletter from themes are created on frontend context because sometime WP themes change the way the content,
|
863 |
+
// excerpt, thumbnail are extracted.
|
864 |
+
if (!Newsletter::instance()->is_allowed()) {
|
865 |
+
die('Not enough privileges');
|
866 |
+
}
|
867 |
+
|
868 |
+
require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
|
869 |
+
$controls = new NewsletterControls();
|
870 |
+
|
871 |
+
if (!$controls->is_action('create')) {
|
872 |
+
die('Wrong call');
|
873 |
+
}
|
874 |
+
|
875 |
+
$theme_id = $controls->data['id'];
|
876 |
+
$theme = $this->themes->get_theme($theme_id);
|
877 |
+
|
878 |
+
if (!$theme) {
|
879 |
+
die('invalid theme');
|
880 |
+
}
|
881 |
+
|
882 |
+
$this->themes->save_options($theme_id, $controls->data);
|
883 |
+
|
884 |
+
$email = array();
|
885 |
+
$email['status'] = 'new';
|
886 |
+
$email['subject'] = ''; //__('Here the email subject', 'newsletter');
|
887 |
+
$email['track'] = Newsletter::instance()->options['track'];
|
888 |
+
$email['send_on'] = time();
|
889 |
+
$email['editor'] = NewsletterEmails::EDITOR_TINYMCE;
|
890 |
+
$email['type'] = 'message';
|
891 |
+
|
892 |
+
$theme_options = $this->themes->get_options($theme_id);
|
893 |
+
|
894 |
+
$theme_url = $theme['url'];
|
895 |
+
$theme_subject = '';
|
896 |
+
|
897 |
+
ob_start();
|
898 |
+
include $theme['dir'] . '/theme.php';
|
899 |
+
$email['message'] = ob_get_clean();
|
900 |
+
|
901 |
+
if (!empty($theme_subject)) {
|
902 |
+
$email['subject'] = $theme_subject;
|
903 |
+
}
|
904 |
+
|
905 |
+
if (file_exists($theme['dir'] . '/theme-text.php')) {
|
906 |
+
ob_start();
|
907 |
+
include $theme['dir'] . '/theme-text.php';
|
908 |
+
$email['message_text'] = ob_get_clean();
|
909 |
+
} else {
|
910 |
+
$email['message_text'] = 'You need a modern email client to read this email. Read it online: {email_url}.';
|
911 |
+
}
|
912 |
+
|
913 |
+
$email = $this->save_email($email);
|
914 |
+
|
915 |
+
$edit_url = $this->get_editor_url($email->id, $email->editor);
|
916 |
+
|
917 |
+
header('Location: ' . $edit_url);
|
918 |
+
|
919 |
+
die();
|
920 |
+
break;
|
921 |
+
}
|
922 |
+
}
|
923 |
+
|
924 |
+
function admin_menu() {
|
925 |
+
$this->add_menu_page('index', 'Newsletters');
|
926 |
+
$this->add_admin_page('list', 'Email List');
|
927 |
+
$this->add_admin_page('new', 'Email New');
|
928 |
+
$this->add_admin_page('edit', 'Email Edit');
|
929 |
+
$this->add_admin_page('theme', 'Email Themes');
|
930 |
+
$this->add_admin_page('composer', 'The Composer');
|
931 |
+
$this->add_admin_page('editorhtml', 'HTML Editor');
|
932 |
+
$this->add_admin_page('editortinymce', 'TinyMCE Editor');
|
933 |
+
}
|
934 |
+
|
935 |
+
/**
|
936 |
+
* Builds a block data structure starting from the folder containing the block
|
937 |
+
* files.
|
938 |
+
*
|
939 |
+
* @param string $dir
|
940 |
+
* @return array | WP_Error
|
941 |
+
*/
|
942 |
+
function build_block($dir) {
|
943 |
+
$dir = realpath($dir);
|
944 |
+
$dir = wp_normalize_path($dir);
|
945 |
+
$full_file = $dir . '/block.php';
|
946 |
+
if (!is_file($full_file)) {
|
947 |
+
return new WP_Error('1', 'Missing block.php file in ' . $dir);
|
948 |
+
}
|
949 |
+
|
950 |
+
$wp_content_dir = wp_normalize_path(realpath(WP_CONTENT_DIR));
|
951 |
+
|
952 |
+
$relative_dir = substr($dir, strlen($wp_content_dir));
|
953 |
+
$file = basename($dir);
|
954 |
+
|
955 |
+
$data = get_file_data($full_file, ['name' => 'Name', 'section' => 'Section', 'description' => 'Description', 'type' => 'Type']);
|
956 |
+
$defaults = ['section' => 'content', 'name' => ucfirst($file), 'descritpion' => '', 'icon' => plugins_url('newsletter') . '/admin/images/block-icon.png'];
|
957 |
+
$data = array_merge($defaults, $data);
|
958 |
+
|
959 |
+
if (is_file($dir . '/icon.png')) {
|
960 |
+
$data['icon'] = content_url($relative_dir . '/icon.png');
|
961 |
+
}
|
962 |
+
|
963 |
+
$data['id'] = sanitize_key($file);
|
964 |
+
|
965 |
+
// Absolute path of the block files
|
966 |
+
$data['dir'] = $dir;
|
967 |
+
$data['url'] = content_url($relative_dir);
|
968 |
+
|
969 |
+
return $data;
|
970 |
+
}
|
971 |
+
|
972 |
+
/**
|
973 |
+
*
|
974 |
+
* @param type $dir
|
975 |
+
* @return type
|
976 |
+
*/
|
977 |
+
function scan_blocks_dir($dir) {
|
978 |
+
$dir = realpath($dir);
|
979 |
+
if (!$dir) {
|
980 |
+
return [];
|
981 |
+
}
|
982 |
+
$dir = wp_normalize_path($dir);
|
983 |
+
|
984 |
+
$list = [];
|
985 |
+
$handle = opendir($dir);
|
986 |
+
while ($file = readdir($handle)) {
|
987 |
+
|
988 |
+
$data = $this->build_block($dir . '/' . $file);
|
989 |
+
|
990 |
+
if (is_wp_error($data)) {
|
991 |
+
$this->logger->error($data);
|
992 |
+
continue;
|
993 |
+
}
|
994 |
+
$list[$data['id']] = $data;
|
995 |
+
}
|
996 |
+
closedir($handle);
|
997 |
+
return $list;
|
998 |
+
}
|
999 |
+
|
1000 |
+
/**
|
1001 |
+
* Array of arrays with every registered block and legacy block converted to the new
|
1002 |
+
* format.
|
1003 |
+
*
|
1004 |
+
* @return array
|
1005 |
+
*/
|
1006 |
+
function get_blocks() {
|
1007 |
+
|
1008 |
+
if (!is_null($this->blocks)) {
|
1009 |
+
return $this->blocks;
|
1010 |
+
}
|
1011 |
+
|
1012 |
+
$this->blocks = $this->scan_blocks_dir(__DIR__ . '/blocks');
|
1013 |
+
|
1014 |
+
$extended = $this->scan_blocks_dir(WP_CONTENT_DIR . '/extensions/newsletter/blocks');
|
1015 |
+
|
1016 |
+
$this->blocks = array_merge($extended, $this->blocks);
|
1017 |
+
|
1018 |
+
$dirs = apply_filters('newsletter_blocks_dir', array());
|
1019 |
+
|
1020 |
+
//$this->logger->debug('Block dirs:');
|
1021 |
+
//$this->logger->debug($dirs);
|
1022 |
+
|
1023 |
+
foreach ($dirs as $dir) {
|
1024 |
+
$list = $this->scan_blocks_dir($dir);
|
1025 |
+
$this->blocks = array_merge($list, $this->blocks);
|
1026 |
+
}
|
1027 |
+
|
1028 |
+
do_action('newsletter_register_blocks');
|
1029 |
+
|
1030 |
+
foreach (TNP_Composer::$block_dirs as $dir) {
|
1031 |
+
$block = $this->build_block($dir);
|
1032 |
+
if (is_wp_error($block)) {
|
1033 |
+
$this->logger->error($block);
|
1034 |
+
continue;
|
1035 |
+
}
|
1036 |
+
if (!isset($this->blocks[$block['id']])) {
|
1037 |
+
$this->blocks[$block['id']] = $block;
|
1038 |
+
} else {
|
1039 |
+
$this->logger->error('The block "' . $block['id'] . '" has already been registered');
|
1040 |
+
}
|
1041 |
+
}
|
1042 |
+
|
1043 |
+
$this->blocks = array_reverse($this->blocks);
|
1044 |
+
return $this->blocks;
|
1045 |
+
}
|
1046 |
+
|
1047 |
+
/**
|
1048 |
+
* Return a single block (associative array) checking for legacy ID as well.
|
1049 |
+
*
|
1050 |
+
* @param string $id
|
1051 |
+
* @return array
|
1052 |
+
*/
|
1053 |
+
function get_block($id) {
|
1054 |
+
switch ($id) {
|
1055 |
+
case 'content-03-text.block':
|
1056 |
+
$id = 'text';
|
1057 |
+
break;
|
1058 |
+
case 'footer-03-social.block':
|
1059 |
+
$id = 'social';
|
1060 |
+
break;
|
1061 |
+
case 'footer-02-canspam.block':
|
1062 |
+
$id = 'canspam';
|
1063 |
+
break;
|
1064 |
+
case 'content-05-image.block':
|
1065 |
+
$id = 'image';
|
1066 |
+
break;
|
1067 |
+
case 'header-01-header.block':
|
1068 |
+
$id = 'header';
|
1069 |
+
break;
|
1070 |
+
case 'footer-01-footer.block':
|
1071 |
+
$id = 'footer';
|
1072 |
+
break;
|
1073 |
+
case 'content-02-heading.block':
|
1074 |
+
$id = 'heading';
|
1075 |
+
break;
|
1076 |
+
case 'content-07-twocols.block':
|
1077 |
+
case 'content-06-posts.block':
|
1078 |
+
$id = 'posts';
|
1079 |
+
break;
|
1080 |
+
case 'content-04-cta.block':
|
1081 |
+
$id = 'cta';
|
1082 |
+
break;
|
1083 |
+
case 'content-01-hero.block':
|
1084 |
+
$id = 'hero';
|
1085 |
+
break;
|
1086 |
+
// case 'content-02-heading.block': $id = '/plugins/newsletter/emails/blocks/heading';
|
1087 |
+
// break;
|
1088 |
+
}
|
1089 |
+
|
1090 |
+
// Conversion for old full path ID
|
1091 |
+
$id = sanitize_key(basename($id));
|
1092 |
+
|
1093 |
+
// TODO: Correct id for compatibility
|
1094 |
+
$blocks = $this->get_blocks();
|
1095 |
+
if (!isset($blocks[$id])) {
|
1096 |
+
return null;
|
1097 |
+
}
|
1098 |
+
return $blocks[$id];
|
1099 |
+
}
|
1100 |
+
|
1101 |
+
function scan_presets_dir($dir = null) {
|
1102 |
+
|
1103 |
+
if (is_null($dir)) {
|
1104 |
+
$dir = __DIR__ . '/presets';
|
1105 |
+
}
|
1106 |
+
|
1107 |
+
if (!is_dir($dir)) {
|
1108 |
+
return array();
|
1109 |
+
}
|
1110 |
+
|
1111 |
+
$handle = opendir($dir);
|
1112 |
+
$list = array();
|
1113 |
+
$relative_dir = substr($dir, strlen(WP_CONTENT_DIR));
|
1114 |
+
while ($file = readdir($handle)) {
|
1115 |
+
|
1116 |
+
if ($file == '.' || $file == '..')
|
1117 |
+
continue;
|
1118 |
+
|
1119 |
+
// The block unique key, we should find out how to build it, maybe an hash of the (relative) dir?
|
1120 |
+
$preset_id = sanitize_key($file);
|
1121 |
+
|
1122 |
+
$full_file = $dir . '/' . $file . '/preset.json';
|
1123 |
+
|
1124 |
+
if (!is_file($full_file)) {
|
1125 |
+
continue;
|
1126 |
+
}
|
1127 |
+
|
1128 |
+
$icon = content_url($relative_dir . '/' . $file . '/icon.png');
|
1129 |
+
|
1130 |
+
$list[$preset_id] = $icon;
|
1131 |
+
}
|
1132 |
+
closedir($handle);
|
1133 |
+
return $list;
|
1134 |
+
}
|
1135 |
+
|
1136 |
+
function get_preset_from_file($id, $dir = null) {
|
1137 |
+
|
1138 |
+
if (is_null($dir)) {
|
1139 |
+
$dir = __DIR__ . '/presets';
|
1140 |
+
}
|
1141 |
+
|
1142 |
+
$id = $this->sanitize_file_name($id);
|
1143 |
+
|
1144 |
+
if (!is_dir($dir . '/' . $id) || !in_array($id, self::$PRESETS_LIST)) {
|
1145 |
+
return array();
|
1146 |
+
}
|
1147 |
+
|
1148 |
+
$json_content = file_get_contents("$dir/$id/preset.json");
|
1149 |
+
$json_content = str_replace("{placeholder_base_url}", plugins_url('newsletter') . '/emails/presets', $json_content);
|
1150 |
+
$json = json_decode($json_content);
|
1151 |
+
$json->icon = NEWSLETTER_URL . "/emails/presets/$id/icon.png?ver=2";
|
1152 |
+
|
1153 |
+
return $json;
|
1154 |
+
}
|
1155 |
+
|
1156 |
+
function get_composer_css() {
|
1157 |
+
$css = file_get_contents(__DIR__ . '/tnp-composer/css/newsletter.css');
|
1158 |
+
$blocks = $this->get_blocks();
|
1159 |
+
foreach ($blocks as $block) {
|
1160 |
+
if (!file_exists($block['dir'] . '/style.css')) {
|
1161 |
+
continue;
|
1162 |
+
}
|
1163 |
+
$css .= "\n\n";
|
1164 |
+
$css .= "/* " . $block['name'] . " */\n";
|
1165 |
+
$css .= file_get_contents($block['dir'] . '/style.css');
|
1166 |
+
}
|
1167 |
+
return $css;
|
1168 |
+
}
|
1169 |
+
|
1170 |
+
function get_composer_backend_css() {
|
1171 |
+
$css = file_get_contents(__DIR__ . '/tnp-composer/css/backend.css');
|
1172 |
+
$css .= "\n\n";
|
1173 |
+
$css .= $this->get_composer_css();
|
1174 |
+
return $css;
|
1175 |
+
}
|
1176 |
+
|
1177 |
+
/**
|
1178 |
+
* Send an email to the test subscribers.
|
1179 |
+
*
|
1180 |
+
* @param TNP_Email $email Could be any object with the TNP_Email attributes
|
1181 |
+
* @param NewsletterControls $controls
|
1182 |
+
*/
|
1183 |
+
function send_test_email($email, $controls) {
|
1184 |
+
if (!$email) {
|
1185 |
+
$controls->errors = __('Newsletter should be saved before send a test', 'newsletter');
|
1186 |
+
return;
|
1187 |
+
}
|
1188 |
+
|
1189 |
+
$original_subject = $email->subject;
|
1190 |
+
$this->set_test_subject_to($email);
|
1191 |
+
|
1192 |
+
$users = NewsletterUsers::instance()->get_test_users();
|
1193 |
+
if (count($users) == 0) {
|
1194 |
+
$controls->errors = '' . __('There are no test subscribers to send to', 'newsletter') .
|
1195 |
+
'. <a href="https://www.thenewsletterplugin.com/plugins/newsletter/subscribers-module#test" target="_blank"><strong>' .
|
1196 |
+
__('Read more', 'newsletter') . '</strong></a>.';
|
1197 |
+
} else {
|
1198 |
+
$r = Newsletter::instance()->send($email, $users, true);
|
1199 |
+
$emails = array();
|
1200 |
+
foreach ($users as $user) {
|
1201 |
+
$emails[] = '<a href="admin.php?page=newsletter_users_edit&id=' . $user->id . '" target="_blank">' . $user->email . '</a>';
|
1202 |
+
}
|
1203 |
+
if (is_wp_error($r)) {
|
1204 |
+
$controls->errors = 'Something went wrong. Check the error logs on status page.<br>';
|
1205 |
+
$controls->errors .= __('Test subscribers:', 'newsletter');
|
1206 |
+
$controls->errors .= ' ' . implode(', ', $emails);
|
1207 |
+
$controls->errors .= '<br>';
|
1208 |
+
$controls->errors .= '<strong>' . esc_html($r->get_error_message()) . '</strong><br>';
|
1209 |
+
$controls->errors .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
|
1210 |
+
} else {
|
1211 |
+
$controls->messages = __('Test subscribers:', 'newsletter');
|
1212 |
+
|
1213 |
+
$controls->messages .= ' ' . implode(', ', $emails);
|
1214 |
+
$controls->messages .= '.<br>';
|
1215 |
+
$controls->messages .= '<a href="https://www.thenewsletterplugin.com/documentation/subscribers#test" target="_blank"><strong>' .
|
1216 |
+
__('Read more about test subscribers', 'newsletter') . '</strong></a>.<br>';
|
1217 |
+
$controls->messages .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
|
1218 |
+
}
|
1219 |
+
}
|
1220 |
+
$email->subject = $original_subject;
|
1221 |
+
}
|
1222 |
+
|
1223 |
+
/**
|
1224 |
+
* Send an email to the test subscribers.
|
1225 |
+
*
|
1226 |
+
* @param TNP_Email $email Could be any object with the TNP_Email attributes
|
1227 |
+
* @param string $email_address
|
1228 |
+
*
|
1229 |
+
* @throws Exception
|
1230 |
+
*/
|
1231 |
+
function send_test_newsletter_to_email_address($email, $email_address) {
|
1232 |
+
|
1233 |
+
if (!$email) {
|
1234 |
+
throw new Exception(__('Newsletter should be saved before send a test', 'newsletter'));
|
1235 |
+
}
|
1236 |
+
|
1237 |
+
$this->set_test_subject_to($email);
|
1238 |
+
|
1239 |
+
$dummy_subscriber = $this->make_dummy_subscriber();
|
1240 |
+
$dummy_subscriber->email = $email_address;
|
1241 |
+
|
1242 |
+
$result = Newsletter::instance()->send($email, [$dummy_subscriber], true);
|
1243 |
+
|
1244 |
+
$email = '<a href="admin.php?page=newsletter_users_edit&id=' . $dummy_subscriber->id . '" target="_blank">' . $dummy_subscriber->email . '</a>';
|
1245 |
+
|
1246 |
+
if (is_wp_error($result)) {
|
1247 |
+
$error_message = 'Something went wrong. Check the error logs on status page.<br>';
|
1248 |
+
$error_message .= __('Test subscribers:', 'newsletter');
|
1249 |
+
$error_message .= ' ' . $email;
|
1250 |
+
$error_message .= '<br>';
|
1251 |
+
$error_message .= '<strong>' . esc_html($result->get_error_message()) . '</strong><br>';
|
1252 |
+
$error_message .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
|
1253 |
+
throw new Exception($error_message);
|
1254 |
+
}
|
1255 |
+
|
1256 |
+
$messages = __('Test subscribers:', 'newsletter');
|
1257 |
+
|
1258 |
+
$messages .= ' ' . $email;
|
1259 |
+
$messages .= '.<br>';
|
1260 |
+
$messages .= '<a href="https://www.thenewsletterplugin.com/documentation/subscribers#test" target="_blank"><strong>' .
|
1261 |
+
__('Read more about test subscribers', 'newsletter') . '</strong></a>.<br>';
|
1262 |
+
$messages .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
|
1263 |
+
|
1264 |
+
return $messages;
|
1265 |
+
}
|
1266 |
+
|
1267 |
+
private function set_test_subject_to($email) {
|
1268 |
+
if ($email->subject == '') {
|
1269 |
+
$email->subject = '[TEST] Dummy subject, it was empty (remember to set it)';
|
1270 |
+
} else {
|
1271 |
+
$email->subject = $email->subject . ' (TEST)';
|
1272 |
+
}
|
1273 |
+
}
|
1274 |
+
|
1275 |
+
private function make_dummy_subscriber() {
|
1276 |
+
$dummy_user = new TNP_User();
|
1277 |
+
$dummy_user->id = 0;
|
1278 |
+
$dummy_user->email = 'john.doe@example.org';
|
1279 |
+
$dummy_user->name = 'John';
|
1280 |
+
$dummy_user->surname = 'Doe';
|
1281 |
+
$dummy_user->sex = 'n';
|
1282 |
+
$dummy_user->language = '';
|
1283 |
+
$dummy_user->ip = '';
|
1284 |
+
|
1285 |
+
for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
|
1286 |
+
$profile_key = "profile_$i";
|
1287 |
+
$dummy_user->$profile_key = '';
|
1288 |
+
}
|
1289 |
+
|
1290 |
+
return $dummy_user;
|
1291 |
+
}
|
1292 |
+
|
1293 |
+
function restore_options_from_request() {
|
1294 |
+
|
1295 |
+
require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
|
1296 |
+
$controls = new NewsletterControls();
|
1297 |
+
$options = $controls->data;
|
1298 |
+
|
1299 |
+
if (isset($_POST['options']) && is_array($_POST['options'])) {
|
1300 |
+
// Get all block options
|
1301 |
+
//$options = stripslashes_deep($_POST['options']);
|
1302 |
+
// Deserialize inline edits when
|
1303 |
+
// render is preformed on saving block options
|
1304 |
+
if (isset($options['inline_edits']) && !is_array($options['inline_edits'])) {
|
1305 |
+
$options['inline_edits'] = $this->options_decode($options['inline_edits']);
|
1306 |
+
}
|
1307 |
+
|
1308 |
+
// Restore inline edits from data-json
|
1309 |
+
// coming from inline editing
|
1310 |
+
// and merge with current inline edit
|
1311 |
+
if (isset($_POST['encoded_options'])) {
|
1312 |
+
$decoded_options = $this->options_decode($_POST['encoded_options']);
|
1313 |
+
|
1314 |
+
$to_merge_inline_edits = [];
|
1315 |
+
|
1316 |
+
if (isset($decoded_options['inline_edits'])) {
|
1317 |
+
foreach ($decoded_options['inline_edits'] as $decoded_inline_edit) {
|
1318 |
+
$to_merge_inline_edits[$decoded_inline_edit['post_id'] . $decoded_inline_edit['type']] = $decoded_inline_edit;
|
1319 |
+
}
|
1320 |
+
}
|
1321 |
+
|
1322 |
+
//Overwrite with new edited content
|
1323 |
+
if (isset($options['inline_edits'])) {
|
1324 |
+
foreach ($options['inline_edits'] as $inline_edit) {
|
1325 |
+
$to_merge_inline_edits[$inline_edit['post_id'] . $inline_edit['type']] = $inline_edit;
|
1326 |
+
}
|
1327 |
+
}
|
1328 |
+
|
1329 |
+
$options['inline_edits'] = array_values($to_merge_inline_edits);
|
1330 |
+
$options = array_merge($decoded_options, $options);
|
1331 |
+
}
|
1332 |
+
|
1333 |
+
return $options;
|
1334 |
+
}
|
1335 |
+
|
1336 |
+
return array();
|
1337 |
+
}
|
1338 |
+
|
1339 |
+
public function hook_wp_ajax_tnpc_delete_preset() {
|
1340 |
+
|
1341 |
+
if (!wp_verify_nonce($_POST['_wpnonce'], 'preset')) {
|
1342 |
+
wp_send_json_error('Expired request');
|
1343 |
+
}
|
1344 |
+
|
1345 |
+
$preset_id = (int) $_REQUEST['presetId'];
|
1346 |
+
|
1347 |
+
$newsletter = Newsletter::instance();
|
1348 |
+
|
1349 |
+
if ($preset_id > 0) {
|
1350 |
+
$preset = $newsletter->get_email($preset_id);
|
1351 |
+
|
1352 |
+
if ($preset && $preset->type === self::PRESET_EMAIL_TYPE) {
|
1353 |
+
Newsletter::instance()->delete_email($preset_id);
|
1354 |
+
wp_send_json_success();
|
1355 |
+
} else {
|
1356 |
+
wp_send_json_error(__('Is not a preset!', 'newsletter'));
|
1357 |
+
}
|
1358 |
+
} else {
|
1359 |
+
wp_send_json_error();
|
1360 |
+
}
|
1361 |
+
}
|
1362 |
+
|
1363 |
+
}
|
1364 |
+
|
1365 |
+
NewsletterEmails::instance();
|
includes/composer.php
CHANGED
@@ -1,987 +1,1008 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/** For old style coders */
|
4 |
-
function tnp_register_block($dir) {
|
5 |
-
return TNP_Composer::register_block($dir);
|
6 |
-
}
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Generates and HTML button for email using the values found on $options and
|
10 |
-
* prefixed by $prefix, with the standard syntax of NewsletterFields::button().
|
11 |
-
*
|
12 |
-
* @param array $options
|
13 |
-
* @param string $prefix
|
14 |
-
* @return string
|
15 |
-
*/
|
16 |
-
function tnpc_button($options, $prefix = 'button') {
|
17 |
-
return TNP_Composer::button($options, $prefix);
|
18 |
-
}
|
19 |
-
|
20 |
-
class TNP_Composer {
|
21 |
-
|
22 |
-
static $block_dirs = array();
|
23 |
-
|
24 |
-
static function register_block($dir) {
|
25 |
-
// Checks
|
26 |
-
$dir = realpath($dir);
|
27 |
-
if (!$dir) {
|
28 |
-
$error = new WP_Error('1', 'Seems not a valid path: ' . $dir);
|
29 |
-
NewsletterEmails::instance()->logger->error($error);
|
30 |
-
return $error;
|
31 |
-
}
|
32 |
-
|
33 |
-
$dir = wp_normalize_path($dir);
|
34 |
-
|
35 |
-
if (!file_exists($dir . '/block.php')) {
|
36 |
-
$error = new WP_Error('1', 'block.php missing on folder ' . $dir);
|
37 |
-
NewsletterEmails::instance()->logger->error($error);
|
38 |
-
return $error;
|
39 |
-
}
|
40 |
-
|
41 |
-
self::$block_dirs[] = $dir;
|
42 |
-
return true;
|
43 |
-
}
|
44 |
-
|
45 |
-
/**
|
46 |
-
* @param string $open
|
47 |
-
* @param string $inner
|
48 |
-
* @param string $close
|
49 |
-
* @param string[] $markers
|
50 |
-
*
|
51 |
-
* @return string
|
52 |
-
*/
|
53 |
-
static function wrap_html_element($open, $inner, $close, $markers = array('<!-- tnp -->', '<!-- /tnp -->')) {
|
54 |
-
|
55 |
-
return $open . $markers[0] . $inner . $markers[1] . $close;
|
56 |
-
}
|
57 |
-
|
58 |
-
/**
|
59 |
-
* @param string $block
|
60 |
-
* @param string[] $markers
|
61 |
-
*
|
62 |
-
* @return string
|
63 |
-
*/
|
64 |
-
static function unwrap_html_element($block, $markers = array('<!-- tnp -->', '<!-- /tnp -->')) {
|
65 |
-
if (self::_has_markers($block, $markers)) {
|
66 |
-
self::_escape_markers($markers);
|
67 |
-
$pattern = sprintf('/%s(.*?)%s/s', $markers[0], $markers[1]);
|
68 |
-
|
69 |
-
$matches = array();
|
70 |
-
preg_match($pattern, $block, $matches);
|
71 |
-
|
72 |
-
return $matches[1];
|
73 |
-
}
|
74 |
-
|
75 |
-
return $block;
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* @param string $block
|
80 |
-
* @param string[] $markers
|
81 |
-
*
|
82 |
-
* @return bool
|
83 |
-
*/
|
84 |
-
private static function _has_markers($block, $markers = array('<!-- tnp -->', '<!-- /tnp -->')) {
|
85 |
-
|
86 |
-
self::_escape_markers($markers);
|
87 |
-
|
88 |
-
$pattern = sprintf('/%s(.*?)%s/s', $markers[0], $markers[1]);
|
89 |
-
|
90 |
-
return preg_match($pattern, $block);
|
91 |
-
}
|
92 |
-
|
93 |
-
/**
|
94 |
-
* Sources:
|
95 |
-
* - https://webdesign.tutsplus.com/tutorials/creating-a-future-proof-responsive-email-without-media-queries--cms-23919
|
96 |
-
*
|
97 |
-
* @param type $email
|
98 |
-
* @return type
|
99 |
-
*/
|
100 |
-
static function get_html_open($email) {
|
101 |
-
$open = '<!DOCTYPE html>' . "\n";
|
102 |
-
$open .= '<html xmlns="https://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">' . "\n";
|
103 |
-
$open .= '<head>' . "\n";
|
104 |
-
$open .= '<title>{email_subject}</title>' . "\n";
|
105 |
-
$open .= '<meta charset="utf-8">' . "\n";
|
106 |
-
$open .= '<meta name="viewport" content="width=device-width, initial-scale=1">' . "\n";
|
107 |
-
$open .= '<meta http-equiv="X-UA-Compatible" content="IE=edge">' . "\n";
|
108 |
-
$open .= '<meta name="format-detection" content="address=no">' . "\n";
|
109 |
-
$open .= '<meta name="format-detection" content="telephone=no">' . "\n";
|
110 |
-
$open .= '<meta name="format-detection" content="email=no">' . "\n";
|
111 |
-
$open .= '<meta name="x-apple-disable-message-reformatting">' . "\n";
|
112 |
-
|
113 |
-
// $open .= '<!--[if !mso]><!-->' . "\n";
|
114 |
-
// $open .= '<meta http-equiv="X-UA-Compatible" content="IE=edge" />' . "\n";
|
115 |
-
// $open .= '<!--<![endif]-->' . "\n";
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
// $open .= '
|
122 |
-
// $open .= '
|
123 |
-
// $open .= 'div
|
124 |
-
// $open .= '
|
125 |
-
// $open .=
|
126 |
-
// $open .=
|
127 |
-
// $open .= '<
|
128 |
-
// $open .= '<
|
129 |
-
// $open .= '<o:
|
130 |
-
// $open .= '
|
131 |
-
// $open .= '</
|
132 |
-
// $open .= '</
|
133 |
-
// $open .=
|
134 |
-
// $open .=
|
135 |
-
// $open .=
|
136 |
-
|
137 |
-
$open .=
|
138 |
-
$open .=
|
139 |
-
$open .= "
|
140 |
-
$open .= "
|
141 |
-
$open .=
|
142 |
-
$open .=
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
$
|
155 |
-
$html
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
*
|
167 |
-
* @
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
"<
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
*
|
184 |
-
* @
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
"</
|
190 |
-
"</
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
*
|
196 |
-
*
|
197 |
-
*
|
198 |
-
*
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
//
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
$
|
211 |
-
$
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
$html_email = preg_replace('/<
|
217 |
-
$html_email = preg_replace('/<
|
218 |
-
$html_email =
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
$html_email = str_replace('
|
224 |
-
$html_email = str_replace('
|
225 |
-
$html_email = str_replace('
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
$markers[
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
*
|
238 |
-
*
|
239 |
-
*
|
240 |
-
*
|
241 |
-
* @param
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
//
|
257 |
-
//
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
*
|
268 |
-
*
|
269 |
-
*
|
270 |
-
*
|
271 |
-
* @param
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
$controls->data['
|
284 |
-
$controls->data['
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
*
|
305 |
-
*
|
306 |
-
* @param
|
307 |
-
* @param
|
308 |
-
*
|
309 |
-
*
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
*
|
325 |
-
*
|
326 |
-
* @param
|
327 |
-
* @param
|
328 |
-
*
|
329 |
-
*
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
*
|
347 |
-
*
|
348 |
-
* - [prefix]
|
349 |
-
* - [prefix]
|
350 |
-
* - [prefix]
|
351 |
-
* - [prefix]
|
352 |
-
* - [prefix]
|
353 |
-
* - [prefix]
|
354 |
-
*
|
355 |
-
*
|
356 |
-
*
|
357 |
-
*
|
358 |
-
* @param
|
359 |
-
* @
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
$prefix . '
|
369 |
-
$prefix . '
|
370 |
-
$prefix . '
|
371 |
-
$prefix . '
|
372 |
-
$prefix . '
|
373 |
-
$prefix . '
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
$
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
$b .= '>';
|
387 |
-
$b .= '<
|
388 |
-
$b .= '<
|
389 |
-
$b .= '
|
390 |
-
$b .= '
|
391 |
-
$b .=
|
392 |
-
$b .=
|
393 |
-
$b .= '</
|
394 |
-
$b
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
*
|
400 |
-
*
|
401 |
-
* @param
|
402 |
-
* @
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
'
|
409 |
-
'
|
410 |
-
'link-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
//Class
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
//Class
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
$
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
. '
|
450 |
-
. '
|
451 |
-
. '
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
*
|
466 |
-
*
|
467 |
-
*
|
468 |
-
*
|
469 |
-
*
|
470 |
-
*
|
471 |
-
* @
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
*
|
504 |
-
*
|
505 |
-
*
|
506 |
-
*
|
507 |
-
* @param
|
508 |
-
* @
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
$media =
|
517 |
-
$media->
|
518 |
-
$media->
|
519 |
-
$media->
|
520 |
-
$media
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
$content = $
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
$
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
'
|
557 |
-
'
|
558 |
-
'
|
559 |
-
'
|
560 |
-
'
|
561 |
-
'
|
562 |
-
'
|
563 |
-
'
|
564 |
-
'
|
565 |
-
'
|
566 |
-
'
|
567 |
-
'
|
568 |
-
'
|
569 |
-
'
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
*
|
576 |
-
*
|
577 |
-
*
|
578 |
-
* -
|
579 |
-
* -
|
580 |
-
* -
|
581 |
-
*
|
582 |
-
*
|
583 |
-
* @param
|
584 |
-
* @
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
$
|
589 |
-
$
|
590 |
-
$
|
591 |
-
$
|
592 |
-
$
|
593 |
-
$
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
$
|
599 |
-
|
600 |
-
$e .= '
|
601 |
-
$
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
$e .=
|
609 |
-
$e .=
|
610 |
-
$e .= '</div>';
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
$e .= '
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
$
|
622 |
-
|
623 |
-
$
|
624 |
-
|
625 |
-
$e .=
|
626 |
-
$e .=
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
$e
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
$
|
646 |
-
$scale
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
$style->
|
654 |
-
$style->
|
655 |
-
$style->
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
$
|
665 |
-
$
|
666 |
-
$button_options['
|
667 |
-
$button_options['
|
668 |
-
$button_options['
|
669 |
-
$button_options['
|
670 |
-
$button_options['
|
671 |
-
$button_options['
|
672 |
-
$button_options['
|
673 |
-
$button_options['
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
$
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
continue;
|
732 |
-
}
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
}
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
class
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
*
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
$this->
|
820 |
-
$this->cells_counter
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
}
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
905 |
-
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
|
917 |
-
|
918 |
-
|
919 |
-
|
920 |
-
|
921 |
-
|
922 |
-
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
930 |
-
|
931 |
-
|
932 |
-
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
-
|
937 |
-
|
938 |
-
|
939 |
-
|
940 |
-
|
941 |
-
|
942 |
-
|
943 |
-
|
944 |
-
|
945 |
-
|
946 |
-
|
947 |
-
|
948 |
-
|
949 |
-
|
950 |
-
|
951 |
-
|
952 |
-
|
953 |
-
|
954 |
-
class
|
955 |
-
|
956 |
-
|
957 |
-
|
958 |
-
|
959 |
-
|
960 |
-
|
961 |
-
|
962 |
-
|
963 |
-
|
964 |
-
|
965 |
-
|
966 |
-
|
967 |
-
|
968 |
-
|
969 |
-
|
970 |
-
|
971 |
-
|
972 |
-
|
973 |
-
|
974 |
-
|
975 |
-
|
976 |
-
|
977 |
-
|
978 |
-
|
979 |
-
|
980 |
-
|
981 |
-
|
982 |
-
|
983 |
-
|
984 |
-
|
985 |
-
|
986 |
-
|
987 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/** For old style coders */
|
4 |
+
function tnp_register_block($dir) {
|
5 |
+
return TNP_Composer::register_block($dir);
|
6 |
+
}
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Generates and HTML button for email using the values found on $options and
|
10 |
+
* prefixed by $prefix, with the standard syntax of NewsletterFields::button().
|
11 |
+
*
|
12 |
+
* @param array $options
|
13 |
+
* @param string $prefix
|
14 |
+
* @return string
|
15 |
+
*/
|
16 |
+
function tnpc_button($options, $prefix = 'button') {
|
17 |
+
return TNP_Composer::button($options, $prefix);
|
18 |
+
}
|
19 |
+
|
20 |
+
class TNP_Composer {
|
21 |
+
|
22 |
+
static $block_dirs = array();
|
23 |
+
|
24 |
+
static function register_block($dir) {
|
25 |
+
// Checks
|
26 |
+
$dir = realpath($dir);
|
27 |
+
if (!$dir) {
|
28 |
+
$error = new WP_Error('1', 'Seems not a valid path: ' . $dir);
|
29 |
+
NewsletterEmails::instance()->logger->error($error);
|
30 |
+
return $error;
|
31 |
+
}
|
32 |
+
|
33 |
+
$dir = wp_normalize_path($dir);
|
34 |
+
|
35 |
+
if (!file_exists($dir . '/block.php')) {
|
36 |
+
$error = new WP_Error('1', 'block.php missing on folder ' . $dir);
|
37 |
+
NewsletterEmails::instance()->logger->error($error);
|
38 |
+
return $error;
|
39 |
+
}
|
40 |
+
|
41 |
+
self::$block_dirs[] = $dir;
|
42 |
+
return true;
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @param string $open
|
47 |
+
* @param string $inner
|
48 |
+
* @param string $close
|
49 |
+
* @param string[] $markers
|
50 |
+
*
|
51 |
+
* @return string
|
52 |
+
*/
|
53 |
+
static function wrap_html_element($open, $inner, $close, $markers = array('<!-- tnp -->', '<!-- /tnp -->')) {
|
54 |
+
|
55 |
+
return $open . $markers[0] . $inner . $markers[1] . $close;
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* @param string $block
|
60 |
+
* @param string[] $markers
|
61 |
+
*
|
62 |
+
* @return string
|
63 |
+
*/
|
64 |
+
static function unwrap_html_element($block, $markers = array('<!-- tnp -->', '<!-- /tnp -->')) {
|
65 |
+
if (self::_has_markers($block, $markers)) {
|
66 |
+
self::_escape_markers($markers);
|
67 |
+
$pattern = sprintf('/%s(.*?)%s/s', $markers[0], $markers[1]);
|
68 |
+
|
69 |
+
$matches = array();
|
70 |
+
preg_match($pattern, $block, $matches);
|
71 |
+
|
72 |
+
return $matches[1];
|
73 |
+
}
|
74 |
+
|
75 |
+
return $block;
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* @param string $block
|
80 |
+
* @param string[] $markers
|
81 |
+
*
|
82 |
+
* @return bool
|
83 |
+
*/
|
84 |
+
private static function _has_markers($block, $markers = array('<!-- tnp -->', '<!-- /tnp -->')) {
|
85 |
+
|
86 |
+
self::_escape_markers($markers);
|
87 |
+
|
88 |
+
$pattern = sprintf('/%s(.*?)%s/s', $markers[0], $markers[1]);
|
89 |
+
|
90 |
+
return preg_match($pattern, $block);
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Sources:
|
95 |
+
* - https://webdesign.tutsplus.com/tutorials/creating-a-future-proof-responsive-email-without-media-queries--cms-23919
|
96 |
+
*
|
97 |
+
* @param type $email
|
98 |
+
* @return type
|
99 |
+
*/
|
100 |
+
static function get_html_open($email) {
|
101 |
+
$open = '<!DOCTYPE html>' . "\n";
|
102 |
+
$open .= '<html xmlns="https://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">' . "\n";
|
103 |
+
$open .= '<head>' . "\n";
|
104 |
+
$open .= '<title>{email_subject}</title>' . "\n";
|
105 |
+
$open .= '<meta charset="utf-8">' . "\n";
|
106 |
+
$open .= '<meta name="viewport" content="width=device-width, initial-scale=1">' . "\n";
|
107 |
+
$open .= '<meta http-equiv="X-UA-Compatible" content="IE=edge">' . "\n";
|
108 |
+
$open .= '<meta name="format-detection" content="address=no">' . "\n";
|
109 |
+
$open .= '<meta name="format-detection" content="telephone=no">' . "\n";
|
110 |
+
$open .= '<meta name="format-detection" content="email=no">' . "\n";
|
111 |
+
$open .= '<meta name="x-apple-disable-message-reformatting">' . "\n";
|
112 |
+
|
113 |
+
// $open .= '<!--[if !mso]><!-->' . "\n";
|
114 |
+
// $open .= '<meta http-equiv="X-UA-Compatible" content="IE=edge" />' . "\n";
|
115 |
+
// $open .= '<!--<![endif]-->' . "\n";
|
116 |
+
// $open .= '<!--[if mso]>' . "\n";
|
117 |
+
|
118 |
+
$open .= '<!--[if gte mso 9]><xml><o:OfficeDocumentSettings><o:AllowPNG/><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml><![endif]-->' . "\n";
|
119 |
+
|
120 |
+
// $open .= '<style type="text/css">';
|
121 |
+
// $open .= 'table {border-collapse:collapse;border-spacing:0;margin:0;}';
|
122 |
+
// $open .= 'div, td {padding:0;}';
|
123 |
+
// $open .= 'div {margin:0 !important;}';
|
124 |
+
// $open .= '</style>';
|
125 |
+
// $open .= "\n";
|
126 |
+
// $open .= '<noscript>';
|
127 |
+
// $open .= '<xml>';
|
128 |
+
// $open .= '<o:OfficeDocumentSettings>';
|
129 |
+
// $open .= '<o:PixelsPerInch>96</o:PixelsPerInch>';
|
130 |
+
// $open .= '</o:OfficeDocumentSettings>';
|
131 |
+
// $open .= '</xml>';
|
132 |
+
// $open .= '</noscript>';
|
133 |
+
// $open .= "\n";
|
134 |
+
// $open .= '<![endif]-->';
|
135 |
+
// $open .= "\n";
|
136 |
+
$open .= '<style type="text/css">' . "\n";
|
137 |
+
$open .= NewsletterEmails::instance()->get_composer_css();
|
138 |
+
$open .= "\n</style>\n";
|
139 |
+
$open .= "</head>\n";
|
140 |
+
$open .= '<body style="margin: 0; padding: 0; line-height: normal; word-spacing: normal;" dir="' . (is_rtl() ? 'rtl' : 'ltr') . '">';
|
141 |
+
$open .= "\n";
|
142 |
+
$open .= self::get_html_preheader($email);
|
143 |
+
|
144 |
+
return $open;
|
145 |
+
}
|
146 |
+
|
147 |
+
static private function get_html_preheader($email) {
|
148 |
+
|
149 |
+
if (empty($email->options['preheader'])) {
|
150 |
+
return "";
|
151 |
+
}
|
152 |
+
|
153 |
+
$preheader_text = esc_html($email->options['preheader']);
|
154 |
+
$html = "<div style=\"display:none;font-size:1px;color:#ffffff;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;\">$preheader_text</div>";
|
155 |
+
$html .= "\n";
|
156 |
+
|
157 |
+
return $html;
|
158 |
+
}
|
159 |
+
|
160 |
+
static function get_html_close($email) {
|
161 |
+
return "</body>\n</html>";
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
*
|
166 |
+
* @param TNP_Email $email
|
167 |
+
* @return string
|
168 |
+
*/
|
169 |
+
static function get_main_wrapper_open($email) {
|
170 |
+
if (!isset($email->options['composer_background']) || $email->options['composer_background'] == 'inherit') {
|
171 |
+
$bgcolor = '';
|
172 |
+
} else {
|
173 |
+
$bgcolor = $email->options['composer_background'];
|
174 |
+
}
|
175 |
+
|
176 |
+
return "\n<table cellpadding='0' cellspacing='0' border='0' width='100%'>\n" .
|
177 |
+
"<tr>\n" .
|
178 |
+
"<td bgcolor='$bgcolor' valign='top'><!-- tnp -->";
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
*
|
183 |
+
* @param TNP_Email $email
|
184 |
+
* @return string
|
185 |
+
*/
|
186 |
+
static function get_main_wrapper_close($email) {
|
187 |
+
return "\n<!-- /tnp -->\n" .
|
188 |
+
"</td>\n" .
|
189 |
+
"</tr>\n" .
|
190 |
+
"</table>\n\n";
|
191 |
+
}
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Remove <doctype>, <body> and unnecessary envelopes for editing with composer
|
195 |
+
*
|
196 |
+
* @param string $html_email
|
197 |
+
*
|
198 |
+
* @return string
|
199 |
+
*/
|
200 |
+
static function unwrap_email($html_email) {
|
201 |
+
|
202 |
+
if (self::_has_markers($html_email)) {
|
203 |
+
$html_email = self::unwrap_html_element($html_email);
|
204 |
+
} else {
|
205 |
+
//KEEP FOR OLD EMAIL COMPATIBILITY
|
206 |
+
// Extracts only the body part
|
207 |
+
$x = strpos($html_email, '<body');
|
208 |
+
if ($x) {
|
209 |
+
$x = strpos($html_email, '>', $x);
|
210 |
+
$y = strpos($html_email, '</body>');
|
211 |
+
$html_email = substr($html_email, $x + 1, $y - $x - 1);
|
212 |
+
}
|
213 |
+
|
214 |
+
/* Cleans up uncorrectly stored newsletter bodies */
|
215 |
+
$html_email = preg_replace('/<style\s+.*?>.*?<\\/style>/is', '', $html_email);
|
216 |
+
$html_email = preg_replace('/<meta.*?>/', '', $html_email);
|
217 |
+
$html_email = preg_replace('/<title\s+.*?>.*?<\\/title>/i', '', $html_email);
|
218 |
+
$html_email = trim($html_email);
|
219 |
+
}
|
220 |
+
|
221 |
+
// Required since esc_html DOES NOT escape the HTML entities (apparently)
|
222 |
+
$html_email = str_replace('&', '&', $html_email);
|
223 |
+
$html_email = str_replace('"', '"', $html_email);
|
224 |
+
$html_email = str_replace('<', '<', $html_email);
|
225 |
+
$html_email = str_replace('>', '>', $html_email);
|
226 |
+
|
227 |
+
return $html_email;
|
228 |
+
}
|
229 |
+
|
230 |
+
private static function _escape_markers(&$markers) {
|
231 |
+
$markers[0] = str_replace('/', '\/', $markers[0]);
|
232 |
+
$markers[1] = str_replace('/', '\/', $markers[1]);
|
233 |
+
}
|
234 |
+
|
235 |
+
/**
|
236 |
+
* Using the data collected inside $controls (and submitted by a form containing the
|
237 |
+
* composer fields), updates the email. The message body is completed with doctype,
|
238 |
+
* head, style and the main wrapper.
|
239 |
+
*
|
240 |
+
* @param TNP_Email $email
|
241 |
+
* @param NewsletterControls $controls
|
242 |
+
*/
|
243 |
+
static function update_email($email, $controls) {
|
244 |
+
if (isset($controls->data['subject'])) {
|
245 |
+
$email->subject = $controls->data['subject'];
|
246 |
+
}
|
247 |
+
|
248 |
+
// They should be only composer options
|
249 |
+
foreach ($controls->data as $name => $value) {
|
250 |
+
if (strpos($name, 'options_') === 0) {
|
251 |
+
$email->options[substr($name, 8)] = $value;
|
252 |
+
}
|
253 |
+
}
|
254 |
+
|
255 |
+
//if (isset($controls->data['preheader'])) {
|
256 |
+
// $email->options['preheader'] = $controls->data['preheader'];
|
257 |
+
//}
|
258 |
+
|
259 |
+
$email->editor = NewsletterEmails::EDITOR_COMPOSER;
|
260 |
+
|
261 |
+
$email->message = self::get_html_open($email) . self::get_main_wrapper_open($email) .
|
262 |
+
$controls->data['message'] . self::get_main_wrapper_close($email) . self::get_html_close($email);
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Prepares a controls object injecting the relevant fields from an email
|
267 |
+
* which cannot be directly used by controls. If $email is null or missing,
|
268 |
+
* $controls is prepared with default values.
|
269 |
+
*
|
270 |
+
* @param NewsletterControls $controls
|
271 |
+
* @param TNP_Email $email
|
272 |
+
*/
|
273 |
+
static function prepare_controls($controls, $email = null) {
|
274 |
+
|
275 |
+
// Controls for a new email (which actually does not exist yet
|
276 |
+
if (!empty($email)) {
|
277 |
+
|
278 |
+
foreach ($email->options as $name => $value) {
|
279 |
+
$controls->data['options_' . $name] = $value;
|
280 |
+
}
|
281 |
+
|
282 |
+
$controls->data['message'] = TNP_Composer::unwrap_email($email->message);
|
283 |
+
$controls->data['subject'] = $email->subject;
|
284 |
+
$controls->data['updated'] = $email->updated;
|
285 |
+
}
|
286 |
+
|
287 |
+
if (!empty($email->options['sender_email'])) {
|
288 |
+
$controls->data['sender_email'] = $email->options['sender_email'];
|
289 |
+
} else {
|
290 |
+
$controls->data['sender_email'] = Newsletter::instance()->options['sender_email'];
|
291 |
+
}
|
292 |
+
|
293 |
+
if (!empty($email->options['sender_name'])) {
|
294 |
+
$controls->data['sender_name'] = $email->options['sender_name'];
|
295 |
+
} else {
|
296 |
+
$controls->data['sender_name'] = Newsletter::instance()->options['sender_name'];
|
297 |
+
}
|
298 |
+
|
299 |
+
$controls->data = array_merge(TNP_Composer::get_global_style_defaults(), $controls->data);
|
300 |
+
}
|
301 |
+
|
302 |
+
/**
|
303 |
+
* Extract inline edited post field from inline_edit_list[]
|
304 |
+
*
|
305 |
+
* @param array $inline_edit_list
|
306 |
+
* @param string $field_type
|
307 |
+
* @param int $post_id
|
308 |
+
*
|
309 |
+
* @return string
|
310 |
+
*/
|
311 |
+
static function get_edited_inline_post_field($inline_edit_list, $field_type, $post_id) {
|
312 |
+
|
313 |
+
foreach ($inline_edit_list as $edit) {
|
314 |
+
if ($edit['type'] == $field_type && $edit['post_id'] == $post_id) {
|
315 |
+
return $edit['content'];
|
316 |
+
}
|
317 |
+
}
|
318 |
+
|
319 |
+
return '';
|
320 |
+
}
|
321 |
+
|
322 |
+
/**
|
323 |
+
* Check if inline_edit_list[] have inline edit field for specific post
|
324 |
+
*
|
325 |
+
* @param array $inline_edit_list
|
326 |
+
* @param string $field_type
|
327 |
+
* @param int $post_id
|
328 |
+
*
|
329 |
+
* @return bool
|
330 |
+
*/
|
331 |
+
static function is_post_field_edited_inline($inline_edit_list, $field_type, $post_id) {
|
332 |
+
if (empty($inline_edit_list) || !is_array($inline_edit_list)) {
|
333 |
+
return false;
|
334 |
+
}
|
335 |
+
foreach ($inline_edit_list as $edit) {
|
336 |
+
if ($edit['type'] == $field_type && $edit['post_id'] == $post_id) {
|
337 |
+
return true;
|
338 |
+
}
|
339 |
+
}
|
340 |
+
|
341 |
+
return false;
|
342 |
+
}
|
343 |
+
|
344 |
+
/**
|
345 |
+
* Creates the HTML for a button extrating from the options, with the provided prefix, the button attributes:
|
346 |
+
*
|
347 |
+
* - [prefix]_url The button URL
|
348 |
+
* - [prefix]_font_family
|
349 |
+
* - [prefix]_font_size
|
350 |
+
* - [prefix]_font_weight
|
351 |
+
* - [prefix]_label
|
352 |
+
* - [prefix]_font_color The label color
|
353 |
+
* - [prefix]_background The button color
|
354 |
+
*
|
355 |
+
* TODO: Add radius and possiblt the alignment
|
356 |
+
*
|
357 |
+
* @param array $options
|
358 |
+
* @param string $prefix
|
359 |
+
* @return string
|
360 |
+
*/
|
361 |
+
static function button($options, $prefix = 'button') {
|
362 |
+
|
363 |
+
if (empty($options[$prefix . '_label'])) {
|
364 |
+
return;
|
365 |
+
}
|
366 |
+
$defaults = [
|
367 |
+
$prefix . '_url' => '#',
|
368 |
+
$prefix . '_font_family' => 'Helvetica, Arial, sans-serif',
|
369 |
+
$prefix . '_font_color' => '#ffffff',
|
370 |
+
$prefix . '_font_weight' => 'bold',
|
371 |
+
$prefix . '_font_size' => 20,
|
372 |
+
$prefix . '_background' => '#256F9C',
|
373 |
+
$prefix . '_align' => 'center'
|
374 |
+
];
|
375 |
+
|
376 |
+
$options = array_merge($defaults, array_filter($options));
|
377 |
+
|
378 |
+
$b = '<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="margin: 0 auto"';
|
379 |
+
if (!empty($options[$prefix . '_align'])) {
|
380 |
+
$b .= ' align="' . esc_attr($options[$prefix . '_align']) . '"';
|
381 |
+
}
|
382 |
+
if (!empty($options[$prefix . '_width'])) {
|
383 |
+
$b .= ' width="' . esc_attr($options[$prefix . '_width']) . '"';
|
384 |
+
}
|
385 |
+
$b .= '>';
|
386 |
+
$b .= '<tr>';
|
387 |
+
$b .= '<td align="center" bgcolor="' . $options[$prefix . '_background'] . '" role="presentation" style="border:none;border-radius:3px;cursor:auto;mso-padding-alt:10px 25px;background:' . $options[$prefix . '_background'] . '" valign="middle">';
|
388 |
+
$b .= '<a href="' . $options[$prefix . '_url'] . '"';
|
389 |
+
$b .= ' style="display:inline-block;background:' . $options[$prefix . '_background'] . ';color:' . $options[$prefix . '_font_color'] . ';font-family:' . $options[$prefix . '_font_family'] . ';font-size:' . $options[$prefix . '_font_size'] . 'px;font-weight:' . $options[$prefix . '_font_weight'] . ';line-height:120%;margin:0;text-decoration:none;text-transform:none;padding:10px 25px;mso-padding-alt:0px;border-radius:3px;"';
|
390 |
+
$b .= ' target="_blank">';
|
391 |
+
$b .= $options[$prefix . '_label'];
|
392 |
+
$b .= '</a>';
|
393 |
+
$b .= '</td></tr></table>';
|
394 |
+
return $b;
|
395 |
+
}
|
396 |
+
|
397 |
+
/**
|
398 |
+
* Generates an IMG tag, linked if the media has an URL.
|
399 |
+
*
|
400 |
+
* @param TNP_Media $media
|
401 |
+
* @param string $style
|
402 |
+
* @return string
|
403 |
+
*/
|
404 |
+
static function image($media, $attr = []) {
|
405 |
+
|
406 |
+
$default_attrs = [
|
407 |
+
'style' => 'max-width: 100%; height: auto; display: inline-block',
|
408 |
+
'class' => '',
|
409 |
+
'link-style' => 'text-decoration: none; display: inline-block',
|
410 |
+
'link-class' => null,
|
411 |
+
];
|
412 |
+
|
413 |
+
$attr = array_merge($default_attrs, $attr);
|
414 |
+
|
415 |
+
//Class and style attribute are mutually exclusive.
|
416 |
+
//Class take priority to style because classes will transform to inline style inside block rendering operation
|
417 |
+
if (!empty($attr['inline-class'])) {
|
418 |
+
$styling = ' inline-class="' . esc_attr($attr['inline-class']) . '" ';
|
419 |
+
} else {
|
420 |
+
$styling = ' style="' . esc_attr($attr['style']) . '" ';
|
421 |
+
}
|
422 |
+
|
423 |
+
if (!empty($attr['class'])) {
|
424 |
+
$styling .= ' class="' . esc_attr($attr['class']) . '" ';
|
425 |
+
}
|
426 |
+
|
427 |
+
//Class and style attribute are mutually exclusive.
|
428 |
+
//Class take priority to style because classes will transform to inline style inside block rendering operation
|
429 |
+
if (!empty($attr['link-class'])) {
|
430 |
+
$link_styling = ' inline-class="' . esc_attr($attr['link-class']) . '" ';
|
431 |
+
} else {
|
432 |
+
$link_styling = ' style="' . esc_attr($attr['link-style']) . '" ';
|
433 |
+
}
|
434 |
+
|
435 |
+
$b = '';
|
436 |
+
if ($media->link) {
|
437 |
+
$b .= '<a href="' . esc_attr($media->link) . '" target="_blank" rel="noopener nofollow" style="display: inline-block; font-size: 0; text-decoration: none; line-height: normal!important">';
|
438 |
+
} else {
|
439 |
+
// The span grants images are not upscaled when fluid (two columns posts block)
|
440 |
+
$b .= '<span style="display: inline-block; font-size: 0; text-decoration: none; line-height: normal!important">';
|
441 |
+
}
|
442 |
+
if ($media) {
|
443 |
+
$b .= '<img src="' . esc_attr($media->url) . '" width="' . esc_attr($media->width) . '"';
|
444 |
+
if ($media->height) {
|
445 |
+
$b .= ' height="' . esc_attr($media->height) . '"';
|
446 |
+
}
|
447 |
+
$b .= ' alt="' . esc_attr($media->alt) . '"'
|
448 |
+
. ' border="0"'
|
449 |
+
. ' style="display: inline-block; max-width: 100%!important; padding: 0; border: 0; font-size: 12px"'
|
450 |
+
. ' class="' . esc_attr($attr['class']) . '" '
|
451 |
+
. '>';
|
452 |
+
}
|
453 |
+
|
454 |
+
if ($media->link) {
|
455 |
+
$b .= '</a>';
|
456 |
+
} else {
|
457 |
+
$b .= '</span>';
|
458 |
+
}
|
459 |
+
|
460 |
+
return $b;
|
461 |
+
}
|
462 |
+
|
463 |
+
/**
|
464 |
+
* Returns a WP media ID for the specified post (or false if nothing can be found)
|
465 |
+
* looking for the featured image or, if missing, taking the first media in the gallery and
|
466 |
+
* if again missing, searching the first reference to a media in the post content.
|
467 |
+
*
|
468 |
+
* The media ID is not checked for real existance of the associated attachment.
|
469 |
+
*
|
470 |
+
* @param int $post_id
|
471 |
+
* @return int
|
472 |
+
*/
|
473 |
+
static function get_post_thumbnail_id($post_id) {
|
474 |
+
if (is_object($post_id)) {
|
475 |
+
$post_id = $post_id->ID;
|
476 |
+
}
|
477 |
+
|
478 |
+
// Find a media id to be used as featured image
|
479 |
+
$media_id = get_post_thumbnail_id($post_id);
|
480 |
+
if (!empty($media_id)) {
|
481 |
+
return $media_id;
|
482 |
+
}
|
483 |
+
|
484 |
+
$attachments = get_children(array('numberpost' => 1, 'post_parent' => $post_id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'menu_order'));
|
485 |
+
if (!empty($attachments)) {
|
486 |
+
foreach ($attachments as $id => &$attachment) {
|
487 |
+
return $id;
|
488 |
+
}
|
489 |
+
}
|
490 |
+
|
491 |
+
$post = get_post($post_id);
|
492 |
+
|
493 |
+
$r = preg_match('/wp-image-(\d+)/', $post->post_content, $matches);
|
494 |
+
if ($matches) {
|
495 |
+
return (int) $matches[1];
|
496 |
+
}
|
497 |
+
|
498 |
+
return false;
|
499 |
+
}
|
500 |
+
|
501 |
+
/**
|
502 |
+
* Builds a TNP_Media object to be used in newsletters from a WP media/attachement ID. The returned
|
503 |
+
* media has a size which best match the one requested (this is the standard WP behavior, plugins
|
504 |
+
* could change it).
|
505 |
+
*
|
506 |
+
* @param int $media_id
|
507 |
+
* @param array $size
|
508 |
+
* @return \TNP_Media
|
509 |
+
*/
|
510 |
+
function get_media($media_id, $size) {
|
511 |
+
$src = wp_get_attachment_image_src($media_id, $size);
|
512 |
+
if (!$src) {
|
513 |
+
return null;
|
514 |
+
}
|
515 |
+
$media = new TNP_Media();
|
516 |
+
$media->id = $media_id;
|
517 |
+
$media->url = $src[0];
|
518 |
+
$media->width = $src[1];
|
519 |
+
$media->height = $src[2];
|
520 |
+
return $media;
|
521 |
+
}
|
522 |
+
|
523 |
+
static function post_content($post) {
|
524 |
+
$content = $post->post_content;
|
525 |
+
$content = wpautop($content);
|
526 |
+
if (true || $options['enable shortcodes']) {
|
527 |
+
remove_shortcode('gallery');
|
528 |
+
add_shortcode('gallery', 'tnp_gallery_shortcode');
|
529 |
+
$content = do_shortcode($content);
|
530 |
+
}
|
531 |
+
$content = str_replace('<p>', '<p class="paragraph">', $content);
|
532 |
+
|
533 |
+
$selected_images = array();
|
534 |
+
if (preg_match_all('/<img [^>]+>/', $content, $matches)) {
|
535 |
+
foreach ($matches[0] as $image) {
|
536 |
+
if (preg_match('/wp-image-([0-9]+)/i', $image, $class_id) && ( $attachment_id = absint($class_id[1]) )) {
|
537 |
+
$selected_images[$image] = $attachment_id;
|
538 |
+
}
|
539 |
+
}
|
540 |
+
}
|
541 |
+
|
542 |
+
foreach ($selected_images as $image => $attachment_id) {
|
543 |
+
$src = tnp_media_resize($attachment_id, array(600, 0));
|
544 |
+
if (is_wp_error($src)) {
|
545 |
+
continue;
|
546 |
+
}
|
547 |
+
$content = str_replace($image, '<img src="' . $src . '" width="600" style="max-width: 100%">', $content);
|
548 |
+
}
|
549 |
+
|
550 |
+
return $content;
|
551 |
+
}
|
552 |
+
|
553 |
+
static function get_global_style_defaults() {
|
554 |
+
return [
|
555 |
+
'options_composer_title_font_family' => 'Verdana, Geneva, sans-serif',
|
556 |
+
'options_composer_title_font_size' => 32,
|
557 |
+
'options_composer_title_font_weight' => 'normal',
|
558 |
+
'options_composer_title_font_color' => '#222222',
|
559 |
+
'options_composer_text_font_family' => 'Verdana, Geneva, sans-serif',
|
560 |
+
'options_composer_text_font_size' => 16,
|
561 |
+
'options_composer_text_font_weight' => 'normal',
|
562 |
+
'options_composer_text_font_color' => '#222222',
|
563 |
+
'options_composer_button_font_family' => 'Verdana, Geneva, sans-serif',
|
564 |
+
'options_composer_button_font_size' => 16,
|
565 |
+
'options_composer_button_font_weight' => 'normal',
|
566 |
+
'options_composer_button_font_color' => '#FFFFFF',
|
567 |
+
'options_composer_button_background_color' => '#256F9C',
|
568 |
+
'options_composer_background' => '#FFFFFF',
|
569 |
+
'options_composer_block_background' => '#FFFFFF',
|
570 |
+
];
|
571 |
+
}
|
572 |
+
|
573 |
+
/**
|
574 |
+
* Inspired by: https://webdesign.tutsplus.com/tutorials/creating-a-future-proof-responsive-email-without-media-queries--cms-23919
|
575 |
+
*
|
576 |
+
* Attributes:
|
577 |
+
* - columns: number of columns [2]
|
578 |
+
* - padding: cells padding [10]
|
579 |
+
* - responsive: il on mobile the cell should stack up [true]
|
580 |
+
* - width: the whole row width, it should reduced by the external row padding [600]
|
581 |
+
*
|
582 |
+
* @param string[] $items
|
583 |
+
* @param array $attrs
|
584 |
+
* @return string
|
585 |
+
*/
|
586 |
+
static function grid($items = [], $attrs = []) {
|
587 |
+
$attrs = wp_parse_args($attrs, ['width' => 600, 'columns' => 2, 'padding' => 10, 'responsive' => true]);
|
588 |
+
$width = (int) $attrs['width'];
|
589 |
+
$columns = (int) $attrs['columns'];
|
590 |
+
$padding = (int) $attrs['padding'];
|
591 |
+
$column_width = $width / $columns;
|
592 |
+
$td_width = 100 / $columns;
|
593 |
+
$chunks = array_chunk($items, $columns);
|
594 |
+
|
595 |
+
if ($attrs['responsive']) {
|
596 |
+
|
597 |
+
$e = '';
|
598 |
+
foreach ($chunks as &$chunk) {
|
599 |
+
$e .= '<div style="text-align:center;font-size:0;">';
|
600 |
+
$e .= '<!--[if mso]><table role="presentation" width="100%"><tr><![endif]-->';
|
601 |
+
foreach ($chunk as &$item) {
|
602 |
+
$e .= '<!--[if mso]><td width="' . $td_width . '%" style="width:' . $td_width . '%;padding:' . $padding . 'px" valign="top"><![endif]-->';
|
603 |
+
|
604 |
+
$e .= '<div class="max-width-100" style="width:100%;max-width:' . $column_width . 'px;display:inline-block;vertical-align: top;box-sizing: border-box;">';
|
605 |
+
|
606 |
+
// This element to add padding without deal with border-box not well supported
|
607 |
+
$e .= '<div style="padding:' . $padding . 'px;">';
|
608 |
+
$e .= $item;
|
609 |
+
$e .= '</div>';
|
610 |
+
$e .= '</div>';
|
611 |
+
|
612 |
+
$e .= '<!--[if mso]></td><![endif]-->';
|
613 |
+
}
|
614 |
+
$e .= '<!--[if mso]></tr></table><![endif]-->';
|
615 |
+
$e .= '</div>';
|
616 |
+
}
|
617 |
+
|
618 |
+
return $e;
|
619 |
+
} else {
|
620 |
+
$e = '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="width: 100%; max-width: 100%!important">';
|
621 |
+
foreach ($chunks as &$chunk) {
|
622 |
+
$e .= '<tr>';
|
623 |
+
foreach ($chunk as &$item) {
|
624 |
+
$e .= '<td width="' . $td_width . '%" style="width:' . $td_width . '%; padding:' . $padding . 'px" valign="top">';
|
625 |
+
$e .= $item;
|
626 |
+
$e .= '</td>';
|
627 |
+
}
|
628 |
+
$e .= '</tr>';
|
629 |
+
}
|
630 |
+
$e .= '</table>';
|
631 |
+
return $e;
|
632 |
+
}
|
633 |
+
}
|
634 |
+
|
635 |
+
static function get_text_style($options, $prefix, $composer, $attrs = []) {
|
636 |
+
return self::get_style($options, $prefix, $composer, 'text', $attrs);
|
637 |
+
}
|
638 |
+
|
639 |
+
static function get_title_style($options, $prefix, $composer, $attrs = []) {
|
640 |
+
return self::get_style($options, $prefix, $composer, 'title', $attrs);
|
641 |
+
}
|
642 |
+
|
643 |
+
static function get_style($options, $prefix, $composer, $type = 'text', $attrs = []) {
|
644 |
+
$style = new TNP_Style();
|
645 |
+
$scale = 1.0;
|
646 |
+
if (!empty($attrs['scale'])) {
|
647 |
+
$scale = (float) $attrs['scale'];
|
648 |
+
}
|
649 |
+
if (!empty($prefix))
|
650 |
+
$prefix .= '_';
|
651 |
+
|
652 |
+
$style->font_family = empty($options[$prefix . 'font_family']) ? $composer[$type . '_font_family'] : $options[$prefix . 'font_family'];
|
653 |
+
$style->font_size = empty($options[$prefix . 'font_size']) ? round($composer[$type . '_font_size'] * $scale) : $options[$prefix . 'font_size'];
|
654 |
+
$style->font_color = empty($options[$prefix . 'font_color']) ? $composer[$type . '_font_color'] : $options[$prefix . 'font_color'];
|
655 |
+
$style->font_weight = empty($options[$prefix . 'font_weight']) ? $composer[$type . '_font_weight'] : $options[$prefix . 'font_weight'];
|
656 |
+
if ($type === 'button') {
|
657 |
+
$style->background = empty($options[$prefix . 'background']) ? $composer[$type . '_background_color'] : $options[$prefix . 'background'];
|
658 |
+
}
|
659 |
+
return $style;
|
660 |
+
}
|
661 |
+
|
662 |
+
static function get_button_options($options, $prefix, $composer) {
|
663 |
+
$button_options = [];
|
664 |
+
$scale = 1;
|
665 |
+
$button_options['button_font_family'] = empty($options[$prefix . '_font_family']) ? $composer['button_font_family'] : $options[$prefix . '_font_family'];
|
666 |
+
$button_options['button_font_size'] = empty($options[$prefix . '_font_size']) ? round($composer['button_font_size'] * $scale) : $options[$prefix . '_font_size'];
|
667 |
+
$button_options['button_font_color'] = empty($options[$prefix . '_font_color']) ? $composer['button_font_color'] : $options[$prefix . '_font_color'];
|
668 |
+
$button_options['button_font_weight'] = empty($options[$prefix . '_font_weight']) ? $composer['button_font_weight'] : $options[$prefix . '_font_weight'];
|
669 |
+
$button_options['button_background'] = empty($options[$prefix . '_background']) ? $composer['button_background_color'] : $options[$prefix . '_background'];
|
670 |
+
$button_options['button_align'] = empty($options[$prefix . '_align']) ? 'center' : $options[$prefix . '_align'];
|
671 |
+
$button_options['button_width'] = empty($options[$prefix . '_width']) ? 'center' : $options[$prefix . '_width'];
|
672 |
+
$button_options['button_url'] = empty($options[$prefix . '_url']) ? '#' : $options[$prefix . '_url'];
|
673 |
+
$button_options['button_label'] = empty($options[$prefix . '_label']) ? '' : $options[$prefix . '_label'];
|
674 |
+
|
675 |
+
return $button_options;
|
676 |
+
}
|
677 |
+
|
678 |
+
static function convert_to_text($html) {
|
679 |
+
if (!class_exists('DOMDocument')) {
|
680 |
+
return '';
|
681 |
+
}
|
682 |
+
|
683 |
+
if (!function_exists('ctype_space')) {
|
684 |
+
return '';
|
685 |
+
}
|
686 |
+
|
687 |
+
// Replace '&' with '&' in URLs to avoid warnings about inavlid entities from loadHTML()
|
688 |
+
// Todo: make this more general using a regular expression
|
689 |
+
//$logger = PlaintextNewsletterAddon::$instance->get_logger();
|
690 |
+
//$logger->debug('html="' . $html . '"');
|
691 |
+
$html = str_replace(
|
692 |
+
array('&nk=', '&nek=', '&id='),
|
693 |
+
array('&nk=', '&nek=', '&id='),
|
694 |
+
$html);
|
695 |
+
//$logger->debug('new html="' . $html . '"');
|
696 |
+
//
|
697 |
+
$output = '';
|
698 |
+
|
699 |
+
// Prevents warnings for problems with the HTML
|
700 |
+
if (function_exists('libxml_use_internal_errors')) {
|
701 |
+
libxml_use_internal_errors(true);
|
702 |
+
}
|
703 |
+
$dom = new DOMDocument();
|
704 |
+
$r = $dom->loadHTML('<?xml encoding="utf-8" ?>' . $html);
|
705 |
+
if (!$r) {
|
706 |
+
return '';
|
707 |
+
}
|
708 |
+
$bodylist = $dom->getElementsByTagName('body');
|
709 |
+
// Of course it should be a single element
|
710 |
+
foreach ($bodylist as $body) {
|
711 |
+
self::process_dom_element($body, $output);
|
712 |
+
}
|
713 |
+
return $output;
|
714 |
+
}
|
715 |
+
|
716 |
+
static function process_dom_element(DOMElement $parent, &$output) {
|
717 |
+
foreach ($parent->childNodes as $node) {
|
718 |
+
if (is_a($node, 'DOMElement') && ($node->tagName != 'style')) {
|
719 |
+
|
720 |
+
if ($node->tagName == 'br') {
|
721 |
+
$output .= "\n";
|
722 |
+
continue;
|
723 |
+
}
|
724 |
+
|
725 |
+
self::process_dom_element($node, $output);
|
726 |
+
|
727 |
+
if ($node->tagName == 'li') {
|
728 |
+
if ((strlen($output) >= 1) && (substr($output, -1) != "\n")) {
|
729 |
+
$output .= "\n";
|
730 |
+
}
|
731 |
+
continue;
|
732 |
+
}
|
733 |
+
|
734 |
+
// If the containing tag was a block level tag, we add a couple of line ending
|
735 |
+
if ($node->tagName == 'p' || $node->tagName == 'div' || $node->tagName == 'td') {
|
736 |
+
// Avoid more than one blank line between elements
|
737 |
+
if ((strlen($output) >= 2) && (substr($output, -2) != "\n\n")) {
|
738 |
+
$output .= "\n\n";
|
739 |
+
}
|
740 |
+
}
|
741 |
+
|
742 |
+
if ($node->tagName == 'a') {
|
743 |
+
// Check if the children is an image
|
744 |
+
if (is_a($node->childNodes[0], 'DOMElement')) {
|
745 |
+
if ($node->childNodes[0]->tagName == 'img') {
|
746 |
+
continue;
|
747 |
+
}
|
748 |
+
}
|
749 |
+
$output .= ' (' . $node->getAttribute('href') . ') ';
|
750 |
+
continue;
|
751 |
+
} elseif ($node->tagName == 'img') {
|
752 |
+
$output .= $node->getAttribute('alt');
|
753 |
+
}
|
754 |
+
} elseif (is_a($node, 'DOMText')) {
|
755 |
+
|
756 |
+
// ???
|
757 |
+
$decoded = utf8_decode($node->wholeText);
|
758 |
+
//$decoded = trim(html_entity_decode($node->wholeText));
|
759 |
+
// We could avoid ctype_*
|
760 |
+
if (ctype_space($decoded)) {
|
761 |
+
// Append blank only if last character output is not blank.
|
762 |
+
if ((strlen($output) > 0) && !ctype_space(substr($output, -1))) {
|
763 |
+
$output .= ' ';
|
764 |
+
}
|
765 |
+
} else {
|
766 |
+
$output .= trim($node->wholeText);
|
767 |
+
$output .= ' ';
|
768 |
+
}
|
769 |
+
}
|
770 |
+
}
|
771 |
+
}
|
772 |
+
|
773 |
+
}
|
774 |
+
|
775 |
+
class TNP_Style {
|
776 |
+
|
777 |
+
var $font_family;
|
778 |
+
var $font_size;
|
779 |
+
var $font_weight;
|
780 |
+
var $font_color;
|
781 |
+
var $background;
|
782 |
+
|
783 |
+
function echo_css($scale = 1.0) {
|
784 |
+
echo 'font-size: ', round($this->font_size * $scale), 'px;';
|
785 |
+
echo 'font-family: ', $this->font_family, ';';
|
786 |
+
echo 'font-weight: ', $this->font_weight, ';';
|
787 |
+
echo 'color: ', $this->font_color, ';';
|
788 |
+
}
|
789 |
+
|
790 |
+
}
|
791 |
+
|
792 |
+
/**
|
793 |
+
* Generate multicolumn and responsive html template for email.
|
794 |
+
* Initialize class with max columns per row and start to add cells.
|
795 |
+
*/
|
796 |
+
class TNP_Composer_Grid_System {
|
797 |
+
|
798 |
+
/**
|
799 |
+
* @var TNP_Composer_Grid_Row[]
|
800 |
+
*/
|
801 |
+
private $rows;
|
802 |
+
|
803 |
+
/**
|
804 |
+
* @var int
|
805 |
+
*/
|
806 |
+
private $cells_per_row;
|
807 |
+
|
808 |
+
/**
|
809 |
+
* @var int
|
810 |
+
*/
|
811 |
+
private $cells_counter;
|
812 |
+
|
813 |
+
/**
|
814 |
+
* TNP_Composer_Grid_System constructor.
|
815 |
+
*
|
816 |
+
* @param int $columns_per_row Max columns per row
|
817 |
+
*/
|
818 |
+
public function __construct($columns_per_row) {
|
819 |
+
$this->cells_per_row = $columns_per_row;
|
820 |
+
$this->cells_counter = 0;
|
821 |
+
$this->rows = [];
|
822 |
+
}
|
823 |
+
|
824 |
+
public function __toString() {
|
825 |
+
return $this->render();
|
826 |
+
}
|
827 |
+
|
828 |
+
/**
|
829 |
+
* Add cell to grid
|
830 |
+
*
|
831 |
+
* @param TNP_Composer_Grid_Cell $cell
|
832 |
+
*/
|
833 |
+
public function add_cell($cell) {
|
834 |
+
|
835 |
+
if ($this->cells_counter % $this->cells_per_row === 0) {
|
836 |
+
$this->add_row(new TNP_Composer_Grid_Row());
|
837 |
+
}
|
838 |
+
|
839 |
+
$row_idx = (int) floor($this->cells_counter / $this->cells_per_row);
|
840 |
+
$this->rows[$row_idx]->add_cell($cell);
|
841 |
+
$this->cells_counter++;
|
842 |
+
}
|
843 |
+
|
844 |
+
private function add_row($row) {
|
845 |
+
$this->rows[] = $row;
|
846 |
+
}
|
847 |
+
|
848 |
+
public function render() {
|
849 |
+
|
850 |
+
$str = '';
|
851 |
+
foreach ($this->rows as $row) {
|
852 |
+
$str .= $row->render();
|
853 |
+
}
|
854 |
+
|
855 |
+
return $str;
|
856 |
+
}
|
857 |
+
|
858 |
+
}
|
859 |
+
|
860 |
+
/**
|
861 |
+
* Class TNP_Composer_Grid_Row
|
862 |
+
*/
|
863 |
+
class TNP_Composer_Grid_Row {
|
864 |
+
|
865 |
+
/**
|
866 |
+
* @var TNP_Composer_Grid_Cell[]
|
867 |
+
*/
|
868 |
+
private $cells;
|
869 |
+
|
870 |
+
public function __construct(...$cells) {
|
871 |
+
if (!empty($cells)) {
|
872 |
+
foreach ($cells as $cell) {
|
873 |
+
$this->add_cell($cell);
|
874 |
+
}
|
875 |
+
}
|
876 |
+
}
|
877 |
+
|
878 |
+
/**
|
879 |
+
* @param TNP_Composer_Grid_Cell $cell
|
880 |
+
*/
|
881 |
+
public function add_cell($cell) {
|
882 |
+
$this->cells[] = $cell;
|
883 |
+
}
|
884 |
+
|
885 |
+
public function render() {
|
886 |
+
$rendered_cells = '';
|
887 |
+
$column_percentage_width = round(100 / $this->cells_count(), 0, PHP_ROUND_HALF_DOWN) . '%';
|
888 |
+
foreach ($this->cells as $cell) {
|
889 |
+
$rendered_cells .= $cell->render(['width' => $column_percentage_width]);
|
890 |
+
}
|
891 |
+
|
892 |
+
$row_template = $this->get_template();
|
893 |
+
|
894 |
+
return str_replace('TNP_ROW_CONTENT_PH', $rendered_cells, $row_template);
|
895 |
+
}
|
896 |
+
|
897 |
+
private function cells_count() {
|
898 |
+
return count($this->cells);
|
899 |
+
}
|
900 |
+
|
901 |
+
private function get_template() {
|
902 |
+
return "<table border='0' cellpadding='0' cellspacing='0' width='100%'><tbody><tr><td>TNP_ROW_CONTENT_PH</td></tr></tbody></table>";
|
903 |
+
}
|
904 |
+
|
905 |
+
}
|
906 |
+
|
907 |
+
/**
|
908 |
+
* Class TNP_Composer_Grid_Cell
|
909 |
+
*/
|
910 |
+
class TNP_Composer_Grid_Cell {
|
911 |
+
|
912 |
+
/**
|
913 |
+
* @var string
|
914 |
+
*/
|
915 |
+
private $content;
|
916 |
+
|
917 |
+
/**
|
918 |
+
* @var array
|
919 |
+
*/
|
920 |
+
public $args;
|
921 |
+
|
922 |
+
public function __construct($content = null, $args = []) {
|
923 |
+
$default_args = [
|
924 |
+
'width' => '100%',
|
925 |
+
'class' => '',
|
926 |
+
'align' => 'left',
|
927 |
+
'valign' => 'top'
|
928 |
+
];
|
929 |
+
|
930 |
+
$this->args = array_merge($default_args, $args);
|
931 |
+
|
932 |
+
$this->content = $content ? $content : '';
|
933 |
+
}
|
934 |
+
|
935 |
+
public function add_content($content) {
|
936 |
+
$this->content .= $content;
|
937 |
+
}
|
938 |
+
|
939 |
+
public function render($args) {
|
940 |
+
$this->args = array_merge($this->args, $args);
|
941 |
+
|
942 |
+
$column_template = $this->get_template();
|
943 |
+
$column = str_replace(
|
944 |
+
[
|
945 |
+
'TNP_ALIGN_PH',
|
946 |
+
'TNP_VALIGN_PH',
|
947 |
+
'TNP_WIDTH_PH',
|
948 |
+
'TNP_CLASS_PH',
|
949 |
+
'TNP_COLUMN_CONTENT_PH'
|
950 |
+
], [
|
951 |
+
$this->args['align'],
|
952 |
+
$this->args['valign'],
|
953 |
+
$this->args['width'],
|
954 |
+
$this->args['class'],
|
955 |
+
$this->content
|
956 |
+
], $column_template);
|
957 |
+
|
958 |
+
return $column;
|
959 |
+
}
|
960 |
+
|
961 |
+
private function get_template() {
|
962 |
+
return "<table border='0' cellpadding='0' cellspacing='0' width='TNP_WIDTH_PH' align='left' style='table-layout: fixed;' class='responsive'>
|
963 |
+
<tbody>
|
964 |
+
<tr>
|
965 |
+
<td border='0' style='padding: 20px 10px 40px;' align='TNP_ALIGN_PH' valign='TNP_VALIGN_PH' class='TNP_CLASS_PH'>
|
966 |
+
TNP_COLUMN_CONTENT_PH
|
967 |
+
</td>
|
968 |
+
</tr>
|
969 |
+
</tbody>
|
970 |
+
</table>";
|
971 |
+
}
|
972 |
+
|
973 |
+
}
|
974 |
+
|
975 |
+
class TNP_Composer_Component_Factory {
|
976 |
+
|
977 |
+
private $options;
|
978 |
+
|
979 |
+
/**
|
980 |
+
* TNP_Composer_Component_Factory constructor.
|
981 |
+
*
|
982 |
+
* @param Controller$controller
|
983 |
+
*/
|
984 |
+
public function __construct($controller) {
|
985 |
+
|
986 |
+
}
|
987 |
+
|
988 |
+
function heading() {
|
989 |
+
|
990 |
+
}
|
991 |
+
|
992 |
+
function paragraph() {
|
993 |
+
|
994 |
+
}
|
995 |
+
|
996 |
+
function link() {
|
997 |
+
|
998 |
+
}
|
999 |
+
|
1000 |
+
function button() {
|
1001 |
+
|
1002 |
+
}
|
1003 |
+
|
1004 |
+
function image() {
|
1005 |
+
|
1006 |
+
}
|
1007 |
+
|
1008 |
+
}
|
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: 7.5.
|
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.
|
@@ -37,7 +37,7 @@ if (version_compare(phpversion(), '5.6', '<')) {
|
|
37 |
Â
return;
|
38 |
Â
}
|
39 |
Â
|
40 |
-
define('NEWSLETTER_VERSION', '7.5.
|
41 |
Â
|
42 |
Â
global $newsletter, $wpdb;
|
43 |
Â
|
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: 7.5.7
|
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.
|
37 |
Â
return;
|
38 |
Â
}
|
39 |
Â
|
40 |
+
define('NEWSLETTER_VERSION', '7.5.7');
|
41 |
Â
|
42 |
Â
global $newsletter, $wpdb;
|
43 |
Â
|
readme.txt
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
Â
=== Newsletter - Send awesome emails from WordPress ===
|
2 |
Â
Tags: newsletter, email marketing, welcome email, signup forms, lead generation, marketing automation
|
3 |
-
Tested up to: 6.1
|
4 |
-
Stable tag: 7.5.
|
5 |
Â
Contributors: satollo,webagile,michael-travan
|
6 |
Â
License: GPLv2 or later
|
7 |
Â
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
@@ -126,6 +126,14 @@ Thank you, The Newsletter Team
|
|
126 |
Â
|
127 |
Â
== Changelog ==
|
128 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
129 |
Â
= 7.5.6 =
|
130 |
Â
|
131 |
Â
* Added new filter for multilanguage support for GTranslate (experimental)
|
1 |
Â
=== Newsletter - Send awesome emails from WordPress ===
|
2 |
Â
Tags: newsletter, email marketing, welcome email, signup forms, lead generation, marketing automation
|
3 |
+
Tested up to: 6.1.1
|
4 |
+
Stable tag: 7.5.7
|
5 |
Â
Contributors: satollo,webagile,michael-travan
|
6 |
Â
License: GPLv2 or later
|
7 |
Â
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
126 |
Â
|
127 |
Â
== Changelog ==
|
128 |
Â
|
129 |
+
= 7.5.7 =
|
130 |
+
|
131 |
+
* Check on ctype_space function (there are installation without it)
|
132 |
+
* Improved the html-2-text conversion
|
133 |
+
* Added language to the export
|
134 |
+
* Status labels fixed on subscriber search and edit panel
|
135 |
+
* Stripped HTML tags on block generated subjects
|
136 |
+
|
137 |
Â
= 7.5.6 =
|
138 |
Â
|
139 |
Â
* Added new filter for multilanguage support for GTranslate (experimental)
|
tnp-header.php
CHANGED
@@ -1,349 +1,349 @@
|
|
1 |
-
<?php
|
2 |
-
global $current_user, $wpdb;
|
3 |
-
|
4 |
-
defined('ABSPATH') || exit;
|
5 |
-
|
6 |
-
$dismissed = get_option('newsletter_dismissed', []);
|
7 |
-
|
8 |
-
$user_count = Newsletter::instance()->get_user_count();
|
9 |
-
|
10 |
-
$is_administrator = current_user_can('administrator');
|
11 |
-
|
12 |
-
function newsletter_print_entries($group) {
|
13 |
-
$entries = apply_filters('newsletter_menu_' . $group, array());
|
14 |
-
if (!$entries) {
|
15 |
-
return;
|
16 |
-
}
|
17 |
-
|
18 |
-
foreach ($entries as &$entry) {
|
19 |
-
echo '<li><a href="', $entry['url'], '">', $entry['label'];
|
20 |
-
if (!empty($entry['description'])) {
|
21 |
-
echo '<small>', $entry['description'], '</small>';
|
22 |
-
}
|
23 |
-
echo '</a></li>';
|
24 |
-
}
|
25 |
-
}
|
26 |
-
|
27 |
-
// Check the status to show a warning if needed
|
28 |
-
$status_options = Newsletter::instance()->get_options('status');
|
29 |
-
$warning = false;
|
30 |
-
|
31 |
-
//$warning |= empty($status_options['mail']);
|
32 |
-
|
33 |
-
$current_user_email = ''; //$current_user->user_email;
|
34 |
-
//if (strpos($current_user_email, 'admin@') === 0) {
|
35 |
-
// $current_user_email = '';
|
36 |
-
//}
|
37 |
-
?>
|
38 |
-
|
39 |
-
<div class="tnp-drowpdown" id="tnp-header">
|
40 |
-
<a href="?page=newsletter_main_index"><img src="<?php echo plugins_url('newsletter'); ?>/admin/images/logo-red.png" class="tnp-header-logo" style="vertical-align: bottom;"></a>
|
41 |
-
<ul>
|
42 |
-
<li><a href="#"><i class="fas fa-users"></i> <?php _e('Subscribers', 'newsletter') ?> <i class="fas fa-chevron-down"></i></a>
|
43 |
-
<ul>
|
44 |
-
<li>
|
45 |
-
<a href="?page=newsletter_users_index"><i class="fas fa-search"></i> <?php _e('Search And Edit', 'newsletter') ?>
|
46 |
-
<small><?php _e('Add, edit, search', 'newsletter') ?></small></a>
|
47 |
-
</li>
|
48 |
-
|
49 |
-
<li>
|
50 |
-
<a href="?page=newsletter_profile_index"><i class="fas fa-user-circle"></i> <?php _e('Profile page', 'newsletter') ?>
|
51 |
-
<small><?php _e('The subscriber personal profile editing panel', 'newsletter') ?></small></a>
|
52 |
-
</li>
|
53 |
-
|
54 |
-
<?php if (!class_exists('NewsletterImport')) { ?>
|
55 |
-
<li>
|
56 |
-
<a href="?page=newsletter_users_import"><i class="fas fa-upload"></i> <?php _e('Import', 'newsletter') ?>
|
57 |
-
<small><?php _e('Import from external sources', 'newsletter') ?></small></a>
|
58 |
-
</li>
|
59 |
-
<?php } ?>
|
60 |
-
|
61 |
-
<li>
|
62 |
-
<a href="?page=newsletter_users_export"><i class="fas fa-download"></i> <?php _e('Export', 'newsletter') ?>
|
63 |
-
<small><?php _e('Export your subscribers list', 'newsletter') ?></small></a>
|
64 |
-
</li>
|
65 |
-
|
66 |
-
<li>
|
67 |
-
<a href="?page=newsletter_users_massive"><i class="fas fa-wrench"></i> <?php _e('Maintenance', 'newsletter') ?>
|
68 |
-
<small><?php _e('Massive actions: change list, clean up, ...', 'newsletter') ?></small></a>
|
69 |
-
</li>
|
70 |
-
|
71 |
-
<li>
|
72 |
-
<a href="?page=newsletter_users_statistics"><i class="fas fa-chart-bar"></i> <?php _e('Statistics', 'newsletter') ?>
|
73 |
-
<small><?php _e('All about your subscribers', 'newsletter') ?></small></a>
|
74 |
-
</li>
|
75 |
-
|
76 |
-
<?php newsletter_print_entries('subscribers') ?>
|
77 |
-
</ul>
|
78 |
-
</li>
|
79 |
-
<li><a href="#"><i class="fas fa-list"></i> <?php _e('List Building', 'newsletter') ?> <i class="fas fa-chevron-down"></i></a>
|
80 |
-
<ul>
|
81 |
-
<li>
|
82 |
-
<a href="?page=newsletter_subscription_profile"><i class="fas fa-check-square"></i> <?php _e('Subscription Form Fields, Buttons, Labels', 'newsletter') ?>
|
83 |
-
<small><?php _e('When and what data to collect', 'newsletter') ?></small></a>
|
84 |
-
</li>
|
85 |
-
|
86 |
-
<li>
|
87 |
-
<a href="?page=newsletter_subscription_options"><i class="fas fa-sign-in-alt"></i> <?php _e('Subscription', 'newsletter') ?>
|
88 |
-
<small><?php _e('The subscription process in detail', 'newsletter') ?></small></a>
|
89 |
-
</li>
|
90 |
-
|
91 |
-
<li>
|
92 |
-
<a href="?page=newsletter_subscription_lists"><i class="fas fa-th-list"></i> <?php _e('Lists', 'newsletter') ?>
|
93 |
-
<small><?php _e('Profile the subscribers for a better targeting', 'newsletter') ?></small></a>
|
94 |
-
</li>
|
95 |
-
|
96 |
-
<li>
|
97 |
-
<a href="?page=newsletter_subscription_antibot"><i class="fas fa-lock"></i> <?php _e('Security', 'newsletter') ?>
|
98 |
-
<small><?php _e('Spam subscriptions control', 'newsletter') ?></small></a>
|
99 |
-
</li>
|
100 |
-
|
101 |
-
<li>
|
102 |
-
<a href="?page=newsletter_unsubscription_index"><i class="fas fa-sign-out-alt"></i> <?php _e('Unsubscription', 'newsletter') ?>
|
103 |
-
<small><?php _e('How to give the last goodbye (or avoid it!)', 'newsletter') ?></small></a>
|
104 |
-
</li>
|
105 |
-
|
106 |
-
<?php
|
107 |
-
newsletter_print_entries('subscription');
|
108 |
-
?>
|
109 |
-
</ul>
|
110 |
-
</li>
|
111 |
-
|
112 |
-
<li>
|
113 |
-
<a href="#"><i class="fas fa-newspaper"></i> <?php _e('Newsletters', 'newsletter') ?> <i class="fas fa-chevron-down"></i></a>
|
114 |
-
<ul>
|
115 |
-
<li>
|
116 |
-
<a href="?page=newsletter_emails_composer"><i class="fas fa-plus"></i> <?php _e('Create newsletter', 'newsletter') ?>
|
117 |
-
<small><?php _e('Start your new campaign', 'newsletter') ?></small></a>
|
118 |
-
</li>
|
119 |
-
|
120 |
-
<li>
|
121 |
-
<a href="?page=newsletter_emails_index"><i class="fas fa-newspaper"></i> <?php _e('Newsletters', 'newsletter') ?>
|
122 |
-
<small><?php _e('The classic "write & send" newsletters', 'newsletter') ?></small></a>
|
123 |
-
</li>
|
124 |
-
|
125 |
-
<li>
|
126 |
-
<a href="<?php echo NewsletterStatistics::instance()->get_index_url() ?>"><i class="fas fa-chart-bar"></i> <?php _e('Statistics', 'newsletter') ?>
|
127 |
-
<small><?php _e('Tracking configuration and basic data', 'newsletter') ?></small></a>
|
128 |
-
</li>
|
129 |
-
<?php
|
130 |
-
newsletter_print_entries('newsletters');
|
131 |
-
?>
|
132 |
-
</ul>
|
133 |
-
</li>
|
134 |
-
|
135 |
-
<li>
|
136 |
-
<a href="#"><i class="fas fa-cog"></i> <?php _e('Settings', 'newsletter') ?> <i class="fas fa-chevron-down"></i></a>
|
137 |
-
<ul>
|
138 |
-
<?php if ($is_administrator) { ?>
|
139 |
-
<li>
|
140 |
-
<a href="?page=newsletter_main_main"><i class="fas fa-cogs"></i> <?php _e('General Settings', 'newsletter') ?>
|
141 |
-
<small><?php _e('Delivery speed, sender details, ...', 'newsletter') ?></small></a>
|
142 |
-
</li>
|
143 |
-
<?php if (!class_exists('NewsletterSmtp')) { ?>
|
144 |
-
<li>
|
145 |
-
<a href="?page=newsletter_main_smtp"><i class="fas fa-server"></i> <?php _e('SMTP', 'newsletter') ?>
|
146 |
-
<small><?php _e('External mail server', 'newsletter') ?></small>
|
147 |
-
</a>
|
148 |
-
</li>
|
149 |
-
<?php } ?>
|
150 |
-
<?php } ?>
|
151 |
-
|
152 |
-
<li>
|
153 |
-
<a href="?page=newsletter_main_info"><i class="fas fa-info"></i> <?php _e('Company Info', 'newsletter') ?>
|
154 |
-
<small><?php _e('Social, address, logo and general info', 'newsletter') ?></small></a>
|
155 |
-
</li>
|
156 |
-
|
157 |
-
<li>
|
158 |
-
<a href="?page=newsletter_subscription_template"><i class="fas fa-file-alt"></i> <?php _e('Messages Template', 'newsletter') ?>
|
159 |
-
<small><?php _e('Change the look of your service emails', 'newsletter') ?></small></a>
|
160 |
-
</li>
|
161 |
-
|
162 |
-
<?php
|
163 |
-
newsletter_print_entries('settings');
|
164 |
-
?>
|
165 |
-
</ul>
|
166 |
-
</li>
|
167 |
-
|
168 |
-
<?php if ($is_administrator) { ?>
|
169 |
-
<li>
|
170 |
-
<a href="#"><i class="fas fa-thermometer"></i> <?php _e('System', 'newsletter') ?>
|
171 |
-
<?php if ($warning) { ?>
|
172 |
-
<i class="fas fa-exclamation-triangle" style="color: red;"></i>
|
173 |
-
<?php } ?>
|
174 |
-
</a>
|
175 |
-
<ul>
|
176 |
-
<li>
|
177 |
-
<a href="<?php echo admin_url('site-health.php') ?> "><i class="fas fa-file"></i> <?php _e('Site health') ?>
|
178 |
-
<small><?php _e('WP native site health checks', 'newsletter') ?></small></a>
|
179 |
-
</li>
|
180 |
-
<li>
|
181 |
-
<a href="?page=newsletter_system_delivery"><i class="fas fa-file"></i> <?php _e('Delivery Diagnostic', 'newsletter') ?>
|
182 |
-
<small><?php _e('Delivery analysis and test', 'newsletter') ?></small></a>
|
183 |
-
</li>
|
184 |
-
<li>
|
185 |
-
<a href="?page=newsletter_system_scheduler"><i class="fas fa-robot"></i> <?php _e('Scheduler', 'newsletter') ?>
|
186 |
-
<small><?php _e('WordPress background jobs', 'newsletter') ?></small></a>
|
187 |
-
</li>
|
188 |
-
<li>
|
189 |
-
<a href="?page=newsletter_system_status"><i class="fas fa-file"></i> <?php _e('Status', 'newsletter') ?>
|
190 |
-
<small><?php _e('Checks and parameters', 'newsletter') ?></small></a>
|
191 |
-
</li>
|
192 |
-
|
193 |
-
<li>
|
194 |
-
<a href="?page=newsletter_system_logs"><i class="fas fa-file"></i> <?php _e('Logs', 'newsletter') ?>
|
195 |
-
<small><?php _e('Plugin and addons logs', 'newsletter') ?></small></a>
|
196 |
-
</li>
|
197 |
-
<li>
|
198 |
-
<a href="https://www.thenewsletterplugin.com/documentation/developers/backup-recovery/" target="_blank"><i class="fas fa-file"></i> <?php _e('Backup', 'newsletter') ?>
|
199 |
-
<small><?php _e('How to backup, recovery, delete', 'newsletter') ?></small></a>
|
200 |
-
</li>
|
201 |
-
</ul>
|
202 |
-
</li>
|
203 |
-
<?php } ?>
|
204 |
-
|
205 |
-
<?php
|
206 |
-
$license_data = Newsletter::instance()->get_license_data();
|
207 |
-
$premium_url = 'https://www.thenewsletterplugin.com/premium?utm_source=header&utm_medium=link&utm_campaign=plugin&utm_content=' . urlencode($_GET['page']);
|
208 |
-
?>
|
209 |
-
|
210 |
-
<?php if (empty($license_data)) { ?>
|
211 |
-
<?php if (time() < 1638226799) { ?>
|
212 |
-
<li class="tnp-professional-extensions-button" style="background-color: #000; color: #fff; border-color: #FF5F65!important; border-width: 2px !important;"><a href="https://www.thenewsletterplugin.com/premium?utm_source=header&utm_medium=link&utm_campaign=black-friday" target="_blank">
|
213 |
-
<i class="fas fa-trophy"></i> BLACK FRIDAY IS LIVE</a>
|
214 |
-
</li>
|
215 |
-
<?php } else { ?>
|
216 |
-
<li class="tnp-professional-extensions-button"><a href="<?php echo $premium_url ?>" target="_blank">
|
217 |
-
<i class="fas fa-trophy"></i> <?php _e('Get Professional Addons', 'newsletter') ?></a>
|
218 |
-
</li>
|
219 |
-
<?php } ?>
|
220 |
-
<?php } elseif (is_wp_error($license_data)) { ?>
|
221 |
-
<li class="tnp-professional-extensions-button-red">
|
222 |
-
<a href="?page=newsletter_main_main"><i class="fas fa-hand-paper" style="color: white"></i> <?php _e('Unable to check', 'newsletter') ?></a>
|
223 |
-
</li>
|
224 |
-
|
225 |
-
<?php } elseif ($license_data->expire == 0) { ?>
|
226 |
-
<?php if (time() < 1638226799) { ?>
|
227 |
-
<li class="tnp-professional-extensions-button" style="background-color: #000; color: #fff; border-color: #FF5F65!important; border-width: 2px !important;"><a href="https://www.thenewsletterplugin.com/premium?utm_source=header&utm_medium=link&utm_campaign=black-friday" target="_blank">
|
228 |
-
<i class="fas fa-trophy"></i> BLACK FRIDAY IS LIVE</a>
|
229 |
-
</li>
|
230 |
-
<?php } else { ?>
|
231 |
-
<li class="tnp-professional-extensions-button"><a href="<?php echo $premium_url ?>" target="_blank">
|
232 |
-
<i class="fas fa-trophy"></i> <?php _e('Get Professional Addons', 'newsletter') ?></a>
|
233 |
-
</li>
|
234 |
-
<?php } ?>
|
235 |
-
|
236 |
-
<?php } elseif ($license_data->expire < time()) { ?>
|
237 |
-
|
238 |
-
<li class="tnp-professional-extensions-button-red">
|
239 |
-
<a href="?page=newsletter_main_main"><i class="fas fa-hand-paper" style="color: white"></i> <?php _e('License expired', 'newsletter') ?></a>
|
240 |
-
</li>
|
241 |
-
|
242 |
-
<?php } elseif ($license_data->expire >= time()) { ?>
|
243 |
-
|
244 |
-
<?php $p = class_exists('NewsletterExtensions') ? 'newsletter_extensions_index' : 'newsletter_main_extensions'; ?>
|
245 |
-
<li class="tnp-professional-extensions-button">
|
246 |
-
<a href="?page=<?php echo $p ?>"><i class="fas fa-check-square"></i> <?php _e('License active', 'newsletter') ?></a>
|
247 |
-
</li>
|
248 |
-
|
249 |
-
<?php } ?>
|
250 |
-
</ul>
|
251 |
-
</div>
|
252 |
-
|
253 |
-
<?php if (isset($_GET['debug']) || !isset($dismissed['newsletter-shortcode'])) { ?>
|
254 |
-
<?php
|
255 |
-
// Check of Newsletter dedicated page
|
256 |
-
if (!empty(Newsletter::instance()->options['page'])) {
|
257 |
-
if (get_post_status(Newsletter::instance()->options['page']) === 'publish') {
|
258 |
-
$content = get_post_field('post_content', Newsletter::instance()->options['page']);
|
259 |
-
// With and without attributes
|
260 |
-
if (strpos($content, '[newsletter]') === false && strpos($content, '[newsletter ') === false) {
|
261 |
-
?>
|
262 |
-
<div class="tnp-notice">
|
263 |
-
<a href="<?php echo esc_attr($_SERVER['REQUEST_URI']) . '&noheader=1&dismiss=newsletter-shortcode' ?>" class="tnp-dismiss">×</a>
|
264 |
-
The Newsletter dedicated page does not contain the [newsletter] shortcode. If you're using a visual composer it could be ok.
|
265 |
-
<a href="<?php echo site_url('/wp-admin/post.php') ?>?post=<?php echo esc_attr(Newsletter::instance()->options['page']) ?>&action=edit"><strong>Edit the page</strong></a>.
|
266 |
-
|
267 |
-
</div>
|
268 |
-
<?php
|
269 |
-
}
|
270 |
-
}
|
271 |
-
}
|
272 |
-
?>
|
273 |
-
<?php } ?>
|
274 |
-
|
275 |
-
<?php if (isset($_GET['debug']) || !isset($dismissed['rate']) && $user_count > 300) { ?>
|
276 |
-
<div class="tnp-notice">
|
277 |
-
<a href="<?php echo esc_attr($_SERVER['REQUEST_URI']) . '&noheader=1&dismiss=rate' ?>" class="tnp-dismiss">×</a>
|
278 |
-
|
279 |
-
We never asked before and we're curious: <a href="http://wordpress.org/plugins/newsletter/" target="_blank">would you rate this plugin</a>?
|
280 |
-
(few seconds required - account on WordPress.org required, every blog owner should have one...). <strong>Really appreciated, The Newsletter Team</strong>.
|
281 |
-
|
282 |
-
</div>
|
283 |
-
<?php } ?>
|
284 |
-
|
285 |
-
<?php if (isset($_GET['debug']) || !isset($dismissed['newsletter-page']) && empty(Newsletter::instance()->options['page'])) { ?>
|
286 |
-
<div class="tnp-notice">
|
287 |
-
<a href="<?php echo esc_attr($_SERVER['REQUEST_URI']) . '&noheader=1&dismiss=newsletter-page' ?>" class="tnp-dismiss">×</a>
|
288 |
-
|
289 |
-
You should create a blog page to show the subscription form and the subscription messages. Go to the
|
290 |
-
<a href="?page=newsletter_main_main">general settings panel</a> to configure it.
|
291 |
-
|
292 |
-
</div>
|
293 |
-
<?php } ?>
|
294 |
-
|
295 |
-
<?php if (isset($_GET['debug']) || !isset($dismissed['newsletter-subscribe']) && get_option('newsletter_install_time') && get_option('newsletter_install_time') < time() - 86400 * 15) { ?>
|
296 |
-
<div class="tnp-notice">
|
297 |
-
<a href="<?php echo esc_attr($_SERVER['REQUEST_URI']) . '&noheader=1&dismiss=newsletter-subscribe' ?>" class="tnp-dismiss">×</a>
|
298 |
-
Subscribe to our news, promotions and getting started lessons!
|
299 |
-
Proceeding you agree to the <a href="https://www.thenewsletterplugin.com/privacy" target="_blank">privacy policy</a>.
|
300 |
-
<br>
|
301 |
-
<form action="https://www.thenewsletterplugin.com/?na=s" target="_blank" method="post">
|
302 |
-
<input type="hidden" value="plugin-header" name="nr">
|
303 |
-
<input type="hidden" value="3" name="nl[]">
|
304 |
-
<input type="hidden" value="1" name="nl[]">
|
305 |
-
<input type="hidden" value="double" name="optin">
|
306 |
-
<input type="email" name="ne" value="<?php echo esc_attr($current_user_email) ?>">
|
307 |
-
<input type="submit" value="<?php esc_attr_e('Subscribe', 'newsletter') ?>">
|
308 |
-
</form>
|
309 |
-
</div>
|
310 |
-
<?php } ?>
|
311 |
-
|
312 |
-
<?php
|
313 |
-
if (!defined('NEWSLETTER_CRON_WARNINGS') || NEWSLETTER_CRON_WARNINGS) {
|
314 |
-
$x = NewsletterSystem::instance()->get_job_status();
|
315 |
-
if ($x !== NewsletterSystem::JOB_OK) {
|
316 |
-
echo '<div class="tnpc-warning">There are issues with the delivery engine. Please <a href="?page=newsletter_system_scheduler">check them here</a>.</div>';
|
317 |
-
}
|
318 |
-
}
|
319 |
-
?>
|
320 |
-
|
321 |
-
<?php
|
322 |
-
if ($_GET['page'] !== 'newsletter_emails_edit') {
|
323 |
-
|
324 |
-
$last_failed_newsletters = Newsletter::instance()->get_emails_by_status(TNP_Email::STATUS_ERROR);
|
325 |
-
if ($last_failed_newsletters) {
|
326 |
-
$c = new NewsletterControls();
|
327 |
-
foreach ($last_failed_newsletters as $n) {
|
328 |
-
echo '<div class="tnpc-error">';
|
329 |
-
printf(__('Newsletter "%s" stopped by fatal error.', 'newsletter'), esc_html($n->subject));
|
330 |
-
echo ' ';
|
331 |
-
|
332 |
-
$c->btn_link('?page=newsletter_emails_edit&id=' . $n->id, __('Check', 'newsletter'));
|
333 |
-
echo '</div>';
|
334 |
-
}
|
335 |
-
}
|
336 |
-
}
|
337 |
-
?>
|
338 |
-
|
339 |
-
<div id="tnp-notification">
|
340 |
-
<?php
|
341 |
-
if (isset($controls)) {
|
342 |
-
$controls->show();
|
343 |
-
$controls->messages = '';
|
344 |
-
$controls->errors = '';
|
345 |
-
}
|
346 |
-
?>
|
347 |
-
</div>
|
348 |
-
|
349 |
-
|
1 |
+
<?php
|
2 |
+
global $current_user, $wpdb;
|
3 |
+
|
4 |
+
defined('ABSPATH') || exit;
|
5 |
+
|
6 |
+
$dismissed = get_option('newsletter_dismissed', []);
|
7 |
+
|
8 |
+
$user_count = Newsletter::instance()->get_user_count();
|
9 |
+
|
10 |
+
$is_administrator = current_user_can('administrator');
|
11 |
+
|
12 |
+
function newsletter_print_entries($group) {
|
13 |
+
$entries = apply_filters('newsletter_menu_' . $group, array());
|
14 |
+
if (!$entries) {
|
15 |
+
return;
|
16 |
+
}
|
17 |
+
|
18 |
+
foreach ($entries as &$entry) {
|
19 |
+
echo '<li><a href="', $entry['url'], '">', $entry['label'];
|
20 |
+
if (!empty($entry['description'])) {
|
21 |
+
echo '<small>', $entry['description'], '</small>';
|
22 |
+
}
|
23 |
+
echo '</a></li>';
|
24 |
+
}
|
25 |
+
}
|
26 |
+
|
27 |
+
// Check the status to show a warning if needed
|
28 |
+
$status_options = Newsletter::instance()->get_options('status');
|
29 |
+
$warning = false;
|
30 |
+
|
31 |
+
//$warning |= empty($status_options['mail']);
|
32 |
+
|
33 |
+
$current_user_email = ''; //$current_user->user_email;
|
34 |
+
//if (strpos($current_user_email, 'admin@') === 0) {
|
35 |
+
// $current_user_email = '';
|
36 |
+
//}
|
37 |
+
?>
|
38 |
+
|
39 |
+
<div class="tnp-drowpdown" id="tnp-header">
|
40 |
+
<a href="?page=newsletter_main_index"><img src="<?php echo plugins_url('newsletter'); ?>/admin/images/logo-red.png" class="tnp-header-logo" style="vertical-align: bottom;"></a>
|
41 |
+
<ul>
|
42 |
+
<li><a href="#"><i class="fas fa-users"></i> <?php _e('Subscribers', 'newsletter') ?> <i class="fas fa-chevron-down"></i></a>
|
43 |
+
<ul>
|
44 |
+
<li>
|
45 |
+
<a href="?page=newsletter_users_index"><i class="fas fa-search"></i> <?php _e('Search And Edit', 'newsletter') ?>
|
46 |
+
<small><?php _e('Add, edit, search', 'newsletter') ?></small></a>
|
47 |
+
</li>
|
48 |
+
|
49 |
+
<li>
|
50 |
+
<a href="?page=newsletter_profile_index"><i class="fas fa-user-circle"></i> <?php _e('Profile page', 'newsletter') ?>
|
51 |
+
<small><?php _e('The subscriber personal profile editing panel', 'newsletter') ?></small></a>
|
52 |
+
</li>
|
53 |
+
|
54 |
+
<?php if (!class_exists('NewsletterImport')) { ?>
|
55 |
+
<li>
|
56 |
+
<a href="?page=newsletter_users_import"><i class="fas fa-upload"></i> <?php _e('Import', 'newsletter') ?>
|
57 |
+
<small><?php _e('Import from external sources', 'newsletter') ?></small></a>
|
58 |
+
</li>
|
59 |
+
<?php } ?>
|
60 |
+
|
61 |
+
<li>
|
62 |
+
<a href="?page=newsletter_users_export"><i class="fas fa-download"></i> <?php _e('Export', 'newsletter') ?>
|
63 |
+
<small><?php _e('Export your subscribers list', 'newsletter') ?></small></a>
|
64 |
+
</li>
|
65 |
+
|
66 |
+
<li>
|
67 |
+
<a href="?page=newsletter_users_massive"><i class="fas fa-wrench"></i> <?php _e('Maintenance', 'newsletter') ?>
|
68 |
+
<small><?php _e('Massive actions: change list, clean up, ...', 'newsletter') ?></small></a>
|
69 |
+
</li>
|
70 |
+
|
71 |
+
<li>
|
72 |
+
<a href="?page=newsletter_users_statistics"><i class="fas fa-chart-bar"></i> <?php _e('Statistics', 'newsletter') ?>
|
73 |
+
<small><?php _e('All about your subscribers', 'newsletter') ?></small></a>
|
74 |
+
</li>
|
75 |
+
|
76 |
+
<?php newsletter_print_entries('subscribers') ?>
|
77 |
+
</ul>
|
78 |
+
</li>
|
79 |
+
<li><a href="#"><i class="fas fa-list"></i> <?php _e('List Building', 'newsletter') ?> <i class="fas fa-chevron-down"></i></a>
|
80 |
+
<ul>
|
81 |
+
<li>
|
82 |
+
<a href="?page=newsletter_subscription_profile"><i class="fas fa-check-square"></i> <?php _e('Subscription Form Fields, Buttons, Labels', 'newsletter') ?>
|
83 |
+
<small><?php _e('When and what data to collect', 'newsletter') ?></small></a>
|
84 |
+
</li>
|
85 |
+
|
86 |
+
<li>
|
87 |
+
<a href="?page=newsletter_subscription_options"><i class="fas fa-sign-in-alt"></i> <?php _e('Subscription', 'newsletter') ?>
|
88 |
+
<small><?php _e('The subscription process in detail', 'newsletter') ?></small></a>
|
89 |
+
</li>
|
90 |
+
|
91 |
+
<li>
|
92 |
+
<a href="?page=newsletter_subscription_lists"><i class="fas fa-th-list"></i> <?php _e('Lists', 'newsletter') ?>
|
93 |
+
<small><?php _e('Profile the subscribers for a better targeting', 'newsletter') ?></small></a>
|
94 |
+
</li>
|
95 |
+
|
96 |
+
<li>
|
97 |
+
<a href="?page=newsletter_subscription_antibot"><i class="fas fa-lock"></i> <?php _e('Security', 'newsletter') ?>
|
98 |
+
<small><?php _e('Spam subscriptions control', 'newsletter') ?></small></a>
|
99 |
+
</li>
|
100 |
+
|
101 |
+
<li>
|
102 |
+
<a href="?page=newsletter_unsubscription_index"><i class="fas fa-sign-out-alt"></i> <?php _e('Unsubscription', 'newsletter') ?>
|
103 |
+
<small><?php _e('How to give the last goodbye (or avoid it!)', 'newsletter') ?></small></a>
|
104 |
+
</li>
|
105 |
+
|
106 |
+
<?php
|
107 |
+
newsletter_print_entries('subscription');
|
108 |
+
?>
|
109 |
+
</ul>
|
110 |
+
</li>
|
111 |
+
|
112 |
+
<li>
|
113 |
+
<a href="#"><i class="fas fa-newspaper"></i> <?php _e('Newsletters', 'newsletter') ?> <i class="fas fa-chevron-down"></i></a>
|
114 |
+
<ul>
|
115 |
+
<li>
|
116 |
+
<a href="?page=newsletter_emails_composer"><i class="fas fa-plus"></i> <?php _e('Create newsletter', 'newsletter') ?>
|
117 |
+
<small><?php _e('Start your new campaign', 'newsletter') ?></small></a>
|
118 |
+
</li>
|
119 |
+
|
120 |
+
<li>
|
121 |
+
<a href="?page=newsletter_emails_index"><i class="fas fa-newspaper"></i> <?php _e('Newsletters', 'newsletter') ?>
|
122 |
+
<small><?php _e('The classic "write & send" newsletters', 'newsletter') ?></small></a>
|
123 |
+
</li>
|
124 |
+
|
125 |
+
<li>
|
126 |
+
<a href="<?php echo NewsletterStatistics::instance()->get_index_url() ?>"><i class="fas fa-chart-bar"></i> <?php _e('Statistics', 'newsletter') ?>
|
127 |
+
<small><?php _e('Tracking configuration and basic data', 'newsletter') ?></small></a>
|
128 |
+
</li>
|
129 |
+
<?php
|
130 |
+
newsletter_print_entries('newsletters');
|
131 |
+
?>
|
132 |
+
</ul>
|
133 |
+
</li>
|
134 |
+
|
135 |
+
<li>
|
136 |
+
<a href="#"><i class="fas fa-cog"></i> <?php _e('Settings', 'newsletter') ?> <i class="fas fa-chevron-down"></i></a>
|
137 |
+
<ul>
|
138 |
+
<?php if ($is_administrator) { ?>
|
139 |
+
<li>
|
140 |
+
<a href="?page=newsletter_main_main"><i class="fas fa-cogs"></i> <?php _e('General Settings', 'newsletter') ?>
|
141 |
+
<small><?php _e('Delivery speed, sender details, ...', 'newsletter') ?></small></a>
|
142 |
+
</li>
|
143 |
+
<?php if (!class_exists('NewsletterSmtp')) { ?>
|
144 |
+
<li>
|
145 |
+
<a href="?page=newsletter_main_smtp"><i class="fas fa-server"></i> <?php _e('SMTP', 'newsletter') ?>
|
146 |
+
<small><?php _e('External mail server', 'newsletter') ?></small>
|
147 |
+
</a>
|
148 |
+
</li>
|
149 |
+
<?php } ?>
|
150 |
+
<?php } ?>
|
151 |
+
|
152 |
+
<li>
|
153 |
+
<a href="?page=newsletter_main_info"><i class="fas fa-info"></i> <?php _e('Company Info', 'newsletter') ?>
|
154 |
+
<small><?php _e('Social, address, logo and general info', 'newsletter') ?></small></a>
|
155 |
+
</li>
|
156 |
+
|
157 |
+
<li>
|
158 |
+
<a href="?page=newsletter_subscription_template"><i class="fas fa-file-alt"></i> <?php _e('Messages Template', 'newsletter') ?>
|
159 |
+
<small><?php _e('Change the look of your service emails', 'newsletter') ?></small></a>
|
160 |
+
</li>
|
161 |
+
|
162 |
+
<?php
|
163 |
+
newsletter_print_entries('settings');
|
164 |
+
?>
|
165 |
+
</ul>
|
166 |
+
</li>
|
167 |
+
|
168 |
+
<?php if ($is_administrator) { ?>
|
169 |
+
<li>
|
170 |
+
<a href="#"><i class="fas fa-thermometer"></i> <?php _e('System', 'newsletter') ?>
|
171 |
+
<?php if ($warning) { ?>
|
172 |
+
<i class="fas fa-exclamation-triangle" style="color: red;"></i>
|
173 |
+
<?php } ?>
|
174 |
+
</a>
|
175 |
+
<ul>
|
176 |
+
<li>
|
177 |
+
<a href="<?php echo admin_url('site-health.php') ?> "><i class="fas fa-file"></i> <?php _e('Site health') ?>
|
178 |
+
<small><?php _e('WP native site health checks', 'newsletter') ?></small></a>
|
179 |
+
</li>
|
180 |
+
<li>
|
181 |
+
<a href="?page=newsletter_system_delivery"><i class="fas fa-file"></i> <?php _e('Delivery Diagnostic', 'newsletter') ?>
|
182 |
+
<small><?php _e('Delivery analysis and test', 'newsletter') ?></small></a>
|
183 |
+
</li>
|
184 |
+
<li>
|
185 |
+
<a href="?page=newsletter_system_scheduler"><i class="fas fa-robot"></i> <?php _e('Scheduler', 'newsletter') ?>
|
186 |
+
<small><?php _e('WordPress background jobs', 'newsletter') ?></small></a>
|
187 |
+
</li>
|
188 |
+
<li>
|
189 |
+
<a href="?page=newsletter_system_status"><i class="fas fa-file"></i> <?php _e('Status', 'newsletter') ?>
|
190 |
+
<small><?php _e('Checks and parameters', 'newsletter') ?></small></a>
|
191 |
+
</li>
|
192 |
+
|
193 |
+
<li>
|
194 |
+
<a href="?page=newsletter_system_logs"><i class="fas fa-file"></i> <?php _e('Logs', 'newsletter') ?>
|
195 |
+
<small><?php _e('Plugin and addons logs', 'newsletter') ?></small></a>
|
196 |
+
</li>
|
197 |
+
<li>
|
198 |
+
<a href="https://www.thenewsletterplugin.com/documentation/developers/backup-recovery/" target="_blank"><i class="fas fa-file"></i> <?php _e('Backup', 'newsletter') ?>
|
199 |
+
<small><?php _e('How to backup, recovery, delete', 'newsletter') ?></small></a>
|
200 |
+
</li>
|
201 |
+
</ul>
|
202 |
+
</li>
|
203 |
+
<?php } ?>
|
204 |
+
|
205 |
+
<?php
|
206 |
+
$license_data = Newsletter::instance()->get_license_data();
|
207 |
+
$premium_url = 'https://www.thenewsletterplugin.com/premium?utm_source=header&utm_medium=link&utm_campaign=plugin&utm_content=' . urlencode($_GET['page']);
|
208 |
+
?>
|
209 |
+
|
210 |
+
<?php if (empty($license_data)) { ?>
|
211 |
+
<?php if (time() < 1638226799) { ?>
|
212 |
+
<li class="tnp-professional-extensions-button" style="background-color: #000; color: #fff; border-color: #FF5F65!important; border-width: 2px !important;"><a href="https://www.thenewsletterplugin.com/premium?utm_source=header&utm_medium=link&utm_campaign=black-friday" target="_blank">
|
213 |
+
<i class="fas fa-trophy"></i> BLACK FRIDAY IS LIVE</a>
|
214 |
+
</li>
|
215 |
+
<?php } else { ?>
|
216 |
+
<li class="tnp-professional-extensions-button"><a href="<?php echo $premium_url ?>" target="_blank">
|
217 |
+
<i class="fas fa-trophy"></i> <?php _e('Get Professional Addons', 'newsletter') ?></a>
|
218 |
+
</li>
|
219 |
+
<?php } ?>
|
220 |
+
<?php } elseif (is_wp_error($license_data)) { ?>
|
221 |
+
<li class="tnp-professional-extensions-button-red">
|
222 |
+
<a href="?page=newsletter_main_main"><i class="fas fa-hand-paper" style="color: white"></i> <?php _e('Unable to check', 'newsletter') ?></a>
|
223 |
+
</li>
|
224 |
+
|
225 |
+
<?php } elseif ($license_data->expire == 0) { ?>
|
226 |
+
<?php if (time() < 1638226799) { ?>
|
227 |
+
<li class="tnp-professional-extensions-button" style="background-color: #000; color: #fff; border-color: #FF5F65!important; border-width: 2px !important;"><a href="https://www.thenewsletterplugin.com/premium?utm_source=header&utm_medium=link&utm_campaign=black-friday" target="_blank">
|
228 |
+
<i class="fas fa-trophy"></i> BLACK FRIDAY IS LIVE</a>
|
229 |
+
</li>
|
230 |
+
<?php } else { ?>
|
231 |
+
<li class="tnp-professional-extensions-button"><a href="<?php echo $premium_url ?>" target="_blank">
|
232 |
+
<i class="fas fa-trophy"></i> <?php _e('Get Professional Addons', 'newsletter') ?></a>
|
233 |
+
</li>
|
234 |
+
<?php } ?>
|
235 |
+
|
236 |
+
<?php } elseif ($license_data->expire < time()) { ?>
|
237 |
+
|
238 |
+
<li class="tnp-professional-extensions-button-red">
|
239 |
+
<a href="?page=newsletter_main_main"><i class="fas fa-hand-paper" style="color: white"></i> <?php _e('License expired', 'newsletter') ?></a>
|
240 |
+
</li>
|
241 |
+
|
242 |
+
<?php } elseif ($license_data->expire >= time()) { ?>
|
243 |
+
|
244 |
+
<?php $p = class_exists('NewsletterExtensions') ? 'newsletter_extensions_index' : 'newsletter_main_extensions'; ?>
|
245 |
+
<li class="tnp-professional-extensions-button">
|
246 |
+
<a href="?page=<?php echo $p ?>"><i class="fas fa-check-square"></i> <?php _e('License active', 'newsletter') ?></a>
|
247 |
+
</li>
|
248 |
+
|
249 |
+
<?php } ?>
|
250 |
+
</ul>
|
251 |
+
</div>
|
252 |
+
|
253 |
+
<?php if (isset($_GET['debug']) || !isset($dismissed['newsletter-shortcode'])) { ?>
|
254 |
+
<?php
|
255 |
+
// Check of Newsletter dedicated page
|
256 |
+
if (!empty(Newsletter::instance()->options['page'])) {
|
257 |
+
if (get_post_status(Newsletter::instance()->options['page']) === 'publish') {
|
258 |
+
$content = get_post_field('post_content', Newsletter::instance()->options['page']);
|
259 |
+
// With and without attributes
|
260 |
+
if (strpos($content, '[newsletter]') === false && strpos($content, '[newsletter ') === false) {
|
261 |
+
?>
|
262 |
+
<div class="tnp-notice">
|
263 |
+
<a href="<?php echo esc_attr($_SERVER['REQUEST_URI']) . '&noheader=1&dismiss=newsletter-shortcode' ?>" class="tnp-dismiss">×</a>
|
264 |
+
The Newsletter dedicated page does not contain the [newsletter] shortcode. If you're using a visual composer it could be ok.
|
265 |
+
<a href="<?php echo site_url('/wp-admin/post.php') ?>?post=<?php echo esc_attr(Newsletter::instance()->options['page']) ?>&action=edit"><strong>Edit the page</strong></a>.
|
266 |
+
|
267 |
+
</div>
|
268 |
+
<?php
|
269 |
+
}
|
270 |
+
}
|
271 |
+
}
|
272 |
+
?>
|
273 |
+
<?php } ?>
|
274 |
+
|
275 |
+
<?php if (isset($_GET['debug']) || !isset($dismissed['rate']) && $user_count > 300) { ?>
|
276 |
+
<div class="tnp-notice">
|
277 |
+
<a href="<?php echo esc_attr($_SERVER['REQUEST_URI']) . '&noheader=1&dismiss=rate' ?>" class="tnp-dismiss">×</a>
|
278 |
+
|
279 |
+
We never asked before and we're curious: <a href="http://wordpress.org/plugins/newsletter/" target="_blank">would you rate this plugin</a>?
|
280 |
+
(few seconds required - account on WordPress.org required, every blog owner should have one...). <strong>Really appreciated, The Newsletter Team</strong>.
|
281 |
+
|
282 |
+
</div>
|
283 |
+
<?php } ?>
|
284 |
+
|
285 |
+
<?php if (isset($_GET['debug']) || !isset($dismissed['newsletter-page']) && empty(Newsletter::instance()->options['page'])) { ?>
|
286 |
+
<div class="tnp-notice">
|
287 |
+
<a href="<?php echo esc_attr($_SERVER['REQUEST_URI']) . '&noheader=1&dismiss=newsletter-page' ?>" class="tnp-dismiss">×</a>
|
288 |
+
|
289 |
+
You should create a blog page to show the subscription form and the subscription messages. Go to the
|
290 |
+
<a href="?page=newsletter_main_main">general settings panel</a> to configure it.
|
291 |
+
|
292 |
+
</div>
|
293 |
+
<?php } ?>
|
294 |
+
|
295 |
+
<?php if (isset($_GET['debug']) || !isset($dismissed['newsletter-subscribe']) && get_option('newsletter_install_time') && get_option('newsletter_install_time') < time() - 86400 * 15) { ?>
|
296 |
+
<div class="tnp-notice">
|
297 |
+
<a href="<?php echo esc_attr($_SERVER['REQUEST_URI']) . '&noheader=1&dismiss=newsletter-subscribe' ?>" class="tnp-dismiss">×</a>
|
298 |
+
Subscribe to our news, promotions and getting started lessons!
|
299 |
+
Proceeding you agree to the <a href="https://www.thenewsletterplugin.com/privacy" target="_blank">privacy policy</a>.
|
300 |
+
<br>
|
301 |
+
<form action="https://www.thenewsletterplugin.com/?na=s" target="_blank" method="post">
|
302 |
+
<input type="hidden" value="plugin-header" name="nr">
|
303 |
+
<input type="hidden" value="3" name="nl[]">
|
304 |
+
<input type="hidden" value="1" name="nl[]">
|
305 |
+
<input type="hidden" value="double" name="optin">
|
306 |
+
<input type="email" name="ne" value="<?php echo esc_attr($current_user_email) ?>">
|
307 |
+
<input type="submit" value="<?php esc_attr_e('Subscribe', 'newsletter') ?>">
|
308 |
+
</form>
|
309 |
+
</div>
|
310 |
+
<?php } ?>
|
311 |
+
|
312 |
+
<?php
|
313 |
+
if (!defined('NEWSLETTER_CRON_WARNINGS') || NEWSLETTER_CRON_WARNINGS) {
|
314 |
+
$x = NewsletterSystem::instance()->get_job_status();
|
315 |
+
if ($x !== NewsletterSystem::JOB_OK) {
|
316 |
+
echo '<div class="tnpc-warning">There are issues with the delivery engine. Please <a href="?page=newsletter_system_scheduler">check them here</a>.</div>';
|
317 |
+
}
|
318 |
+
}
|
319 |
+
?>
|
320 |
+
|
321 |
+
<?php
|
322 |
+
if ($_GET['page'] !== 'newsletter_emails_edit') {
|
323 |
+
|
324 |
+
$last_failed_newsletters = Newsletter::instance()->get_emails_by_status(TNP_Email::STATUS_ERROR);
|
325 |
+
if ($last_failed_newsletters) {
|
326 |
+
$c = new NewsletterControls();
|
327 |
+
foreach ($last_failed_newsletters as $n) {
|
328 |
+
echo '<div class="tnpc-error">';
|
329 |
+
printf(__('Newsletter "%s" stopped by fatal error.', 'newsletter'), esc_html($n->subject));
|
330 |
+
echo ' ';
|
331 |
+
|
332 |
+
$c->btn_link('?page=newsletter_emails_edit&id=' . $n->id, __('Check', 'newsletter'));
|
333 |
+
echo '</div>';
|
334 |
+
}
|
335 |
+
}
|
336 |
+
}
|
337 |
+
?>
|
338 |
+
|
339 |
+
<div id="tnp-notification">
|
340 |
+
<?php
|
341 |
+
if (isset($controls)) {
|
342 |
+
$controls->show();
|
343 |
+
$controls->messages = '';
|
344 |
+
$controls->errors = '';
|
345 |
+
}
|
346 |
+
?>
|
347 |
+
</div>
|
348 |
+
|
349 |
+
|
users/index.php
CHANGED
@@ -1,225 +1,226 @@
|
|
1 |
-
<?php
|
2 |
-
/* @var $this NewsletterUsers */
|
3 |
-
defined('ABSPATH') || exit;
|
4 |
-
|
5 |
-
require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
|
6 |
-
|
7 |
-
$controls = new NewsletterControls();
|
8 |
-
|
9 |
-
$options = $controls->data;
|
10 |
-
$options_profile = get_option('newsletter_profile');
|
11 |
-
$options_main = get_option('newsletter_main');
|
12 |
-
|
13 |
-
// Move to base zero
|
14 |
-
if ($controls->is_action()) {
|
15 |
-
if ($controls->is_action('reset')) {
|
16 |
-
$controls->data = array();
|
17 |
-
} else {
|
18 |
-
$controls->data['search_page'] = (int) $controls->data['search_page'] - 1;
|
19 |
-
}
|
20 |
-
$this->save_options($controls->data, 'search');
|
21 |
-
} else {
|
22 |
-
$controls->data = $this->get_options('search');
|
23 |
-
if (empty($controls->data['search_page']))
|
24 |
-
$controls->data['search_page'] = 0;
|
25 |
-
}
|
26 |
-
|
27 |
-
if ($controls->is_action('resend')) {
|
28 |
-
$user = $this->get_user($controls->button_data);
|
29 |
-
NewsletterSubscription::instance()->send_message('confirmation', $user, true);
|
30 |
-
$controls->messages = __('Activation email sent.', 'newsletter');
|
31 |
-
}
|
32 |
-
|
33 |
-
if ($controls->is_action('resend_welcome')) {
|
34 |
-
$user = $this->get_user($controls->button_data);
|
35 |
-
NewsletterSubscription::instance()->send_message('confirmed', $user, true);
|
36 |
-
$controls->messages = __('Welcome email sent.', 'newsletter');
|
37 |
-
}
|
38 |
-
|
39 |
-
if ($controls->is_action('delete')) {
|
40 |
-
$this->delete_user($controls->button_data);
|
41 |
-
unset($controls->data['subscriber_id']);
|
42 |
-
}
|
43 |
-
|
44 |
-
if ($controls->is_action('delete_selected')) {
|
45 |
-
$r = Newsletter::instance()->delete_user($_POST['ids']);
|
46 |
-
$controls->messages .= $r . ' user(s) deleted';
|
47 |
-
}
|
48 |
-
|
49 |
-
// We build the query condition
|
50 |
-
$where = 'where 1=1';
|
51 |
-
$query_args = array();
|
52 |
-
$text = trim($controls->get_value('search_text'));
|
53 |
-
if ($text) {
|
54 |
-
$query_args[] = '%' . $text . '%';
|
55 |
-
$query_args[] = '%' . $text . '%';
|
56 |
-
$query_args[] = '%' . $text . '%';
|
57 |
-
$where .= " and (email like %s or name like %s or surname like %s)";
|
58 |
-
}
|
59 |
-
|
60 |
-
if (!empty($controls->data['search_status'])) {
|
61 |
-
if ($controls->data['search_status'] == 'T') {
|
62 |
-
$where .= " and test=1";
|
63 |
-
} else {
|
64 |
-
$query_args[] = $controls->data['search_status'];
|
65 |
-
$where .= " and status=%s";
|
66 |
-
}
|
67 |
-
}
|
68 |
-
|
69 |
-
if (!empty($controls->data['search_list'])) {
|
70 |
-
$where .= " and list_" . ((int) $controls->data['search_list']) . "=1";
|
71 |
-
}
|
72 |
-
|
73 |
-
$filtered = $where != 'where 1=1';
|
74 |
-
|
75 |
-
// Total items, total pages
|
76 |
-
$items_per_page = 20;
|
77 |
-
if (!empty($query_args)) {
|
78 |
-
$where = $wpdb->prepare($where, $query_args);
|
79 |
-
}
|
80 |
-
$count = Newsletter::instance()->store->get_count(NEWSLETTER_USERS_TABLE, $where);
|
81 |
-
$last_page = floor($count / $items_per_page) - ($count % $items_per_page == 0 ? 1 : 0);
|
82 |
-
if ($last_page < 0)
|
83 |
-
$last_page = 0;
|
84 |
-
|
85 |
-
if ($controls->is_action('last')) {
|
86 |
-
$controls->data['search_page'] = $last_page;
|
87 |
-
}
|
88 |
-
if ($controls->is_action('first')) {
|
89 |
-
$controls->data['search_page'] = 0;
|
90 |
-
}
|
91 |
-
if ($controls->is_action('next')) {
|
92 |
-
$controls->data['search_page'] = (int) $controls->data['search_page'] + 1;
|
93 |
-
}
|
94 |
-
if ($controls->is_action('prev')) {
|
95 |
-
$controls->data['search_page'] = (int) $controls->data['search_page'] - 1;
|
96 |
-
}
|
97 |
-
if ($controls->is_action('search')) {
|
98 |
-
$controls->data['search_page'] = 0;
|
99 |
-
}
|
100 |
-
|
101 |
-
// Eventually fix the page
|
102 |
-
if (!isset($controls->data['search_page']) || $controls->data['search_page'] < 0)
|
103 |
-
$controls->data['search_page'] = 0;
|
104 |
-
if ($controls->data['search_page'] > $last_page)
|
105 |
-
$controls->data['search_page'] = $last_page;
|
106 |
-
|
107 |
-
$query = "select * from " . NEWSLETTER_USERS_TABLE . ' ' . $where . " order by id desc";
|
108 |
-
$query .= " limit " . ($controls->data['search_page'] * $items_per_page) . "," . $items_per_page;
|
109 |
-
$list = $wpdb->get_results($query);
|
110 |
-
|
111 |
-
// Move to base 1
|
112 |
-
$controls->data['search_page'] ++;
|
113 |
-
?>
|
114 |
-
|
115 |
-
<div class="wrap tnp-users tnp-users-index" id="tnp-wrap">
|
116 |
-
|
117 |
-
<?php include NEWSLETTER_DIR . '/tnp-header.php'; ?>
|
118 |
-
|
119 |
-
<div id="tnp-heading">
|
120 |
-
|
121 |
-
<h2><?php _e('Subscribers', 'newsletter') ?>
|
122 |
-
<a class="tnp-btn-h1" href="?page=newsletter_users_new"><?php _e('Add a subscriber', 'newsletter') ?></a>
|
123 |
-
</h2>
|
124 |
-
|
125 |
-
<p>
|
126 |
-
See the <a href="admin.php?page=newsletter_users_massive">maintenance panel</a> to move subscribers between list, massively delete and so on.
|
127 |
-
</p>
|
128 |
-
|
129 |
-
</div>
|
130 |
-
|
131 |
-
<div id="tnp-body">
|
132 |
-
|
133 |
-
<form id="channel" method="post" action="">
|
134 |
-
<?php $controls->init(); ?>
|
135 |
-
|
136 |
-
<div class="tnp-subscribers-search">
|
137 |
-
<?php $controls->text('search_text', 45, __('Search text', 'newsletter')); ?>
|
138 |
-
|
139 |
-
<?php _e('filter by', 'newsletter') ?>:
|
140 |
-
<?php $controls->select('search_status', ['' => 'Any
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
<?php
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
<?php $controls->button('
|
159 |
-
<?php $controls->
|
160 |
-
<?php $controls->button('
|
161 |
-
<?php $controls->button('
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
<th>
|
174 |
-
<th>
|
175 |
-
<th
|
176 |
-
<th><?php _e('
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
<?php
|
187 |
-
|
188 |
-
|
189 |
-
<
|
190 |
-
<td><?php echo
|
191 |
-
<td><?php echo esc_html($s->
|
192 |
-
<td
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
<td
|
205 |
-
|
206 |
-
<?php
|
207 |
-
<?php
|
208 |
-
<?php
|
209 |
-
<?php
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
<?php $controls->button('
|
217 |
-
<?php $controls->button('
|
218 |
-
<?php $controls->button('
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
Â
|
1 |
+
<?php
|
2 |
+
/* @var $this NewsletterUsers */
|
3 |
+
defined('ABSPATH') || exit;
|
4 |
+
|
5 |
+
require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
|
6 |
+
|
7 |
+
$controls = new NewsletterControls();
|
8 |
+
|
9 |
+
$options = $controls->data;
|
10 |
+
$options_profile = get_option('newsletter_profile');
|
11 |
+
$options_main = get_option('newsletter_main');
|
12 |
+
|
13 |
+
// Move to base zero
|
14 |
+
if ($controls->is_action()) {
|
15 |
+
if ($controls->is_action('reset')) {
|
16 |
+
$controls->data = array();
|
17 |
+
} else {
|
18 |
+
$controls->data['search_page'] = (int) $controls->data['search_page'] - 1;
|
19 |
+
}
|
20 |
+
$this->save_options($controls->data, 'search');
|
21 |
+
} else {
|
22 |
+
$controls->data = $this->get_options('search');
|
23 |
+
if (empty($controls->data['search_page']))
|
24 |
+
$controls->data['search_page'] = 0;
|
25 |
+
}
|
26 |
+
|
27 |
+
if ($controls->is_action('resend')) {
|
28 |
+
$user = $this->get_user($controls->button_data);
|
29 |
+
NewsletterSubscription::instance()->send_message('confirmation', $user, true);
|
30 |
+
$controls->messages = __('Activation email sent.', 'newsletter');
|
31 |
+
}
|
32 |
+
|
33 |
+
if ($controls->is_action('resend_welcome')) {
|
34 |
+
$user = $this->get_user($controls->button_data);
|
35 |
+
NewsletterSubscription::instance()->send_message('confirmed', $user, true);
|
36 |
+
$controls->messages = __('Welcome email sent.', 'newsletter');
|
37 |
+
}
|
38 |
+
|
39 |
+
if ($controls->is_action('delete')) {
|
40 |
+
$this->delete_user($controls->button_data);
|
41 |
+
unset($controls->data['subscriber_id']);
|
42 |
+
}
|
43 |
+
|
44 |
+
if ($controls->is_action('delete_selected')) {
|
45 |
+
$r = Newsletter::instance()->delete_user($_POST['ids']);
|
46 |
+
$controls->messages .= $r . ' user(s) deleted';
|
47 |
+
}
|
48 |
+
|
49 |
+
// We build the query condition
|
50 |
+
$where = 'where 1=1';
|
51 |
+
$query_args = array();
|
52 |
+
$text = trim($controls->get_value('search_text'));
|
53 |
+
if ($text) {
|
54 |
+
$query_args[] = '%' . $text . '%';
|
55 |
+
$query_args[] = '%' . $text . '%';
|
56 |
+
$query_args[] = '%' . $text . '%';
|
57 |
+
$where .= " and (email like %s or name like %s or surname like %s)";
|
58 |
+
}
|
59 |
+
|
60 |
+
if (!empty($controls->data['search_status'])) {
|
61 |
+
if ($controls->data['search_status'] == 'T') {
|
62 |
+
$where .= " and test=1";
|
63 |
+
} else {
|
64 |
+
$query_args[] = $controls->data['search_status'];
|
65 |
+
$where .= " and status=%s";
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
+
if (!empty($controls->data['search_list'])) {
|
70 |
+
$where .= " and list_" . ((int) $controls->data['search_list']) . "=1";
|
71 |
+
}
|
72 |
+
|
73 |
+
$filtered = $where != 'where 1=1';
|
74 |
+
|
75 |
+
// Total items, total pages
|
76 |
+
$items_per_page = 20;
|
77 |
+
if (!empty($query_args)) {
|
78 |
+
$where = $wpdb->prepare($where, $query_args);
|
79 |
+
}
|
80 |
+
$count = Newsletter::instance()->store->get_count(NEWSLETTER_USERS_TABLE, $where);
|
81 |
+
$last_page = floor($count / $items_per_page) - ($count % $items_per_page == 0 ? 1 : 0);
|
82 |
+
if ($last_page < 0)
|
83 |
+
$last_page = 0;
|
84 |
+
|
85 |
+
if ($controls->is_action('last')) {
|
86 |
+
$controls->data['search_page'] = $last_page;
|
87 |
+
}
|
88 |
+
if ($controls->is_action('first')) {
|
89 |
+
$controls->data['search_page'] = 0;
|
90 |
+
}
|
91 |
+
if ($controls->is_action('next')) {
|
92 |
+
$controls->data['search_page'] = (int) $controls->data['search_page'] + 1;
|
93 |
+
}
|
94 |
+
if ($controls->is_action('prev')) {
|
95 |
+
$controls->data['search_page'] = (int) $controls->data['search_page'] - 1;
|
96 |
+
}
|
97 |
+
if ($controls->is_action('search')) {
|
98 |
+
$controls->data['search_page'] = 0;
|
99 |
+
}
|
100 |
+
|
101 |
+
// Eventually fix the page
|
102 |
+
if (!isset($controls->data['search_page']) || $controls->data['search_page'] < 0)
|
103 |
+
$controls->data['search_page'] = 0;
|
104 |
+
if ($controls->data['search_page'] > $last_page)
|
105 |
+
$controls->data['search_page'] = $last_page;
|
106 |
+
|
107 |
+
$query = "select * from " . NEWSLETTER_USERS_TABLE . ' ' . $where . " order by id desc";
|
108 |
+
$query .= " limit " . ($controls->data['search_page'] * $items_per_page) . "," . $items_per_page;
|
109 |
+
$list = $wpdb->get_results($query);
|
110 |
+
|
111 |
+
// Move to base 1
|
112 |
+
$controls->data['search_page'] ++;
|
113 |
+
?>
|
114 |
+
|
115 |
+
<div class="wrap tnp-users tnp-users-index" id="tnp-wrap">
|
116 |
+
|
117 |
+
<?php include NEWSLETTER_DIR . '/tnp-header.php'; ?>
|
118 |
+
|
119 |
+
<div id="tnp-heading">
|
120 |
+
|
121 |
+
<h2><?php _e('Subscribers', 'newsletter') ?>
|
122 |
+
<a class="tnp-btn-h1" href="?page=newsletter_users_new"><?php _e('Add a subscriber', 'newsletter') ?></a>
|
123 |
+
</h2>
|
124 |
+
|
125 |
+
<p>
|
126 |
+
See the <a href="admin.php?page=newsletter_users_massive">maintenance panel</a> to move subscribers between list, massively delete and so on.
|
127 |
+
</p>
|
128 |
+
|
129 |
+
</div>
|
130 |
+
|
131 |
+
<div id="tnp-body">
|
132 |
+
|
133 |
+
<form id="channel" method="post" action="">
|
134 |
+
<?php $controls->init(); ?>
|
135 |
+
|
136 |
+
<div class="tnp-subscribers-search">
|
137 |
+
<?php $controls->text('search_text', 45, __('Search text', 'newsletter')); ?>
|
138 |
+
|
139 |
+
<?php _e('filter by', 'newsletter') ?>:
|
140 |
+
<?php $controls->select('search_status', ['' => __('Any', 'newsletter'), 'T' => __('Test subscribers', 'newsletter'), 'C' => TNP_User::get_status_label('C'),
|
141 |
+
'S' => TNP_User::get_status_label('S'), 'U' => TNP_User::get_status_label('U'), 'B' => TNP_User::get_status_label('B'), 'P'=> TNP_User::get_status_label('P')]); ?>
|
142 |
+
<?php $controls->lists_select('search_list', '-'); ?>
|
143 |
+
|
144 |
+
<?php $controls->button('search', __('Search', 'newsletter')); ?>
|
145 |
+
<?php if ($where != "where 1=1") { ?>
|
146 |
+
<?php $controls->button('reset', __('Reset Filters', 'newsletter')); ?>
|
147 |
+
<?php } ?>
|
148 |
+
<br>
|
149 |
+
<?php $controls->checkbox('show_preferences', __('Show lists', 'newsletter')); ?>
|
150 |
+
</div>
|
151 |
+
|
152 |
+
<?php if ($filtered) { ?>
|
153 |
+
<p><?php _e('The list below is filtered.', 'newsletter') ?></p>
|
154 |
+
<?php } ?>
|
155 |
+
|
156 |
+
<div class="tnp-paginator">
|
157 |
+
|
158 |
+
<?php $controls->button('first', '«'); ?>
|
159 |
+
<?php $controls->button('prev', '‹'); ?>
|
160 |
+
<?php $controls->text('search_page', 3); ?> of <?php echo $last_page + 1 ?> <?php $controls->button('go', __('Go', 'newsletter')); ?>
|
161 |
+
<?php $controls->button('next', '›'); ?>
|
162 |
+
<?php $controls->button('last', '»'); ?>
|
163 |
+
|
164 |
+
<?php echo $count ?> <?php _e('subscriber(s) found', 'newsletter') ?>
|
165 |
+
|
166 |
+
<?php $controls->button_confirm('delete_selected', __('Delete selected', 'newsletter')); ?>
|
167 |
+
|
168 |
+
</div>
|
169 |
+
|
170 |
+
<table class="widefat">
|
171 |
+
<thead>
|
172 |
+
<tr>
|
173 |
+
<td class="check-column"><input type="checkbox" onchange="jQuery('input.tnp-selector').prop('checked', this.checked)"></th>
|
174 |
+
<th>Id</th>
|
175 |
+
<th>Email</th>
|
176 |
+
<th><?php _e('Name', 'newsletter') ?></th>
|
177 |
+
<th><?php _e('Status', 'newsletter') ?></th>
|
178 |
+
<?php if (isset($options['show_preferences']) && $options['show_preferences'] == 1) { ?>
|
179 |
+
<th><?php _e('Lists', 'newsletter') ?></th>
|
180 |
+
<?php } ?>
|
181 |
+
<th> </th>
|
182 |
+
|
183 |
+
<th> </th>
|
184 |
+
</tr>
|
185 |
+
</thead>
|
186 |
+
<?php $i = 0; ?>
|
187 |
+
<?php foreach ($list as $s) { ?>
|
188 |
+
<tr>
|
189 |
+
<th scope="row" class="check-column" style="vertical-align: middle"><input class="tnp-selector" type="checkbox" name="ids[]" value="<?php echo $s->id; ?>"/></td>
|
190 |
+
<td><?php echo $s->id; ?></td>
|
191 |
+
<td><?php echo esc_html($s->email); ?></td>
|
192 |
+
<td><?php echo esc_html($s->name); ?> <?php echo esc_html($s->surname); ?></td>
|
193 |
+
<td><small><?php echo $this->get_user_status_label($s, true) ?></small></td>
|
194 |
+
<?php if (isset($options['show_preferences']) && $options['show_preferences'] == 1) { ?>
|
195 |
+
<td><small><?php
|
196 |
+
$lists = $this->get_lists();
|
197 |
+
foreach ($lists as $item) {
|
198 |
+
$l = 'list_' . $item->id;
|
199 |
+
if ($s->$l == 1)
|
200 |
+
echo esc_html($item->name) . '<br>';
|
201 |
+
}
|
202 |
+
?></small></td>
|
203 |
+
<?php } ?>
|
204 |
+
<td><?php $controls->button_icon_edit($this->get_admin_page_url('edit') . '&id=' . $s->id)?></td>
|
205 |
+
<td style="white-space: nowrap"><?php $controls->button_icon_delete($s->id); ?>
|
206 |
+
<?php if ($s->status == "C") { ?>
|
207 |
+
<?php $controls->button_icon('resend_welcome', 'fa-redo', __('Resend welcome', 'newsletter'), $s->id, true); ?>
|
208 |
+
<?php } else { ?>
|
209 |
+
<?php $controls->button_icon('resend', 'fa-redo', __('Resend activation', 'newsletter'), $s->id, true); ?>
|
210 |
+
<?php } ?></td>
|
211 |
+
</tr>
|
212 |
+
<?php } ?>
|
213 |
+
</table>
|
214 |
+
<div class="tnp-paginator">
|
215 |
+
|
216 |
+
<?php $controls->button('first', '«'); ?>
|
217 |
+
<?php $controls->button('prev', '‹'); ?>
|
218 |
+
<?php $controls->button('next', '›'); ?>
|
219 |
+
<?php $controls->button('last', '»'); ?>
|
220 |
+
</div>
|
221 |
+
</form>
|
222 |
+
</div>
|
223 |
+
|
224 |
+
<?php include NEWSLETTER_DIR . '/tnp-footer.php'; ?>
|
225 |
+
|
226 |
+
</div>
|
users/users.php
CHANGED
@@ -1,252 +1,253 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
defined('ABSPATH') || exit;
|
4 |
-
|
5 |
-
class NewsletterUsers extends NewsletterModule {
|
6 |
-
|
7 |
-
static $instance;
|
8 |
-
|
9 |
-
/**
|
10 |
-
* @return NewsletterUsers
|
11 |
-
*/
|
12 |
-
static function instance() {
|
13 |
-
if (self::$instance == null) {
|
14 |
-
self::$instance = new NewsletterUsers();
|
15 |
-
}
|
16 |
-
|
17 |
-
return self::$instance;
|
18 |
-
}
|
19 |
-
|
20 |
-
function __construct() {
|
21 |
-
parent::__construct('users', '1.3.0');
|
22 |
-
if (is_admin()) {
|
23 |
-
add_action('wp_ajax_newsletter_users_export', array($this, 'hook_wp_ajax_newsletter_users_export'));
|
24 |
-
}
|
25 |
-
}
|
26 |
-
|
27 |
-
function hook_wp_ajax_newsletter_users_export() {
|
28 |
-
|
29 |
-
$newsletter = Newsletter::instance();
|
30 |
-
if ($newsletter->is_allowed()) {
|
31 |
-
require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
|
32 |
-
$controls = new NewsletterControls();
|
33 |
-
|
34 |
-
if ($controls->is_action('export')) {
|
35 |
-
$this->export($controls->data);
|
36 |
-
}
|
37 |
-
} else {
|
38 |
-
die('Not allowed.');
|
39 |
-
}
|
40 |
-
}
|
41 |
-
|
42 |
-
function upgrade() {
|
43 |
-
global $wpdb, $charset_collate;
|
44 |
-
|
45 |
-
parent::upgrade();
|
46 |
-
|
47 |
-
$sql = "CREATE TABLE `" . $wpdb->prefix . "newsletter` (
|
48 |
-
`name` varchar(100) NOT NULL DEFAULT '',
|
49 |
-
`email` varchar(100) NOT NULL DEFAULT '',
|
50 |
-
`token` varchar(50) NOT NULL DEFAULT '',
|
51 |
-
`language` varchar(10) NOT NULL DEFAULT '',
|
52 |
-
`status` varchar(1) NOT NULL DEFAULT 'S',
|
53 |
-
`id` int(11) NOT NULL AUTO_INCREMENT,
|
54 |
-
`profile` mediumtext,
|
55 |
-
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
56 |
-
`updated` int(11) NOT NULL DEFAULT '0',
|
57 |
-
`last_activity` int(11) NOT NULL DEFAULT '0',
|
58 |
-
`followup_step` tinyint(4) NOT NULL DEFAULT '0',
|
59 |
-
`followup_time` bigint(20) NOT NULL DEFAULT '0',
|
60 |
-
`followup` tinyint(4) NOT NULL DEFAULT '0',
|
61 |
-
`surname` varchar(100) NOT NULL DEFAULT '',
|
62 |
-
`sex` char(1) NOT NULL DEFAULT 'n',
|
63 |
-
`feed_time` bigint(20) NOT NULL DEFAULT '0',
|
64 |
-
`feed` tinyint(4) NOT NULL DEFAULT '0',
|
65 |
-
`referrer` varchar(50) NOT NULL DEFAULT '',
|
66 |
-
`ip` varchar(50) NOT NULL DEFAULT '',
|
67 |
-
`wp_user_id` int(11) NOT NULL DEFAULT '0',
|
68 |
-
`http_referer` varchar(255) NOT NULL DEFAULT '',
|
69 |
-
`geo` tinyint(4) NOT NULL DEFAULT '0',
|
70 |
-
`country` varchar(4) NOT NULL DEFAULT '',
|
71 |
-
`region` varchar(100) NOT NULL DEFAULT '',
|
72 |
-
`city` varchar(100) NOT NULL DEFAULT '',
|
73 |
-
`bounce_type` varchar(50) NOT NULL DEFAULT '',
|
74 |
-
`bounce_time` int(11) NOT NULL DEFAULT '0',
|
75 |
-
`unsub_email_id` int(11) NOT NULL DEFAULT '0',
|
76 |
-
`unsub_time` int(11) NOT NULL DEFAULT '0',\n";
|
77 |
-
|
78 |
-
for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
|
79 |
-
$sql .= "`list_$i` tinyint(4) NOT NULL DEFAULT '0',\n";
|
80 |
-
}
|
81 |
-
|
82 |
-
for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
|
83 |
-
$sql .= "`profile_$i` varchar(255) NOT NULL DEFAULT '',\n";
|
84 |
-
}
|
85 |
-
// Leave as last
|
86 |
-
$sql .= "`test` tinyint(4) NOT NULL DEFAULT '0',\n";
|
87 |
-
$sql .= "PRIMARY KEY (`id`),\nUNIQUE KEY `email` (`email`),\nKEY `wp_user_id` (`wp_user_id`)\n) $charset_collate;";
|
88 |
-
|
89 |
-
dbDelta($sql);
|
90 |
-
|
91 |
-
if ($this->old_version < '1.2.7') {
|
92 |
-
$this->query("update " . NEWSLETTER_USERS_TABLE . " set geo=1 where country<>''");
|
93 |
-
}
|
94 |
-
if ($this->old_version > '1.2.5' && $this->old_version < '1.2.9') {
|
95 |
-
$this->upgrade_query("ALTER TABLE " . NEWSLETTER_USERS_TABLE . " DROP COLUMN last_ip;");
|
96 |
-
}
|
97 |
-
}
|
98 |
-
|
99 |
-
function admin_menu() {
|
100 |
-
$this->add_menu_page('index', __('Subscribers', 'newsletter'));
|
101 |
-
$this->add_admin_page('new', __('New subscriber', 'newsletter'));
|
102 |
-
$this->add_admin_page('edit', __('Subscriber Edit', 'newsletter'));
|
103 |
-
$this->add_admin_page('massive', __('Subscribers Maintenance', 'newsletter'));
|
104 |
-
$this->add_admin_page('export', __('Export', 'newsletter'));
|
105 |
-
$this->add_admin_page('import', __('Import', 'newsletter'));
|
106 |
-
$this->add_admin_page('statistics', __('Statistics', 'newsletter'));
|
107 |
-
}
|
108 |
-
|
109 |
-
function export($options = null) {
|
110 |
-
global $wpdb;
|
111 |
-
|
112 |
-
@setlocale(LC_CTYPE, 'en_US.UTF-8');
|
113 |
-
header('Content-Type: application/octet-stream;charset=UTF-8');
|
114 |
-
header('Content-Disposition: attachment; filename="newsletter-subscribers.csv"');
|
115 |
-
|
116 |
-
// BOM
|
117 |
-
echo "\xEF\xBB\xBF";
|
118 |
-
|
119 |
-
$sep = ';';
|
120 |
-
if ($options) {
|
121 |
-
$sep = $options['separator'];
|
122 |
-
}
|
123 |
-
if ($sep == 'tab') {
|
124 |
-
$sep = "\t";
|
125 |
-
}
|
126 |
-
|
127 |
-
// CSV header
|
128 |
-
echo '"Email"' . $sep . '"Name"' . $sep . '"Surname"' . $sep . '"Gender"' . $sep . '"Status"' . $sep . '"Date"' . $sep . '"Token"' . $sep;
|
129 |
-
|
130 |
-
// In table profiles
|
131 |
-
for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
|
132 |
-
echo '"Profile ' . $i . '"' . $sep; // To adjust with field name
|
133 |
-
}
|
134 |
-
|
135 |
-
// Lists
|
136 |
-
for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
|
137 |
-
echo '"List ' . $i . '"' . $sep;
|
138 |
-
}
|
139 |
-
|
140 |
-
echo '"Feed by mail"' . $sep . '"Follow up"' . $sep;
|
141 |
-
echo '"IP"' . $sep . '"Referrer"' . $sep . '"Country"';
|
142 |
-
|
143 |
-
echo "\n";
|
144 |
-
|
145 |
-
$page = 0;
|
146 |
-
while (true) {
|
147 |
-
$query = "select * from " . NEWSLETTER_USERS_TABLE . "";
|
148 |
-
$list = (int) $_POST['options']['list'];
|
149 |
-
if (!empty($list)) {
|
150 |
-
$query .= " where list_" . $list . "=1";
|
151 |
-
}
|
152 |
-
$recipients = $wpdb->get_results($query . " order by email limit " . $page * 500 . ",500");
|
153 |
-
for ($i = 0; $i < count($recipients); $i++) {
|
154 |
-
echo '"' . $recipients[$i]->email . '"' . $sep . '"' . $this->sanitize_csv($recipients[$i]->name) .
|
155 |
-
'"' . $sep . '"' . $this->sanitize_csv($recipients[$i]->surname) .
|
156 |
-
'"' . $sep . '"' . $recipients[$i]->sex .
|
157 |
-
'"' . $sep . '"' . $recipients[$i]->status . '"' . $sep . '"' . $recipients[$i]->created . '"' . $sep . '"' . $recipients[$i]->token . '"' . $sep;
|
158 |
-
|
159 |
-
for ($j = 1; $j <= NEWSLETTER_PROFILE_MAX; $j++) {
|
160 |
-
$column = 'profile_' . $j;
|
161 |
-
echo '"' . $this->sanitize_csv($recipients[$i]->$column) . '"' . $sep;
|
162 |
-
}
|
163 |
-
|
164 |
-
for ($j = 1; $j <= NEWSLETTER_LIST_MAX; $j++) {
|
165 |
-
$list = 'list_' . $j;
|
166 |
-
echo '"' . $recipients[$i]->$list . '"' . $sep;
|
167 |
-
}
|
168 |
-
|
169 |
-
echo '"' . $recipients[$i]->feed . '"' . $sep;
|
170 |
-
echo '"' . $recipients[$i]->followup . '"' . $sep;
|
171 |
-
echo '"' . $recipients[$i]->ip . '"' . $sep;
|
172 |
-
echo '"' . $recipients[$i]->referrer . '"' . $sep;
|
173 |
-
echo '"' . $recipients[$i]->country . '"' . $sep;
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
$text = str_replace("
|
189 |
-
$text = str_replace("\
|
190 |
-
$text = str_replace("
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
* @param
|
204 |
-
*
|
205 |
-
*
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
'
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
$
|
219 |
-
|
220 |
-
|
221 |
-
$
|
222 |
-
$query_args[] = (
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
*
|
238 |
-
*
|
239 |
-
*
|
240 |
-
*
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
$
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
defined('ABSPATH') || exit;
|
4 |
+
|
5 |
+
class NewsletterUsers extends NewsletterModule {
|
6 |
+
|
7 |
+
static $instance;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @return NewsletterUsers
|
11 |
+
*/
|
12 |
+
static function instance() {
|
13 |
+
if (self::$instance == null) {
|
14 |
+
self::$instance = new NewsletterUsers();
|
15 |
+
}
|
16 |
+
|
17 |
+
return self::$instance;
|
18 |
+
}
|
19 |
+
|
20 |
+
function __construct() {
|
21 |
+
parent::__construct('users', '1.3.0');
|
22 |
+
if (is_admin()) {
|
23 |
+
add_action('wp_ajax_newsletter_users_export', array($this, 'hook_wp_ajax_newsletter_users_export'));
|
24 |
+
}
|
25 |
+
}
|
26 |
+
|
27 |
+
function hook_wp_ajax_newsletter_users_export() {
|
28 |
+
|
29 |
+
$newsletter = Newsletter::instance();
|
30 |
+
if ($newsletter->is_allowed()) {
|
31 |
+
require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
|
32 |
+
$controls = new NewsletterControls();
|
33 |
+
|
34 |
+
if ($controls->is_action('export')) {
|
35 |
+
$this->export($controls->data);
|
36 |
+
}
|
37 |
+
} else {
|
38 |
+
die('Not allowed.');
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
function upgrade() {
|
43 |
+
global $wpdb, $charset_collate;
|
44 |
+
|
45 |
+
parent::upgrade();
|
46 |
+
|
47 |
+
$sql = "CREATE TABLE `" . $wpdb->prefix . "newsletter` (
|
48 |
+
`name` varchar(100) NOT NULL DEFAULT '',
|
49 |
+
`email` varchar(100) NOT NULL DEFAULT '',
|
50 |
+
`token` varchar(50) NOT NULL DEFAULT '',
|
51 |
+
`language` varchar(10) NOT NULL DEFAULT '',
|
52 |
+
`status` varchar(1) NOT NULL DEFAULT 'S',
|
53 |
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
54 |
+
`profile` mediumtext,
|
55 |
+
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
56 |
+
`updated` int(11) NOT NULL DEFAULT '0',
|
57 |
+
`last_activity` int(11) NOT NULL DEFAULT '0',
|
58 |
+
`followup_step` tinyint(4) NOT NULL DEFAULT '0',
|
59 |
+
`followup_time` bigint(20) NOT NULL DEFAULT '0',
|
60 |
+
`followup` tinyint(4) NOT NULL DEFAULT '0',
|
61 |
+
`surname` varchar(100) NOT NULL DEFAULT '',
|
62 |
+
`sex` char(1) NOT NULL DEFAULT 'n',
|
63 |
+
`feed_time` bigint(20) NOT NULL DEFAULT '0',
|
64 |
+
`feed` tinyint(4) NOT NULL DEFAULT '0',
|
65 |
+
`referrer` varchar(50) NOT NULL DEFAULT '',
|
66 |
+
`ip` varchar(50) NOT NULL DEFAULT '',
|
67 |
+
`wp_user_id` int(11) NOT NULL DEFAULT '0',
|
68 |
+
`http_referer` varchar(255) NOT NULL DEFAULT '',
|
69 |
+
`geo` tinyint(4) NOT NULL DEFAULT '0',
|
70 |
+
`country` varchar(4) NOT NULL DEFAULT '',
|
71 |
+
`region` varchar(100) NOT NULL DEFAULT '',
|
72 |
+
`city` varchar(100) NOT NULL DEFAULT '',
|
73 |
+
`bounce_type` varchar(50) NOT NULL DEFAULT '',
|
74 |
+
`bounce_time` int(11) NOT NULL DEFAULT '0',
|
75 |
+
`unsub_email_id` int(11) NOT NULL DEFAULT '0',
|
76 |
+
`unsub_time` int(11) NOT NULL DEFAULT '0',\n";
|
77 |
+
|
78 |
+
for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
|
79 |
+
$sql .= "`list_$i` tinyint(4) NOT NULL DEFAULT '0',\n";
|
80 |
+
}
|
81 |
+
|
82 |
+
for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
|
83 |
+
$sql .= "`profile_$i` varchar(255) NOT NULL DEFAULT '',\n";
|
84 |
+
}
|
85 |
+
// Leave as last
|
86 |
+
$sql .= "`test` tinyint(4) NOT NULL DEFAULT '0',\n";
|
87 |
+
$sql .= "PRIMARY KEY (`id`),\nUNIQUE KEY `email` (`email`),\nKEY `wp_user_id` (`wp_user_id`)\n) $charset_collate;";
|
88 |
+
|
89 |
+
dbDelta($sql);
|
90 |
+
|
91 |
+
if ($this->old_version < '1.2.7') {
|
92 |
+
$this->query("update " . NEWSLETTER_USERS_TABLE . " set geo=1 where country<>''");
|
93 |
+
}
|
94 |
+
if ($this->old_version > '1.2.5' && $this->old_version < '1.2.9') {
|
95 |
+
$this->upgrade_query("ALTER TABLE " . NEWSLETTER_USERS_TABLE . " DROP COLUMN last_ip;");
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
function admin_menu() {
|
100 |
+
$this->add_menu_page('index', __('Subscribers', 'newsletter'));
|
101 |
+
$this->add_admin_page('new', __('New subscriber', 'newsletter'));
|
102 |
+
$this->add_admin_page('edit', __('Subscriber Edit', 'newsletter'));
|
103 |
+
$this->add_admin_page('massive', __('Subscribers Maintenance', 'newsletter'));
|
104 |
+
$this->add_admin_page('export', __('Export', 'newsletter'));
|
105 |
+
$this->add_admin_page('import', __('Import', 'newsletter'));
|
106 |
+
$this->add_admin_page('statistics', __('Statistics', 'newsletter'));
|
107 |
+
}
|
108 |
+
|
109 |
+
function export($options = null) {
|
110 |
+
global $wpdb;
|
111 |
+
|
112 |
+
@setlocale(LC_CTYPE, 'en_US.UTF-8');
|
113 |
+
header('Content-Type: application/octet-stream;charset=UTF-8');
|
114 |
+
header('Content-Disposition: attachment; filename="newsletter-subscribers.csv"');
|
115 |
+
|
116 |
+
// BOM
|
117 |
+
echo "\xEF\xBB\xBF";
|
118 |
+
|
119 |
+
$sep = ';';
|
120 |
+
if ($options) {
|
121 |
+
$sep = $options['separator'];
|
122 |
+
}
|
123 |
+
if ($sep == 'tab') {
|
124 |
+
$sep = "\t";
|
125 |
+
}
|
126 |
+
|
127 |
+
// CSV header
|
128 |
+
echo '"Email"' . $sep . '"Name"' . $sep . '"Surname"' . $sep . '"Gender"' . $sep . '"Status"' . $sep . '"Date"' . $sep . '"Token"' . $sep;
|
129 |
+
|
130 |
+
// In table profiles
|
131 |
+
for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
|
132 |
+
echo '"Profile ' . $i . '"' . $sep; // To adjust with field name
|
133 |
+
}
|
134 |
+
|
135 |
+
// Lists
|
136 |
+
for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
|
137 |
+
echo '"List ' . $i . '"' . $sep;
|
138 |
+
}
|
139 |
+
|
140 |
+
echo '"Feed by mail"' . $sep . '"Follow up"' . $sep;
|
141 |
+
echo '"IP"' . $sep . '"Referrer"' . $sep . '"Country"' . $sep . '"Language"';
|
142 |
+
|
143 |
+
echo "\n";
|
144 |
+
|
145 |
+
$page = 0;
|
146 |
+
while (true) {
|
147 |
+
$query = "select * from " . NEWSLETTER_USERS_TABLE . "";
|
148 |
+
$list = (int) $_POST['options']['list'];
|
149 |
+
if (!empty($list)) {
|
150 |
+
$query .= " where list_" . $list . "=1";
|
151 |
+
}
|
152 |
+
$recipients = $wpdb->get_results($query . " order by email limit " . $page * 500 . ",500");
|
153 |
+
for ($i = 0; $i < count($recipients); $i++) {
|
154 |
+
echo '"' . $recipients[$i]->email . '"' . $sep . '"' . $this->sanitize_csv($recipients[$i]->name) .
|
155 |
+
'"' . $sep . '"' . $this->sanitize_csv($recipients[$i]->surname) .
|
156 |
+
'"' . $sep . '"' . $recipients[$i]->sex .
|
157 |
+
'"' . $sep . '"' . $recipients[$i]->status . '"' . $sep . '"' . $recipients[$i]->created . '"' . $sep . '"' . $recipients[$i]->token . '"' . $sep;
|
158 |
+
|
159 |
+
for ($j = 1; $j <= NEWSLETTER_PROFILE_MAX; $j++) {
|
160 |
+
$column = 'profile_' . $j;
|
161 |
+
echo '"' . $this->sanitize_csv($recipients[$i]->$column) . '"' . $sep;
|
162 |
+
}
|
163 |
+
|
164 |
+
for ($j = 1; $j <= NEWSLETTER_LIST_MAX; $j++) {
|
165 |
+
$list = 'list_' . $j;
|
166 |
+
echo '"' . $recipients[$i]->$list . '"' . $sep;
|
167 |
+
}
|
168 |
+
|
169 |
+
echo '"' . $recipients[$i]->feed . '"' . $sep;
|
170 |
+
echo '"' . $recipients[$i]->followup . '"' . $sep;
|
171 |
+
echo '"' . $recipients[$i]->ip . '"' . $sep;
|
172 |
+
echo '"' . $recipients[$i]->referrer . '"' . $sep;
|
173 |
+
echo '"' . $recipients[$i]->country . '"' . $sep;
|
174 |
+
echo '"' . $recipients[$i]->language . '"' . $sep;
|
175 |
+
|
176 |
+
echo "\n";
|
177 |
+
flush();
|
178 |
+
}
|
179 |
+
if (count($recipients) < 500) {
|
180 |
+
break;
|
181 |
+
}
|
182 |
+
$page++;
|
183 |
+
}
|
184 |
+
die();
|
185 |
+
}
|
186 |
+
|
187 |
+
function sanitize_csv($text) {
|
188 |
+
$text = str_replace('"', "'", $text);
|
189 |
+
$text = str_replace("\n", ' ', $text);
|
190 |
+
$text = str_replace("\r", ' ', $text);
|
191 |
+
$text = str_replace(";", ' ', $text);
|
192 |
+
|
193 |
+
// Do you wonder? Excel...
|
194 |
+
$first = substr($text, 0, 1);
|
195 |
+
if ($first == '=' || $first == '+' || $first == '-' || $first == '@') {
|
196 |
+
$text = "'" . $text;
|
197 |
+
}
|
198 |
+
|
199 |
+
return $text;
|
200 |
+
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* @param array $args
|
204 |
+
* @param string $format
|
205 |
+
*
|
206 |
+
* @return array|object|null
|
207 |
+
*/
|
208 |
+
function get_users($args, $format = OBJECT) {
|
209 |
+
global $wpdb;
|
210 |
+
|
211 |
+
$default_args = array(
|
212 |
+
'page' => 1,
|
213 |
+
'per_page' => 10
|
214 |
+
);
|
215 |
+
|
216 |
+
$args = array_merge($default_args, $args);
|
217 |
+
|
218 |
+
$query = 'SELECT * FROM ' . NEWSLETTER_USERS_TABLE . ' ';
|
219 |
+
$query_args = [];
|
220 |
+
|
221 |
+
$query .= ' LIMIT %d OFFSET %d';
|
222 |
+
$query_args[] = (int) $args['per_page'];
|
223 |
+
$query_args[] = ( (int) $args['page'] - 1 ) * (int) $args['per_page'];
|
224 |
+
|
225 |
+
$records = $wpdb->get_results($wpdb->prepare($query, $query_args), $format);
|
226 |
+
|
227 |
+
if ($wpdb->last_error) {
|
228 |
+
$this->logger->error($wpdb->last_error);
|
229 |
+
|
230 |
+
return null;
|
231 |
+
}
|
232 |
+
|
233 |
+
return $records;
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* Check if email exists
|
238 |
+
*
|
239 |
+
* @param string $email
|
240 |
+
*
|
241 |
+
* @return bool
|
242 |
+
*/
|
243 |
+
function email_exists($email) {
|
244 |
+
|
245 |
+
$email = parent::normalize_email($email);
|
246 |
+
$user = parent::get_user($email);
|
247 |
+
|
248 |
+
return $user ? true : false;
|
249 |
+
}
|
250 |
+
|
251 |
+
}
|
252 |
+
|
253 |
+
NewsletterUsers::instance();
|