Newsletter - Version 7.4.0

Version Description

  • Added privacy links
  • Added filter "newsletter_subscription" (documentation is under writing)
Download this release

Release Info

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

Code changes from version 7.3.9 to 7.4.0

Files changed (8) hide show
  1. admin/admin.css +1448 -1445
  2. emails/emails.php +1351 -1351
  3. plugin.php +2 -2
  4. readme.txt +6 -1
  5. subscription/subscription.php +3 -1
  6. system/status.php +1091 -1077
  7. tnp-footer.php +10 -4
  8. tnp-header.php +11 -3
admin/admin.css CHANGED
@@ -1,1445 +1,1448 @@
1
- /* WordPress admin main wrapper */
2
- :root {
3
- --tnp-color-green: #27AE60;
4
- }
5
-
6
- #wpwrap {
7
- background-color: #222B36 !important;
8
- }
9
-
10
- #tnp-wrap * {
11
- -webkit-box-sizing: border-box;
12
- -moz-box-sizing: border-box;
13
- box-sizing: border-box;
14
- }
15
-
16
- #tnp-wrap *:before,
17
- #tnp-wrap *:after {
18
- -webkit-box-sizing: border-box;
19
- -moz-box-sizing: border-box;
20
- box-sizing: border-box;
21
- }
22
-
23
- #tnp-wrap,
24
- #tnp-wrap td,
25
- #tnp-wrap h1,
26
- #tnp-wrap h2,
27
- #tnp-wrap h3,
28
- #tnp-wrap h4,
29
- #tnp-wrap input,
30
- #tnp-wrap select,
31
- #tnp-wrap textarea,
32
- #tnp-wrap button,
33
- #tnp-wrap li,
34
- #tnp-wrap a
35
- {
36
- font-family: soleil, sans-serif;
37
- -webkit-font-smoothing: antialiased; /* Chrome, Safari */
38
- -moz-osx-font-smoothing: grayscale; /* Firefox */
39
- }
40
-
41
- .container {
42
- width: 100%;
43
- padding-right: 1rem;
44
- padding-left: 1rem;
45
- margin-right: auto;
46
- margin-left: auto;
47
- }
48
-
49
- @media (min-width: 576px) {
50
- .container {
51
- max-width: 540px;
52
- }
53
- }
54
-
55
- @media (min-width: 768px) {
56
- .container {
57
- max-width: 720px;
58
- }
59
- }
60
-
61
- @media (min-width: 992px) {
62
- .container {
63
- max-width: 960px;
64
- }
65
- }
66
-
67
- @media (min-width: 1200px) {
68
- .container {
69
- max-width: 1140px;
70
- }
71
- }
72
-
73
- .row:before,
74
- .row:after {
75
- display: table;
76
- content: " ";
77
-
78
- }
79
- .row:after {
80
- clear: both;
81
- }
82
- .col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
83
- position: relative;
84
- min-height: 1px;
85
- padding-right: 15px;
86
- padding-left: 15px;
87
- }
88
- .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
89
- float: left;
90
- }
91
- .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
92
- float: left;
93
- }
94
- .col-md-12 {width: 100%;}
95
- .col-md-11 {width: 91.66666667%;}
96
- .col-md-10 {width: 83.33333333%;}
97
- .col-md-9 {width: 75%;}
98
- .col-md-8 {width: 66.66666667%;}
99
- .col-md-7 {width: 58.33333333%;}
100
- .col-md-6 {width: 50%;}
101
- .col-md-5 {width: 41.66666667%;}
102
- .col-md-4 {width: 33.33333333%;}
103
- .col-md-3 {width: 25%;}
104
- .col-md-2 {width: 16.66666667%;}
105
- .col-md-1 {width: 8.33333333%;}
106
-
107
- @media all and (max-width: 1100px) {
108
- .col-md-12 {width: 100%;}
109
- .col-md-11 {width: 100%;}
110
- .col-md-10 {width: 100%;}
111
- .col-md-9 {width: 100%;}
112
- .col-md-8 {width: 100%;}
113
- .col-md-7 {width: 100%;}
114
- .col-md-6 {width: 100%;}
115
- .col-md-5 {width: 100%;}
116
- .col-md-4 {width: 100%;}
117
- .col-md-3 {width: 100%;}
118
- .col-md-2 {width: 100%;}
119
- .col-md-1 {width: 100%;}
120
- }
121
-
122
- .tnp-row-padded {
123
- width: 90%;
124
- margin: 0 auto;
125
- display: flex;
126
- justify-content: space-between;
127
- }
128
-
129
- .tnp-col-3-boxed {
130
- width: 30%;
131
- border: 1px solid #3c414c;
132
- padding: 0px 0px 30px 0px;
133
- border-radius: 10px;
134
- }
135
-
136
- .tnp-margin-top {
137
- margin-top: 80px;
138
- }
139
-
140
- #tnp-promotion-bar {
141
- background-color: #FF5F65;
142
- color: ddd;
143
- padding: 10px 0;
144
- text-align: center;
145
- font-size: 16px;
146
- }
147
-
148
- #tnp-promotion-bar a {
149
- color: #fff;
150
- font-weight: normal;
151
- text-decoration: none;
152
- }
153
-
154
- /*******************************************************************************
155
- * Header
156
- */
157
-
158
- #tnp-header {
159
- text-align: left;
160
- font-size: 12px;
161
- color: #fff;
162
- font-family: soleil, sans-serif;
163
- min-width: 1200px;
164
- }
165
-
166
- #tnp-header input {
167
- font-size: 12px;
168
- }
169
-
170
- #tnp-header a {
171
- text-decoration: none;
172
- color: white;
173
- letter-spacing: 0.1em;
174
- }
175
-
176
- #tnp-header a:hover {
177
- color: #fff;
178
- }
179
-
180
- .error a, .error a:hover {
181
- color: #000!important;
182
- }
183
-
184
- .updated a, .updated a:hover {
185
- color: #000!important;
186
- }
187
-
188
- /******************************************************************************
189
- * BODY
190
- ******************************************************************************/
191
-
192
- #tnp-body {
193
- padding: 0 10px 10px 10px;
194
- /*background-color: #28313C;*/
195
- }
196
-
197
- #tnp-body h1,
198
- #tnp-body h2,
199
- #tnp-body h3,
200
- #tnp-body h4,
201
- #tnp-body p {
202
- color: #fff;
203
- font-weight: normal;
204
- }
205
-
206
- #tnp-body h3 {
207
- margin-top: 25px;
208
- clear: both;
209
- margin-bottom: 10px;
210
- }
211
-
212
- #tnp-body hr {
213
- height: 0px;
214
- border: 0;
215
- border-top: 1px solid #666;
216
- }
217
-
218
- #tnp-body ul {
219
- list-style-type: circle;
220
- list-style-position: inside;
221
- }
222
-
223
- #tnp-body a, #tnp-body a:active {
224
- color: #2980B9; /* Blue */
225
- }
226
-
227
- #tnp-body a:hover {
228
- color: #3498DB;
229
- }
230
-
231
- /* Action button container */
232
- #tnp-body .tnp-submit {
233
- margin-bottom: 10px;
234
- }
235
-
236
- /* Primary button correction */
237
- #tnp-body .button,
238
- #tnp-body .button:visited,
239
- #tnp-body .button:hover,
240
- #tnp-body .button:active,
241
- #tnp-body .button:focus,
242
- #tnp-body .button-primary,
243
- #tnp-body .button-primary:visited,
244
- #tnp-body .button-primary:hover {
245
- color: #fff;
246
- text-shadow: none;
247
- width: auto;
248
- vertical-align: bottom;
249
- }
250
-
251
- #tnp-body .button-secondary,
252
- #tnp-body .button-secondary:visited,
253
- #tnp-body .button-secondary:hover {
254
- color: #fff;
255
- background-color: #999;
256
- text-shadow: none;
257
- width: auto;
258
- vertical-align: bottom;
259
- }
260
-
261
- /* Icon in button media selector */
262
- #tnp-body span.wp-media-buttons-icon:before {
263
- color: #fff;
264
- }
265
-
266
- /* Standard button */
267
- #tnp-body .tnp-button {
268
- color: #fff;
269
- background-color: #3498db;
270
- text-shadow: none;
271
- }
272
-
273
- /* White button variant */
274
- #tnp-body .button-primary.tnp-button-white, #tnp-body .tnp-button.tnp-button-white {
275
- color: #444!important;
276
- background-color: #fff!important;
277
- box-shadow: none !important;
278
- -webkit-box-shadow: none !important;
279
- width: auto;
280
- }
281
-
282
- #tnp-body tbody th,
283
- #tnp-body td,
284
- #tnp-body td p,
285
- #tnp-body td .button,
286
- #tnp-body td .button:visited,
287
- #tnp-body td .button:hover,
288
- #tnp-body td .button:active,
289
- #tnp-body td .button:focus {
290
- color: #444;
291
- }
292
-
293
- #tnp-body td a,
294
- #tnp-body td a:visited {
295
- color: #27AE60; /* Green */
296
- }
297
-
298
- /*******************************************************************************
299
- * Wide fat tables
300
- */
301
-
302
- #tnp-body .widefat {
303
- width: 90%;
304
- color: #444;
305
- }
306
-
307
- #tnp-body .widefat th {
308
- text-align: left;
309
- }
310
-
311
- #tnp-body .widefat thead {
312
- background-color: #3498DB;
313
- font-family: soleil, sans-serif;
314
- color: #fff !important;
315
- }
316
-
317
- #tnp-body .widefat thead tr th {
318
- color: #fff !important;
319
- }
320
-
321
- #tnp-body .widefat td, .widefat th {
322
- vertical-align: middle;
323
- }
324
-
325
- #tnp-body .widefat tr:nth-child(even) {
326
- background-color: #f4faff;
327
- }
328
-
329
-
330
-
331
- table.clicks td {
332
- border: 1px solid #666;
333
- padding: 2px;
334
- font-size: 10px;
335
- }
336
-
337
- table.clicks {
338
- border-collapse: collapse;
339
- }
340
-
341
- .grid {
342
- border-collapse: collapse;
343
- }
344
- .grid td, .grid th {
345
- padding: 10px;
346
- border: 1px solid #ddd;
347
- margin: 0;
348
- }
349
- .grid th {
350
- background-color: #aaa;
351
- }
352
-
353
- .tnp-buttons {
354
- /*background-color: #0073aa;*/
355
- padding: 10px 0;
356
- }
357
-
358
-
359
-
360
-
361
-
362
-
363
- .tnp-notice {
364
- padding: 15px;
365
- margin: 10px 0;
366
- padding-right: 70px;
367
- position: relative;
368
- border: 1px solid #eee;
369
- background-color: #fff;
370
- color: #444;
371
- font-size: 13px;
372
- border-left: 5px solid #27AE60;
373
- }
374
-
375
- .tnp-notice a,
376
- .tnp-warning a {
377
- color: #0073aa;
378
- text-decoration: none;
379
- font-weight: bold;
380
- }
381
-
382
- .tnp-notice a.tnp-dismiss,
383
- .tnp-warning a.tnp-dismiss{
384
- display: block;
385
- position: absolute;
386
- right: 10px;
387
- top: 13px;
388
- font-size: 25px;
389
- text-decoration: none;
390
- color: #666;
391
- }
392
-
393
- .tnp-notice input[type=email] {
394
- margin: 10px 5px 5px;
395
- width: 250px;
396
- border: none;
397
- box-shadow: none;
398
- background-color: #ECF0F1;
399
- padding: 8px;
400
- }
401
-
402
- .tnp-notice input[type=submit] {
403
- border: none;
404
- box-shadow: none;
405
- background-color: #27AE60;
406
- padding: 8px;
407
- font-family: soleil, sans-serif;
408
- font-size: 13px;
409
- color: #fff;
410
- cursor: pointer;
411
- }
412
-
413
- .tnp-paginator {
414
- margin-top: 10px;
415
- margin-bottom: 5px;
416
- }
417
-
418
- .newsletter-box {
419
- border: 1px solid #ddd;
420
- padding: 10px;
421
- background-color: #fafafa;
422
- margin-bottom: 15px;
423
- }
424
-
425
- .newsletter-box h3 {
426
- margin-top: 0;
427
- }
428
-
429
- .newsletter-textarea-preview {
430
- border: 1px solid #ddd;
431
- }
432
-
433
- .tnp-tab-notice {
434
- background-color: #fff;
435
- border: 1px solid #eee;
436
- border-left: 3px solid gray;
437
- padding: 10px;
438
- margin: 10px 0;
439
- color: #444;
440
- }
441
-
442
- .tnp-tab-warning {
443
- background-color: #fff;
444
- border: 1px solid #eee;
445
- border-left: 3px solid orange;
446
- padding: 10px;
447
- margin: 10px 0;
448
- color: #444;
449
- }
450
-
451
- .tnp-tab-success {
452
- background-color: #fff;
453
- border: 1px solid #eee;
454
- border-left: 3px solid green;
455
- padding: 10px;
456
- margin: 10px 0;
457
- color: #444;
458
- }
459
-
460
- .tnp-tab-error {
461
- background-color: #fff;
462
- border: 1px solid #eee;
463
- border-left: 3px solid red;
464
- padding: 10px;
465
- margin: 10px 0;
466
- color: #444;
467
- }
468
-
469
- /* .tnp-wrap a[target=_blank]:after {
470
- content: "»";
471
- }*/
472
-
473
-
474
- /* CSS The Newsletter Team */
475
-
476
- /* CSS Tips */
477
-
478
- .tnp-tip {
479
- margin-top: 5px;
480
- }
481
-
482
- .tip-button {
483
- padding: 0px 5px;
484
- color: #FD5F65;
485
- text-transform: uppercase;
486
- letter-spacing: 0.2em;
487
- /*font-family: soleil;*/
488
- font-size: 10px;
489
- border: 1px red solid;
490
- }
491
-
492
- .tip-content {
493
- /*font-family: soleil;*/
494
- font-weight: 500;
495
- font-size: 11px;
496
- color: #999999;
497
- }
498
-
499
- /* CSS General Font Styles */
500
-
501
-
502
-
503
-
504
- /* CSS Themes Preview */
505
-
506
- .tnp-theme-preview {
507
- display: inline-block;
508
- text-align: center;
509
- }
510
-
511
- .tnp-theme-preview p {
512
- font-family: soleil;
513
- font-size: 13px;
514
- letter-spacing: 0.2em;
515
- color: #fff;
516
- }
517
-
518
- .tnp-theme-preview img:hover {
519
- box-shadow: 3px 3px 8px 2px #293848;
520
- }
521
-
522
- .tnp-theme-preview img {
523
- border-radius: 10px;
524
- height: 190px;
525
- width: auto;
526
- }
527
-
528
- .tnp-theme-preview .tnp-theme-composer {
529
- height: 250px;
530
- width: auto;
531
- }
532
-
533
- .tnp-theme-preview .tnp-theme-html {
534
- width: auto;
535
- }
536
-
537
-
538
- .tnp-header-logo {
539
- margin-left: 10px;
540
- }
541
-
542
-
543
- /* Altrimenti si crea una striscia bianca in mezzo alla pagina! */
544
-
545
-
546
- .wp-core-ui .button-primary {
547
- background-color: #2b2f3a;
548
- color: #fff;
549
- width: auto;
550
- }
551
-
552
-
553
-
554
-
555
-
556
- .tnp-body-lite {
557
- background-color: #F1F1F1 !important;
558
- }
559
-
560
-
561
- /* Header & Sub-header Pannelli */
562
-
563
- #tnp-heading {
564
- padding: 10px;
565
- /*background-color: #28313C;*/
566
- margin-bottom: 10px;
567
- border-radius: 5px;
568
- }
569
-
570
- #tnp-heading a {
571
- color: #fff;
572
- border-bottom: 1px solid #fff;
573
- text-decoration: none;
574
- }
575
-
576
- #tnp-heading a:hover {
577
- color: #27AE60;
578
- border-bottom: 1px solid #27AE60;
579
- }
580
-
581
- #tnp-heading div p {
582
- color: #565656;
583
- }
584
-
585
- #tnp-heading h1 {
586
- color: #fff;
587
- font-family: soleil, sans-serif;
588
- font-weight: 900;
589
- }
590
-
591
- #tnp-heading h2 {
592
- color: #fff;
593
- font-family: soleil, sans-serif;
594
- letter-spacing: 0.1rem;
595
- font-size: 1.1rem;
596
- line-height: normal;
597
- text-transform: uppercase;
598
- vertical-align: middle;
599
- font-weight: 700;
600
- padding: 0;
601
- margin: 0px;
602
- margin-bottom: 15px;
603
- }
604
-
605
- #tnp-heading h3 {
606
- color: #27AE60;
607
- font-family: soleil, sans-serif;
608
- letter-spacing: 0.1rem;
609
- font-size: .8rem;
610
- line-height: 1.8rem;
611
- text-transform: uppercase;
612
- vertical-align: middle;
613
- font-weight: 700;
614
- padding: 0;
615
- margin: 0px;
616
- }
617
-
618
- #tnp-heading p, #tnp-heading ul {
619
- margin: 0px;
620
- color: #ccc;
621
- }
622
-
623
- #tnp-heading ul {
624
- list-style-type: circle;
625
- list-style-position: inside;
626
- margin-left: 2em;
627
- margin-top: 1em;
628
- }
629
-
630
- /* Style for WP global notices */
631
- #tnp-heading .notice p {
632
- margin: 0.5em 0;
633
- padding: 2px;
634
- }
635
-
636
- #tnp-heading .tnp-btn-h1 {
637
- color: #fff;
638
- background-color: #3498db;
639
- border-radius: 3px;
640
- padding: 6px 11px;
641
- text-decoration: none;
642
- text-transform: capitalize;
643
- font-family: soleil, sans-serif;
644
- margin-left: 10px;
645
- font-size: 0.75rem;
646
- font-weight: 300;
647
- border: none;
648
- }
649
-
650
- #tnp-heading .tnp-btn-h1:hover {
651
- color: #fff;
652
- background-color: #5DADE2;
653
- -webkit-transition: background-color .25s linear;
654
- transition: background-color .25s linear;
655
- -webkit-font-smoothing: subpixel-antialiased;
656
- border: none;
657
- color: #fff;
658
- }
659
-
660
- /* Dashboard Box */
661
-
662
- .metabox-holder {
663
- width: 100%;
664
- }
665
-
666
- .postbox {
667
- border: none;
668
- }
669
-
670
- .postbox h3 a {
671
- float: right;
672
-
673
- }
674
-
675
-
676
- #dashboard-widgets .postbox-container {
677
- width: 33.333%
678
- }
679
-
680
- #tnp-body .postbox p {
681
- color: #000;
682
- }
683
-
684
- #dashboard-widgets .postbox-container .postbox h3 {
685
- font-family: soleil, sans-serif;
686
- letter-spacing: 0.05rem;
687
- background-color: #415b76;
688
- color: #fff;
689
- margin: 0;
690
- padding: 9px;
691
- }
692
-
693
- #dashboard-widgets .postbox-container h3 a {
694
- color: white;
695
- text-decoration: none;
696
- margin-left: 5px;
697
- padding: 2px 8px;
698
- background-color: #26C281;
699
- border-radius: 2px;
700
- font-weight: 300;
701
- text-transform: capitalize;
702
- font-size: 0.8rem;
703
- }
704
-
705
- #dashboard-widgets .postbox-container h3 a:hover {
706
- color: white;
707
- text-decoration: none;
708
- margin-left: 5px;
709
- background-color: #2ECC71;
710
- }
711
-
712
- .postbox-container i {
713
- margin-right: 3px;
714
- }
715
- #tnp-dash-newsletters tr td:last-of-type {
716
- width: 80px;
717
- text-align: right;
718
- }
719
-
720
- #tnp-dash-subscribers tr td:last-of-type {
721
- width: 80px;
722
- text-align: right;
723
- }
724
-
725
- #tnp-dash-subscribers tr td:first-of-type {
726
- width: 250px;
727
- overflow: hidden;
728
- }
729
-
730
- #tnp-dash-subscribers table {
731
- table-layout: fixed;
732
- }
733
-
734
- #tnp-dash-documentation .inside div {
735
- margin-top: 10px;
736
- }
737
-
738
- #tnp-dash-documentation .inside a {
739
- text-decoration: none;
740
- color: #fff;
741
- display: block;
742
- font-family: soleil, sans-serif;
743
- padding: 5px 10px;
744
- }
745
-
746
-
747
- /* Footer */
748
-
749
- #tnp-footer {
750
- margin-top: 10px;
751
- padding: 20px 10px 10px 40px;
752
- background-color: #28313C;
753
- font-family: soleil, sans-serif;
754
- }
755
-
756
- #tnp-footer div {
757
- width: 33%;
758
- display: inline-block;
759
- }
760
-
761
- #tnp-footer a {
762
- color: #fff;
763
- text-decoration: none;
764
- }
765
-
766
- #tnp-footer a:hover {
767
- color: #BDC3C7;
768
- }
769
-
770
- #tnp-footer input[type="submit"] {
771
- background-color: #2ECC71;
772
- border: none;
773
- padding: 5px;
774
- color: #fff;
775
- }
776
-
777
- #tnp-footer form {
778
- white-space: nowrap;
779
- }
780
-
781
- #tnp-footer li {
782
- display: inline;
783
- margin-left: 15px;
784
- padding: 2px 5px;
785
- border-left: 3px solid #2ECC71;
786
- }
787
-
788
- /* Global buttons styles */
789
-
790
- #dashboard-widgets .button {
791
- border: none;
792
- background: none;
793
- box-shadow: none;
794
- color: #322C39;
795
- }
796
-
797
- #dashboard-widgets .button:hover {
798
- background-color: #ECF0F1;
799
- }
800
-
801
- .wp-core-ui .button-secondary, .wp-core-ui .button-primary {
802
- background-color: #3498db;
803
- border: none;
804
- box-shadow: none;
805
- color: #fff;
806
- font-family: soleil,sans-serif;
807
- margin: 0px 2px;
808
- width: auto;
809
- }
810
-
811
- .wp-core-ui .button-secondary:hover, .wp-core-ui .button-primary:hover {
812
- background-color: #5DADE2;
813
- color: #fff;
814
- width: auto;
815
- }
816
-
817
- span.wp-media-buttons-icon:before {
818
- color: #fff;
819
- }
820
-
821
- .tnp-paginator [value="Go"] {
822
- background-color: #27AE60;
823
- }
824
-
825
- .tnp-paginator [value="Go"]:hover {
826
- background-color: #2ECC71;
827
- }
828
-
829
- .notice-dismiss {
830
- padding: 3px;
831
- }
832
-
833
- /*.widefat .button-secondary {
834
- background: none;
835
- color: #3498db;
836
- }*/
837
-
838
- /* Paginator */
839
-
840
- .tnp-paginator {
841
- color: #fff;
842
- font-family: soleil,sans-serif;
843
- margin: 10px 0px;
844
- }
845
-
846
- .tnp-paginator .button-secondary {
847
- padding: 5px;
848
- line-height: normal;
849
- height: auto;
850
- font-size: 12px;
851
- height: 25px;
852
- border: none;
853
- border-radius: 3px;
854
- vertical-align: baseline;
855
- }
856
-
857
- .tnp-paginator [value="Go"] {
858
- background-color: #27AE60 !important;
859
- }
860
-
861
- .tnp-paginator [value="Go"]:hover {
862
- background-color: #2ECC71 !important;
863
- }
864
-
865
- .tnp-paginator input {
866
- background-color: #2C3E50;
867
- border: none;
868
- border-radius: 3px;
869
- color: #fff;
870
- padding: 5px;
871
- line-height: normal;
872
- font-size: 12px;
873
- height: 25px;
874
- }
875
-
876
- /* Subscribers Search Box */
877
-
878
- .tnp-subscribers-search {
879
- color: #fff;
880
- font-family: soleil, sans-serif;
881
- background-color: #2C3E50;
882
- padding: 20px;
883
- border-radius: 5px;
884
- margin-bottom: 20px;
885
- display: inline-block;
886
- }
887
-
888
- .tnp-subscribers-search select {
889
- margin-left: 5px;
890
- padding: 0;
891
- line-height: inherit;
892
- }
893
-
894
-
895
- /* Responsive Video Embeds */
896
-
897
- .tnp-video-container {
898
- position: relative;
899
- padding-bottom: 56.25%;
900
- padding-top: 30px; height: 0; overflow: hidden;
901
- }
902
-
903
- .tnp-video-container iframe,
904
- .tnp-video-container object,
905
- .tnp-video-container embed {
906
- position: absolute;
907
- top: 0;
908
- left: 0;
909
- width: 100%;
910
- height: 100%;
911
- }
912
-
913
-
914
- /* Colors Palette */
915
-
916
- .bg-white {
917
- background-color: #FFF;
918
- }
919
-
920
- .orange {
921
- background-color: #F39C12; /*Orange #F39C12 */
922
- }
923
-
924
- .blue {
925
- background-color: #2980B9; /* Blue #2980B9 */
926
- }
927
-
928
- .purple {
929
- background-color: #8E44AD; /* Purple #8E44AD */
930
- }
931
-
932
- .notice a {
933
- color: #27AE60 !important;
934
- text-decoration: underline!important;
935
- }
936
-
937
- .tnp-chart {
938
- border: 1px solid #eee;
939
- width: 100%;
940
- }
941
-
942
- /* Suggerimenti Oggetto + Inserimento Emoticons */
943
-
944
- .tnp-emails-edit #options-subject {
945
- font-size: 16px;
946
- display: inline-block;
947
- margin: 20px 0px;
948
- width: auto;
949
- border-radius: 4px;
950
- padding: 5px 10px;
951
- }
952
-
953
- .tnp-suggest-button {
954
- font-family: soleil, sans-serif;
955
- margin-left: 8px;
956
- border-radius: 3px;
957
- background-color: #2980B9;
958
- padding: 10px 15px 8px;
959
- font-size: 14px;
960
- color: #fff !important;
961
- text-decoration: none;
962
- }
963
-
964
- .tnp-suggest-button:hover {
965
- background-color: #3f8dbf;
966
- }
967
-
968
- .tnp-popup-overlay {
969
- display: none;
970
- position: fixed;
971
- top: 0;
972
- left: 0;
973
- width: 100%;
974
- height: 100%;
975
- background-color: rgba(0, 0, 0, .8);
976
- z-index: 10000;
977
- }
978
-
979
- .tnp-popup {
980
- width: 40vw;
981
- height: 66vh;
982
- overflow: auto;
983
- margin: 100px auto 0 auto;
984
- background-color: #181818;
985
- padding: 20px;
986
- position: relative;
987
- }
988
- .tnp-popup-close {
989
- display: block;
990
- position: absolute;
991
- top: 5px;
992
- right: 5px;
993
- background-color: #181818;
994
- color: #fff;
995
- font-size: 40px;
996
- padding: 10px;
997
- text-align: right;
998
- cursor: pointer;
999
- }
1000
-
1001
- .tnp-subjects-header {
1002
- font-size: 16px;
1003
- color: #fff;
1004
- padding: 0px 70px 20px 20px;
1005
- font-family: soleil, sans-serif;
1006
- border-bottom: 1px solid #282828;
1007
- }
1008
-
1009
- #tnp-edit-subjects-list {
1010
- padding: 0px 70px 20px 20px;
1011
- }
1012
-
1013
- #tnp-edit-subjects-list a {
1014
- padding: 5px;
1015
- }
1016
-
1017
- #tnp-edit-subjects-list svg {
1018
- margin: 0px 10px 0px 0px;
1019
- vertical-align: middle;
1020
- }
1021
-
1022
- .tnp-subject-category {
1023
- color: #565656;
1024
- margin: 25px 0px 10px 0px;
1025
- /* font-family: soleil; */
1026
- font-size: 12px;
1027
- text-transform: uppercase;
1028
- letter-spacing: 0.1em;
1029
- }
1030
-
1031
-
1032
- /* Stile selettore liste - Schermata di invio newsletter */
1033
-
1034
- .tnp-list-conditions p {
1035
- margin: 0px 10px;
1036
- }
1037
-
1038
- /* Lists panel */
1039
- .tnp-lists .tnp-notes {
1040
- margin: 0;
1041
- font-size: .9em;
1042
- }
1043
-
1044
- /* Codemirror editor with preview */
1045
- iframe.tnp-editor-preview-mobile {
1046
- box-sizing: border-box;
1047
- background-color: #fff;
1048
- border: 1px solid #bbb;
1049
- box-shadow: 1px 1px 10px #777;
1050
- border-radius: 10px;
1051
- padding: 5px;
1052
- width: 320px;
1053
- height: 500px;
1054
- float: left;
1055
- }
1056
-
1057
- iframe.tnp-editor-preview-desktop {
1058
- box-sizing: border-box;
1059
- background-color: #fff;
1060
- border: 1px solid #bbb;
1061
- border-radius: 10px;
1062
- box-shadow: 1px 1px 10px #777;
1063
- padding: 15px;
1064
- width: 650px;
1065
- margin-right: 20px;
1066
- height: 500px;
1067
- float: left;
1068
- }
1069
-
1070
-
1071
- /* Form inserimento licenza in Addons Manager */
1072
-
1073
- #tnp-license-control {
1074
- border-left: 5px solid #27ae60;
1075
- display: inline-block;
1076
- padding: 15px 20px;
1077
- margin-left: -10px;
1078
- margin-top: 15px;
1079
- border-radius: 2px;
1080
- background-color: #fff;
1081
- }
1082
-
1083
- #tnp-license-control form {
1084
- margin-bottom: 10px;
1085
- margin-top: 10px;
1086
- }
1087
-
1088
- #tnp-license-control form input {
1089
- padding-left: 10px;
1090
- }
1091
-
1092
- #tnp-license-control a {
1093
- border-bottom: none;
1094
- color: #27AE60;
1095
- }
1096
-
1097
-
1098
- /* Status Box Style */
1099
-
1100
- #tnp-nl-status {
1101
- width: 100%;
1102
- background: #fffafa;
1103
- padding: 15px 25px 15px 25px;
1104
- border-left: 10px solid #27AE60;
1105
- border-radius: 0px 5px 5px 0px;
1106
- }
1107
-
1108
- #tnp-nl-status p {
1109
- font-size: 17px;
1110
- }
1111
-
1112
- .tnp-nl-status-row {
1113
- margin: 10px 0;
1114
- }
1115
-
1116
- .tnp-nl-status-title {
1117
- font-size: 26px;
1118
- line-height: 32px;
1119
- margin: 5px 0px 0px 0px;
1120
- color: #3498DB;
1121
- font-weight: 900;
1122
- vertical-align: middle;
1123
- }
1124
-
1125
- .tnp-nl-status-title-value {
1126
- font-size: 13px;
1127
- line-height: 32px;
1128
- margin: 0px 0px 0px 5px;
1129
- color: #fff;
1130
- background-color: #95A5A6;
1131
- border-radius: 4px;
1132
- text-transform: uppercase;
1133
- letter-spacing: 1px;
1134
- vertical-align: sub;
1135
- }
1136
-
1137
- .tnp-nl-status-schedule-targeting {
1138
- font-size: 15px;
1139
- color: #34495E;
1140
- }
1141
-
1142
- .tnp-nl-status-schedule-value {
1143
- font-size: 15px;
1144
- color: #34495E;
1145
- }
1146
-
1147
- .tnp-status-header #options-subject {
1148
- width: calc(100% - 150px);
1149
- }
1150
-
1151
- /* Grid Helpers */
1152
-
1153
- .tnp-one-third {
1154
- width: 40%;
1155
- display: inline-block;
1156
- vertical-align: top;
1157
- }
1158
-
1159
- .tnp-two-thirds {
1160
- width: 59%;
1161
- display: inline-block;
1162
- vertical-align: top;
1163
- }
1164
-
1165
- /* Progress bar */
1166
- .tnp-progress {
1167
- display: flex;
1168
- height: 1.5rem;
1169
- overflow: hidden;
1170
- font-size: .75rem;
1171
- background-color: #c9cccf;
1172
- border-radius: .25rem;
1173
- margin: 0px 0px 0px;
1174
- min-width: 100px;
1175
- }
1176
-
1177
- .tnp-progress-bar {
1178
- display: -ms-flexbox;
1179
- display: flex;
1180
- -ms-flex-direction: column;
1181
- flex-direction: column;
1182
- -ms-flex-pack: center;
1183
- justify-content: center;
1184
- color: #fff;
1185
- text-align: center;
1186
- white-space: nowrap;
1187
- background-color: #007bff;
1188
- transition: width .6s ease;
1189
- }
1190
-
1191
- .tnp-progress--sent .tnp-progress-bar {
1192
- background-color: green;
1193
- }
1194
-
1195
- .tnp-progress--error .tnp-progress-bar {
1196
- background-color: #E74C3C;
1197
- }
1198
-
1199
- .tnp-progress-numbers {
1200
- text-align: center;
1201
- color: #666;
1202
- }
1203
-
1204
- .tnp-progress-date {
1205
- color: #666;
1206
- font-style: italic;
1207
- }
1208
-
1209
- span.tnp-email-status {
1210
- background-color: #95A5A6;
1211
- padding: 2px 10px;
1212
- border-radius: 4px;
1213
- color: #fff;
1214
- white-space: nowrap;
1215
- }
1216
-
1217
- /* Email status label */
1218
- span.tnp-email-status.tnp-email-status--new {
1219
- background-color: #8E44AD;
1220
- }
1221
-
1222
- span.tnp-email-status.tnp-email-status--paused {
1223
- background-color: #95A5A6;
1224
- }
1225
-
1226
- span.tnp-email-status.tnp-email-status--sending {
1227
- background-color: #27AE60;
1228
- }
1229
-
1230
- span.tnp-email-status.tnp-email-status--scheduled {
1231
- background-color: #E67E22;
1232
- }
1233
-
1234
- span.tnp-email-status.tnp-email-status--sent {
1235
- background-color: #95A5A6;
1236
- }
1237
-
1238
- span.tnp-email-status.tnp-email-status--error {
1239
- background-color: #E74C3C;
1240
- }
1241
-
1242
- /* Schedule buttons styles */
1243
-
1244
- #tnp-schedule-button {
1245
- background-color: #E67E22 !important;
1246
- }
1247
-
1248
- #tnp-schedule-button:hover {
1249
- background-color: #ec913f !important;
1250
- }
1251
-
1252
- .tnp-button-cancel {
1253
- background-color: #E74C3C !important;
1254
- }
1255
-
1256
- /* Newsletter preview on targeting panel */
1257
- .tnpc-preview {
1258
- margin-top: 10px;
1259
- }
1260
-
1261
- .tnpc-preview .fake-browser-ui iframe {
1262
- width: 700px;
1263
- }
1264
-
1265
- .tnpc-preview .fake-mobile-browser-ui iframe {
1266
- width: 320px;
1267
- }
1268
-
1269
- .fake-browser-ui {
1270
- padding: 30px 0 0;
1271
- border-radius: 3px;
1272
- border-bottom: 10px solid #ccc;
1273
- background: #ddd;
1274
- display: inline-block;
1275
- position: relative;
1276
- line-height: 0;
1277
- vertical-align: top;
1278
- margin-left: 20px;
1279
- }
1280
-
1281
- .fake-mobile-browser-ui {
1282
- padding: 30px 10px 37px;
1283
- border-radius: 10px;
1284
- border-bottom: 10px solid #ccc;
1285
- background: #ddd;
1286
- display: inline-block;
1287
- position: relative;
1288
- line-height: 0;
1289
- margin-left: 30px;
1290
- }
1291
-
1292
- .fake-browser-ui .frame {
1293
- display: block;
1294
- height: 25px;
1295
- position: absolute;
1296
- top: 12px;
1297
- left: 8px;
1298
- }
1299
-
1300
- .fake-mobile-browser-ui .frame {
1301
- display: block;
1302
- height: 25px;
1303
- margin-top: 10px;
1304
- }
1305
-
1306
- .fake-browser-ui span {
1307
- height: 12px;
1308
- width: 12px;
1309
- border-radius: 8px;
1310
- background-color: #eee;
1311
- border: 1px solid #dadada;
1312
- float: left;
1313
- margin: 0 0 0 4px;
1314
- }
1315
-
1316
- .fake-mobile-browser-ui span {
1317
- height: 50px;
1318
- width: 50px;
1319
- border-radius: 60px;
1320
- background-color: #eee;
1321
- border: 2px solid #ccc;
1322
- display: block;
1323
- margin: auto;
1324
- }
1325
-
1326
- .fake-browser-ui .bt-1 {
1327
- background-color: #ED594A;
1328
- }
1329
-
1330
- .fake-browser-ui .bt-2 {
1331
- background-color: #FDD800;
1332
- }
1333
-
1334
- .fake-browser-ui .bt-3 {
1335
- background-color: #5AC05A;
1336
- }
1337
-
1338
- /* Addons page */
1339
-
1340
- #tnp-promo {
1341
- text-align: left;
1342
- background-color: #222b36;
1343
- margin: 20px;
1344
- border-radius: 5px;
1345
- padding: 20px 40px;
1346
- }
1347
- #tnp-promo .tnp-promo-how-to {
1348
- width: 50%;
1349
- padding: 5px 20px;
1350
- margin-top: 30px;
1351
- margin-bottom: 30px;
1352
- border-left: 2px solid #F1C40F;
1353
- }
1354
-
1355
- #tnp-promo .tnp-promo-how-to h3 {
1356
- color: #ECF0F1;
1357
- margin: 0px;
1358
- line-height: 36px;
1359
- }
1360
-
1361
- #tnp-promo .tnp-promo-how-to p {
1362
- color: #ECF0F1;
1363
- margin: 0px;
1364
- font-size: 16px;
1365
- line-height: 26px;
1366
- }
1367
-
1368
- #tnp-promo .tnp-promo-buttons {
1369
- margin: 50px 0px;
1370
- }
1371
-
1372
- #tnp-promo .tnp-promo-button {
1373
- background: #27AE60;
1374
- text-decoration: none;
1375
- color: white;
1376
- padding: 15px 20px;
1377
- font-size: 15px;
1378
- border-radius: 2px;
1379
- }
1380
-
1381
- #tnp-promo .tnp-promo-button:hover {
1382
- background: #2ECC71;
1383
- color: white;
1384
- }
1385
-
1386
- #tnp-promo .tnp-promo-button i {
1387
- margin-right: 3px;
1388
- }
1389
-
1390
- #tnp-body td a.tnp-table-link,
1391
- #tnp-body td a.tnp-table-link:visited {
1392
- color: #444;
1393
- }
1394
-
1395
- #tnp-body td a.tnp-table-link:hover {
1396
- color: #3498DB;
1397
- }
1398
-
1399
- .text-left {
1400
- text-align: left;
1401
- }
1402
-
1403
- .tab-min-height {
1404
- min-height: 500px;
1405
- }
1406
-
1407
- .tnp-control-all-languages-notice {
1408
- padding: 15px;
1409
- border: 1px dashed #999;
1410
- }
1411
-
1412
- /* Spectru, color picker */
1413
-
1414
- /* Down arrow */
1415
- .sp-dd {
1416
- display: none;
1417
- }
1418
-
1419
- .sp-replacer {
1420
- width: 30px!important;
1421
- height: 30px!important;
1422
- }
1423
-
1424
-
1425
- /* Subscriber status labels */
1426
-
1427
- #tnp-body .unsubscribed {
1428
- color: gray;
1429
- }
1430
-
1431
- #tnp-body .confirmed {
1432
- color: darkgreen;
1433
- }
1434
-
1435
- #tnp-body .not-confirmed {
1436
- color: darkgray;
1437
- }
1438
-
1439
- #tnp-body .complained {
1440
- color: red;
1441
- }
1442
-
1443
- #tnp-body .bounced {
1444
- color: darkorange;
1445
- }
 
 
 
1
+ /* WordPress admin main wrapper */
2
+ :root {
3
+ --tnp-color-green: #27AE60;
4
+ }
5
+
6
+ #wpwrap {
7
+ background-color: #222B36 !important;
8
+ }
9
+
10
+ #tnp-wrap * {
11
+ -webkit-box-sizing: border-box;
12
+ -moz-box-sizing: border-box;
13
+ box-sizing: border-box;
14
+ }
15
+
16
+ #tnp-wrap *:before,
17
+ #tnp-wrap *:after {
18
+ -webkit-box-sizing: border-box;
19
+ -moz-box-sizing: border-box;
20
+ box-sizing: border-box;
21
+ }
22
+
23
+ #tnp-wrap,
24
+ #tnp-wrap td,
25
+ #tnp-wrap h1,
26
+ #tnp-wrap h2,
27
+ #tnp-wrap h3,
28
+ #tnp-wrap h4,
29
+ #tnp-wrap input,
30
+ #tnp-wrap select,
31
+ #tnp-wrap textarea,
32
+ #tnp-wrap button,
33
+ #tnp-wrap li,
34
+ #tnp-wrap a
35
+ {
36
+ font-family: soleil, sans-serif;
37
+ -webkit-font-smoothing: antialiased; /* Chrome, Safari */
38
+ -moz-osx-font-smoothing: grayscale; /* Firefox */
39
+ }
40
+
41
+ .container {
42
+ width: 100%;
43
+ padding-right: 1rem;
44
+ padding-left: 1rem;
45
+ margin-right: auto;
46
+ margin-left: auto;
47
+ }
48
+
49
+ @media (min-width: 576px) {
50
+ .container {
51
+ max-width: 540px;
52
+ }
53
+ }
54
+
55
+ @media (min-width: 768px) {
56
+ .container {
57
+ max-width: 720px;
58
+ }
59
+ }
60
+
61
+ @media (min-width: 992px) {
62
+ .container {
63
+ max-width: 960px;
64
+ }
65
+ }
66
+
67
+ @media (min-width: 1200px) {
68
+ .container {
69
+ max-width: 1140px;
70
+ }
71
+ }
72
+
73
+ .row:before,
74
+ .row:after {
75
+ display: table;
76
+ content: " ";
77
+
78
+ }
79
+ .row:after {
80
+ clear: both;
81
+ }
82
+ .col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
83
+ position: relative;
84
+ min-height: 1px;
85
+ padding-right: 15px;
86
+ padding-left: 15px;
87
+ }
88
+ .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
89
+ float: left;
90
+ }
91
+ .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
92
+ float: left;
93
+ }
94
+ .col-md-12 {width: 100%;}
95
+ .col-md-11 {width: 91.66666667%;}
96
+ .col-md-10 {width: 83.33333333%;}
97
+ .col-md-9 {width: 75%;}
98
+ .col-md-8 {width: 66.66666667%;}
99
+ .col-md-7 {width: 58.33333333%;}
100
+ .col-md-6 {width: 50%;}
101
+ .col-md-5 {width: 41.66666667%;}
102
+ .col-md-4 {width: 33.33333333%;}
103
+ .col-md-3 {width: 25%;}
104
+ .col-md-2 {width: 16.66666667%;}
105
+ .col-md-1 {width: 8.33333333%;}
106
+
107
+ @media all and (max-width: 1100px) {
108
+ .col-md-12 {width: 100%;}
109
+ .col-md-11 {width: 100%;}
110
+ .col-md-10 {width: 100%;}
111
+ .col-md-9 {width: 100%;}
112
+ .col-md-8 {width: 100%;}
113
+ .col-md-7 {width: 100%;}
114
+ .col-md-6 {width: 100%;}
115
+ .col-md-5 {width: 100%;}
116
+ .col-md-4 {width: 100%;}
117
+ .col-md-3 {width: 100%;}
118
+ .col-md-2 {width: 100%;}
119
+ .col-md-1 {width: 100%;}
120
+ }
121
+
122
+ .tnp-row-padded {
123
+ width: 90%;
124
+ margin: 0 auto;
125
+ display: flex;
126
+ justify-content: space-between;
127
+ }
128
+
129
+ .tnp-col-3-boxed {
130
+ width: 30%;
131
+ border: 1px solid #3c414c;
132
+ padding: 0px 0px 30px 0px;
133
+ border-radius: 10px;
134
+ }
135
+
136
+ .tnp-margin-top {
137
+ margin-top: 80px;
138
+ }
139
+
140
+ #tnp-promotion-bar {
141
+ background-color: #FF5F65;
142
+ color: ddd;
143
+ padding: 10px 0;
144
+ text-align: center;
145
+ font-size: 16px;
146
+ }
147
+
148
+ #tnp-promotion-bar a {
149
+ color: #fff;
150
+ font-weight: normal;
151
+ text-decoration: none;
152
+ }
153
+
154
+ /*******************************************************************************
155
+ * Header
156
+ */
157
+
158
+ #tnp-header {
159
+ text-align: left;
160
+ font-size: 12px;
161
+ color: #fff;
162
+ font-family: soleil, sans-serif;
163
+ min-width: 1200px;
164
+ }
165
+
166
+ #tnp-header input {
167
+ font-size: 12px;
168
+ }
169
+
170
+ #tnp-header a {
171
+ text-decoration: none;
172
+ color: white;
173
+ letter-spacing: 0.1em;
174
+ }
175
+
176
+ #tnp-header a:hover {
177
+ color: #fff;
178
+ }
179
+
180
+ .error a, .error a:hover {
181
+ color: #000!important;
182
+ }
183
+
184
+ .updated a, .updated a:hover {
185
+ color: #000!important;
186
+ }
187
+
188
+ /******************************************************************************
189
+ * BODY
190
+ ******************************************************************************/
191
+
192
+ #tnp-body {
193
+ padding: 0 10px 10px 10px;
194
+ /*background-color: #28313C;*/
195
+ }
196
+
197
+ #tnp-body h1,
198
+ #tnp-body h2,
199
+ #tnp-body h3,
200
+ #tnp-body h4,
201
+ #tnp-body p {
202
+ color: #fff;
203
+ font-weight: normal;
204
+ }
205
+
206
+ #tnp-body h3 {
207
+ margin-top: 25px;
208
+ clear: both;
209
+ margin-bottom: 10px;
210
+ }
211
+
212
+ #tnp-body hr {
213
+ height: 0px;
214
+ border: 0;
215
+ border-top: 1px solid #666;
216
+ }
217
+
218
+ #tnp-body ul {
219
+ list-style-type: circle;
220
+ list-style-position: inside;
221
+ }
222
+
223
+ #tnp-body a, #tnp-body a:active {
224
+ color: #2980B9; /* Blue */
225
+ }
226
+
227
+ #tnp-body a:hover {
228
+ color: #3498DB;
229
+ }
230
+
231
+ /* Action button container */
232
+ #tnp-body .tnp-submit {
233
+ margin-bottom: 10px;
234
+ }
235
+
236
+ /* Primary button correction */
237
+ #tnp-body .button,
238
+ #tnp-body .button:visited,
239
+ #tnp-body .button:hover,
240
+ #tnp-body .button:active,
241
+ #tnp-body .button:focus,
242
+ #tnp-body .button-primary,
243
+ #tnp-body .button-primary:visited,
244
+ #tnp-body .button-primary:hover {
245
+ color: #fff;
246
+ text-shadow: none;
247
+ width: auto;
248
+ vertical-align: bottom;
249
+ }
250
+
251
+ #tnp-body .button-secondary,
252
+ #tnp-body .button-secondary:visited,
253
+ #tnp-body .button-secondary:hover {
254
+ color: #fff;
255
+ background-color: #999;
256
+ text-shadow: none;
257
+ width: auto;
258
+ vertical-align: bottom;
259
+ }
260
+
261
+ /* Icon in button media selector */
262
+ #tnp-body span.wp-media-buttons-icon:before {
263
+ color: #fff;
264
+ }
265
+
266
+ /* Standard button */
267
+ #tnp-body .tnp-button {
268
+ color: #fff;
269
+ background-color: #3498db;
270
+ text-shadow: none;
271
+ }
272
+
273
+ /* White button variant */
274
+ #tnp-body .button-primary.tnp-button-white, #tnp-body .tnp-button.tnp-button-white {
275
+ color: #444!important;
276
+ background-color: #fff!important;
277
+ box-shadow: none !important;
278
+ -webkit-box-shadow: none !important;
279
+ width: auto;
280
+ }
281
+
282
+ #tnp-body tbody th,
283
+ #tnp-body td,
284
+ #tnp-body td p,
285
+ #tnp-body td .button,
286
+ #tnp-body td .button:visited,
287
+ #tnp-body td .button:hover,
288
+ #tnp-body td .button:active,
289
+ #tnp-body td .button:focus {
290
+ color: #444;
291
+ }
292
+
293
+ #tnp-body td a,
294
+ #tnp-body td a:visited {
295
+ color: #27AE60; /* Green */
296
+ }
297
+
298
+ /*******************************************************************************
299
+ * Wide fat tables
300
+ */
301
+
302
+ #tnp-body .widefat {
303
+ width: 90%;
304
+ color: #444;
305
+ }
306
+
307
+ #tnp-body .widefat th {
308
+ text-align: left;
309
+ }
310
+
311
+ #tnp-body .widefat thead {
312
+ background-color: #3498DB;
313
+ font-family: soleil, sans-serif;
314
+ color: #fff !important;
315
+ }
316
+
317
+ #tnp-body .widefat thead tr th {
318
+ color: #fff !important;
319
+ }
320
+
321
+ #tnp-body .widefat td, .widefat th {
322
+ vertical-align: middle;
323
+ }
324
+
325
+ #tnp-body .widefat tr:nth-child(even) {
326
+ background-color: #f4faff;
327
+ }
328
+
329
+
330
+
331
+ table.clicks td {
332
+ border: 1px solid #666;
333
+ padding: 2px;
334
+ font-size: 10px;
335
+ }
336
+
337
+ table.clicks {
338
+ border-collapse: collapse;
339
+ }
340
+
341
+ .grid {
342
+ border-collapse: collapse;
343
+ }
344
+ .grid td, .grid th {
345
+ padding: 10px;
346
+ border: 1px solid #ddd;
347
+ margin: 0;
348
+ }
349
+ .grid th {
350
+ background-color: #aaa;
351
+ }
352
+
353
+ .tnp-buttons {
354
+ /*background-color: #0073aa;*/
355
+ padding: 10px 0;
356
+ }
357
+
358
+
359
+
360
+
361
+
362
+
363
+ .tnp-notice {
364
+ padding: 15px;
365
+ margin: 10px 0;
366
+ padding-right: 70px;
367
+ position: relative;
368
+ border: 1px solid #eee;
369
+ background-color: #fff;
370
+ color: #444;
371
+ font-size: 13px;
372
+ border-left: 5px solid #27AE60;
373
+ }
374
+
375
+ .tnp-notice a,
376
+ .tnp-warning a {
377
+ color: #0073aa;
378
+ text-decoration: none;
379
+ font-weight: bold;
380
+ }
381
+
382
+ .tnp-notice a.tnp-dismiss,
383
+ .tnp-warning a.tnp-dismiss{
384
+ display: block;
385
+ position: absolute;
386
+ right: 10px;
387
+ top: 13px;
388
+ font-size: 25px;
389
+ text-decoration: none;
390
+ color: #666;
391
+ }
392
+
393
+ .tnp-notice input[type=email] {
394
+ margin: 10px 5px 5px;
395
+ width: 250px;
396
+ border: none;
397
+ box-shadow: none;
398
+ background-color: #ECF0F1;
399
+ padding: 8px;
400
+ }
401
+
402
+ .tnp-notice input[type=submit] {
403
+ border: none;
404
+ box-shadow: none;
405
+ background-color: #27AE60;
406
+ padding: 8px;
407
+ font-family: soleil, sans-serif;
408
+ font-size: 13px;
409
+ color: #fff;
410
+ cursor: pointer;
411
+ }
412
+
413
+ .tnp-paginator {
414
+ margin-top: 10px;
415
+ margin-bottom: 5px;
416
+ }
417
+
418
+ .newsletter-box {
419
+ border: 1px solid #ddd;
420
+ padding: 10px;
421
+ background-color: #fafafa;
422
+ margin-bottom: 15px;
423
+ }
424
+
425
+ .newsletter-box h3 {
426
+ margin-top: 0;
427
+ }
428
+
429
+ .newsletter-textarea-preview {
430
+ border: 1px solid #ddd;
431
+ }
432
+
433
+ .tnp-tab-notice {
434
+ background-color: #fff;
435
+ border: 1px solid #eee;
436
+ border-left: 3px solid gray;
437
+ padding: 10px;
438
+ margin: 10px 0;
439
+ color: #444;
440
+ }
441
+
442
+ .tnp-tab-warning {
443
+ background-color: #fff;
444
+ border: 1px solid #eee;
445
+ border-left: 3px solid orange;
446
+ padding: 10px;
447
+ margin: 10px 0;
448
+ color: #444;
449
+ }
450
+
451
+ .tnp-tab-success {
452
+ background-color: #fff;
453
+ border: 1px solid #eee;
454
+ border-left: 3px solid green;
455
+ padding: 10px;
456
+ margin: 10px 0;
457
+ color: #444;
458
+ }
459
+
460
+ .tnp-tab-error {
461
+ background-color: #fff;
462
+ border: 1px solid #eee;
463
+ border-left: 3px solid red;
464
+ padding: 10px;
465
+ margin: 10px 0;
466
+ color: #444;
467
+ }
468
+
469
+ /* .tnp-wrap a[target=_blank]:after {
470
+ content: "»";
471
+ }*/
472
+
473
+
474
+ /* CSS The Newsletter Team */
475
+
476
+ /* CSS Tips */
477
+
478
+ .tnp-tip {
479
+ margin-top: 5px;
480
+ }
481
+
482
+ .tip-button {
483
+ padding: 0px 5px;
484
+ color: #FD5F65;
485
+ text-transform: uppercase;
486
+ letter-spacing: 0.2em;
487
+ /*font-family: soleil;*/
488
+ font-size: 10px;
489
+ border: 1px red solid;
490
+ }
491
+
492
+ .tip-content {
493
+ /*font-family: soleil;*/
494
+ font-weight: 500;
495
+ font-size: 11px;
496
+ color: #999999;
497
+ }
498
+
499
+ /* CSS General Font Styles */
500
+
501
+
502
+
503
+
504
+ /* CSS Themes Preview */
505
+
506
+ .tnp-theme-preview {
507
+ display: inline-block;
508
+ text-align: center;
509
+ }
510
+
511
+ .tnp-theme-preview p {
512
+ font-family: soleil;
513
+ font-size: 13px;
514
+ letter-spacing: 0.2em;
515
+ color: #fff;
516
+ }
517
+
518
+ .tnp-theme-preview img:hover {
519
+ box-shadow: 3px 3px 8px 2px #293848;
520
+ }
521
+
522
+ .tnp-theme-preview img {
523
+ border-radius: 10px;
524
+ height: 190px;
525
+ width: auto;
526
+ }
527
+
528
+ .tnp-theme-preview .tnp-theme-composer {
529
+ height: 250px;
530
+ width: auto;
531
+ }
532
+
533
+ .tnp-theme-preview .tnp-theme-html {
534
+ width: auto;
535
+ }
536
+
537
+
538
+ .tnp-header-logo {
539
+ margin-left: 10px;
540
+ }
541
+
542
+
543
+ /* Altrimenti si crea una striscia bianca in mezzo alla pagina! */
544
+
545
+
546
+ .wp-core-ui .button-primary {
547
+ background-color: #2b2f3a;
548
+ color: #fff;
549
+ width: auto;
550
+ }
551
+
552
+
553
+
554
+
555
+
556
+ .tnp-body-lite {
557
+ background-color: #F1F1F1 !important;
558
+ }
559
+
560
+
561
+ /* Header & Sub-header Pannelli */
562
+
563
+ #tnp-heading {
564
+ padding: 10px;
565
+ /*background-color: #28313C;*/
566
+ margin-bottom: 10px;
567
+ border-radius: 5px;
568
+ }
569
+
570
+ #tnp-heading a {
571
+ color: #fff;
572
+ border-bottom: 1px solid #fff;
573
+ text-decoration: none;
574
+ }
575
+
576
+ #tnp-heading a:hover {
577
+ color: #27AE60;
578
+ border-bottom: 1px solid #27AE60;
579
+ }
580
+
581
+ #tnp-heading div p {
582
+ color: #565656;
583
+ }
584
+
585
+ #tnp-heading h1 {
586
+ color: #fff;
587
+ font-family: soleil, sans-serif;
588
+ font-weight: 900;
589
+ }
590
+
591
+ #tnp-heading h2 {
592
+ color: #fff;
593
+ font-family: soleil, sans-serif;
594
+ letter-spacing: 0.1rem;
595
+ font-size: 1.1rem;
596
+ line-height: normal;
597
+ text-transform: uppercase;
598
+ vertical-align: middle;
599
+ font-weight: 700;
600
+ padding: 0;
601
+ margin: 0px;
602
+ margin-bottom: 15px;
603
+ }
604
+
605
+ #tnp-heading h3 {
606
+ color: #27AE60;
607
+ font-family: soleil, sans-serif;
608
+ letter-spacing: 0.1rem;
609
+ font-size: .8rem;
610
+ line-height: 1.8rem;
611
+ text-transform: uppercase;
612
+ vertical-align: middle;
613
+ font-weight: 700;
614
+ padding: 0;
615
+ margin: 0px;
616
+ }
617
+
618
+ #tnp-heading p, #tnp-heading ul {
619
+ margin: 0px;
620
+ color: #ccc;
621
+ }
622
+
623
+ #tnp-heading ul {
624
+ list-style-type: circle;
625
+ list-style-position: inside;
626
+ margin-left: 2em;
627
+ margin-top: 1em;
628
+ }
629
+
630
+ /* Style for WP global notices */
631
+ #tnp-heading .notice p {
632
+ margin: 0.5em 0;
633
+ padding: 2px;
634
+ }
635
+
636
+ #tnp-heading .tnp-btn-h1 {
637
+ color: #fff;
638
+ background-color: #3498db;
639
+ border-radius: 3px;
640
+ padding: 6px 11px;
641
+ text-decoration: none;
642
+ text-transform: capitalize;
643
+ font-family: soleil, sans-serif;
644
+ margin-left: 10px;
645
+ font-size: 0.75rem;
646
+ font-weight: 300;
647
+ border: none;
648
+ }
649
+
650
+ #tnp-heading .tnp-btn-h1:hover {
651
+ color: #fff;
652
+ background-color: #5DADE2;
653
+ -webkit-transition: background-color .25s linear;
654
+ transition: background-color .25s linear;
655
+ -webkit-font-smoothing: subpixel-antialiased;
656
+ border: none;
657
+ color: #fff;
658
+ }
659
+
660
+ /* Dashboard Box */
661
+
662
+ .metabox-holder {
663
+ width: 100%;
664
+ }
665
+
666
+ .postbox {
667
+ border: none;
668
+ }
669
+
670
+ .postbox h3 a {
671
+ float: right;
672
+
673
+ }
674
+
675
+
676
+ #dashboard-widgets .postbox-container {
677
+ width: 33.333%
678
+ }
679
+
680
+ #tnp-body .postbox p {
681
+ color: #000;
682
+ }
683
+
684
+ #dashboard-widgets .postbox-container .postbox h3 {
685
+ font-family: soleil, sans-serif;
686
+ letter-spacing: 0.05rem;
687
+ background-color: #415b76;
688
+ color: #fff;
689
+ margin: 0;
690
+ padding: 9px;
691
+ }
692
+
693
+ #dashboard-widgets .postbox-container h3 a {
694
+ color: white;
695
+ text-decoration: none;
696
+ margin-left: 5px;
697
+ padding: 2px 8px;
698
+ background-color: #26C281;
699
+ border-radius: 2px;
700
+ font-weight: 300;
701
+ text-transform: capitalize;
702
+ font-size: 0.8rem;
703
+ }
704
+
705
+ #dashboard-widgets .postbox-container h3 a:hover {
706
+ color: white;
707
+ text-decoration: none;
708
+ margin-left: 5px;
709
+ background-color: #2ECC71;
710
+ }
711
+
712
+ .postbox-container i {
713
+ margin-right: 3px;
714
+ }
715
+ #tnp-dash-newsletters tr td:last-of-type {
716
+ width: 80px;
717
+ text-align: right;
718
+ }
719
+
720
+ #tnp-dash-subscribers tr td:last-of-type {
721
+ width: 80px;
722
+ text-align: right;
723
+ }
724
+
725
+ #tnp-dash-subscribers tr td:first-of-type {
726
+ width: 250px;
727
+ overflow: hidden;
728
+ }
729
+
730
+ #tnp-dash-subscribers table {
731
+ table-layout: fixed;
732
+ }
733
+
734
+ #tnp-dash-documentation .inside div {
735
+ margin-top: 10px;
736
+ }
737
+
738
+ #tnp-dash-documentation .inside a {
739
+ text-decoration: none;
740
+ color: #fff;
741
+ display: block;
742
+ font-family: soleil, sans-serif;
743
+ padding: 5px 10px;
744
+ }
745
+
746
+
747
+ /* Footer */
748
+
749
+ #tnp-footer {
750
+ display: flex;
751
+ justify-content: space-between;
752
+ align-items: flex-start;
753
+ margin-top: 10px;
754
+ padding: 10px 30px;
755
+ background-color: #28313C;
756
+ font-family: soleil, sans-serif;
757
+ }
758
+
759
+ #tnp-footer div {
760
+ /*width: 33%;*/
761
+ /*display: inline-block;*/
762
+ }
763
+
764
+ #tnp-footer a {
765
+ color: #fff;
766
+ text-decoration: none;
767
+ }
768
+
769
+ #tnp-footer a:hover {
770
+ color: #BDC3C7;
771
+ }
772
+
773
+ #tnp-footer input[type="submit"] {
774
+ background-color: #2ECC71;
775
+ border: none;
776
+ padding: 5px 10px;
777
+ color: #fff;
778
+ }
779
+
780
+ #tnp-footer form {
781
+ white-space: nowrap;
782
+ }
783
+
784
+ #tnp-footer li {
785
+ display: inline;
786
+ margin-left: 15px;
787
+ padding: 2px 5px;
788
+ border-left: 3px solid #2ECC71;
789
+ }
790
+
791
+ /* Global buttons styles */
792
+
793
+ #dashboard-widgets .button {
794
+ border: none;
795
+ background: none;
796
+ box-shadow: none;
797
+ color: #322C39;
798
+ }
799
+
800
+ #dashboard-widgets .button:hover {
801
+ background-color: #ECF0F1;
802
+ }
803
+
804
+ .wp-core-ui .button-secondary, .wp-core-ui .button-primary {
805
+ background-color: #3498db;
806
+ border: none;
807
+ box-shadow: none;
808
+ color: #fff;
809
+ font-family: soleil,sans-serif;
810
+ margin: 0px 2px;
811
+ width: auto;
812
+ }
813
+
814
+ .wp-core-ui .button-secondary:hover, .wp-core-ui .button-primary:hover {
815
+ background-color: #5DADE2;
816
+ color: #fff;
817
+ width: auto;
818
+ }
819
+
820
+ span.wp-media-buttons-icon:before {
821
+ color: #fff;
822
+ }
823
+
824
+ .tnp-paginator [value="Go"] {
825
+ background-color: #27AE60;
826
+ }
827
+
828
+ .tnp-paginator [value="Go"]:hover {
829
+ background-color: #2ECC71;
830
+ }
831
+
832
+ .notice-dismiss {
833
+ padding: 3px;
834
+ }
835
+
836
+ /*.widefat .button-secondary {
837
+ background: none;
838
+ color: #3498db;
839
+ }*/
840
+
841
+ /* Paginator */
842
+
843
+ .tnp-paginator {
844
+ color: #fff;
845
+ font-family: soleil,sans-serif;
846
+ margin: 10px 0px;
847
+ }
848
+
849
+ .tnp-paginator .button-secondary {
850
+ padding: 5px;
851
+ line-height: normal;
852
+ height: auto;
853
+ font-size: 12px;
854
+ height: 25px;
855
+ border: none;
856
+ border-radius: 3px;
857
+ vertical-align: baseline;
858
+ }
859
+
860
+ .tnp-paginator [value="Go"] {
861
+ background-color: #27AE60 !important;
862
+ }
863
+
864
+ .tnp-paginator [value="Go"]:hover {
865
+ background-color: #2ECC71 !important;
866
+ }
867
+
868
+ .tnp-paginator input {
869
+ background-color: #2C3E50;
870
+ border: none;
871
+ border-radius: 3px;
872
+ color: #fff;
873
+ padding: 5px;
874
+ line-height: normal;
875
+ font-size: 12px;
876
+ height: 25px;
877
+ }
878
+
879
+ /* Subscribers Search Box */
880
+
881
+ .tnp-subscribers-search {
882
+ color: #fff;
883
+ font-family: soleil, sans-serif;
884
+ background-color: #2C3E50;
885
+ padding: 20px;
886
+ border-radius: 5px;
887
+ margin-bottom: 20px;
888
+ display: inline-block;
889
+ }
890
+
891
+ .tnp-subscribers-search select {
892
+ margin-left: 5px;
893
+ padding: 0;
894
+ line-height: inherit;
895
+ }
896
+
897
+
898
+ /* Responsive Video Embeds */
899
+
900
+ .tnp-video-container {
901
+ position: relative;
902
+ padding-bottom: 56.25%;
903
+ padding-top: 30px; height: 0; overflow: hidden;
904
+ }
905
+
906
+ .tnp-video-container iframe,
907
+ .tnp-video-container object,
908
+ .tnp-video-container embed {
909
+ position: absolute;
910
+ top: 0;
911
+ left: 0;
912
+ width: 100%;
913
+ height: 100%;
914
+ }
915
+
916
+
917
+ /* Colors Palette */
918
+
919
+ .bg-white {
920
+ background-color: #FFF;
921
+ }
922
+
923
+ .orange {
924
+ background-color: #F39C12; /*Orange #F39C12 */
925
+ }
926
+
927
+ .blue {
928
+ background-color: #2980B9; /* Blue #2980B9 */
929
+ }
930
+
931
+ .purple {
932
+ background-color: #8E44AD; /* Purple #8E44AD */
933
+ }
934
+
935
+ .notice a {
936
+ color: #27AE60 !important;
937
+ text-decoration: underline!important;
938
+ }
939
+
940
+ .tnp-chart {
941
+ border: 1px solid #eee;
942
+ width: 100%;
943
+ }
944
+
945
+ /* Suggerimenti Oggetto + Inserimento Emoticons */
946
+
947
+ .tnp-emails-edit #options-subject {
948
+ font-size: 16px;
949
+ display: inline-block;
950
+ margin: 20px 0px;
951
+ width: auto;
952
+ border-radius: 4px;
953
+ padding: 5px 10px;
954
+ }
955
+
956
+ .tnp-suggest-button {
957
+ font-family: soleil, sans-serif;
958
+ margin-left: 8px;
959
+ border-radius: 3px;
960
+ background-color: #2980B9;
961
+ padding: 10px 15px 8px;
962
+ font-size: 14px;
963
+ color: #fff !important;
964
+ text-decoration: none;
965
+ }
966
+
967
+ .tnp-suggest-button:hover {
968
+ background-color: #3f8dbf;
969
+ }
970
+
971
+ .tnp-popup-overlay {
972
+ display: none;
973
+ position: fixed;
974
+ top: 0;
975
+ left: 0;
976
+ width: 100%;
977
+ height: 100%;
978
+ background-color: rgba(0, 0, 0, .8);
979
+ z-index: 10000;
980
+ }
981
+
982
+ .tnp-popup {
983
+ width: 40vw;
984
+ height: 66vh;
985
+ overflow: auto;
986
+ margin: 100px auto 0 auto;
987
+ background-color: #181818;
988
+ padding: 20px;
989
+ position: relative;
990
+ }
991
+ .tnp-popup-close {
992
+ display: block;
993
+ position: absolute;
994
+ top: 5px;
995
+ right: 5px;
996
+ background-color: #181818;
997
+ color: #fff;
998
+ font-size: 40px;
999
+ padding: 10px;
1000
+ text-align: right;
1001
+ cursor: pointer;
1002
+ }
1003
+
1004
+ .tnp-subjects-header {
1005
+ font-size: 16px;
1006
+ color: #fff;
1007
+ padding: 0px 70px 20px 20px;
1008
+ font-family: soleil, sans-serif;
1009
+ border-bottom: 1px solid #282828;
1010
+ }
1011
+
1012
+ #tnp-edit-subjects-list {
1013
+ padding: 0px 70px 20px 20px;
1014
+ }
1015
+
1016
+ #tnp-edit-subjects-list a {
1017
+ padding: 5px;
1018
+ }
1019
+
1020
+ #tnp-edit-subjects-list svg {
1021
+ margin: 0px 10px 0px 0px;
1022
+ vertical-align: middle;
1023
+ }
1024
+
1025
+ .tnp-subject-category {
1026
+ color: #565656;
1027
+ margin: 25px 0px 10px 0px;
1028
+ /* font-family: soleil; */
1029
+ font-size: 12px;
1030
+ text-transform: uppercase;
1031
+ letter-spacing: 0.1em;
1032
+ }
1033
+
1034
+
1035
+ /* Stile selettore liste - Schermata di invio newsletter */
1036
+
1037
+ .tnp-list-conditions p {
1038
+ margin: 0px 10px;
1039
+ }
1040
+
1041
+ /* Lists panel */
1042
+ .tnp-lists .tnp-notes {
1043
+ margin: 0;
1044
+ font-size: .9em;
1045
+ }
1046
+
1047
+ /* Codemirror editor with preview */
1048
+ iframe.tnp-editor-preview-mobile {
1049
+ box-sizing: border-box;
1050
+ background-color: #fff;
1051
+ border: 1px solid #bbb;
1052
+ box-shadow: 1px 1px 10px #777;
1053
+ border-radius: 10px;
1054
+ padding: 5px;
1055
+ width: 320px;
1056
+ height: 500px;
1057
+ float: left;
1058
+ }
1059
+
1060
+ iframe.tnp-editor-preview-desktop {
1061
+ box-sizing: border-box;
1062
+ background-color: #fff;
1063
+ border: 1px solid #bbb;
1064
+ border-radius: 10px;
1065
+ box-shadow: 1px 1px 10px #777;
1066
+ padding: 15px;
1067
+ width: 650px;
1068
+ margin-right: 20px;
1069
+ height: 500px;
1070
+ float: left;
1071
+ }
1072
+
1073
+
1074
+ /* Form inserimento licenza in Addons Manager */
1075
+
1076
+ #tnp-license-control {
1077
+ border-left: 5px solid #27ae60;
1078
+ display: inline-block;
1079
+ padding: 15px 20px;
1080
+ margin-left: -10px;
1081
+ margin-top: 15px;
1082
+ border-radius: 2px;
1083
+ background-color: #fff;
1084
+ }
1085
+
1086
+ #tnp-license-control form {
1087
+ margin-bottom: 10px;
1088
+ margin-top: 10px;
1089
+ }
1090
+
1091
+ #tnp-license-control form input {
1092
+ padding-left: 10px;
1093
+ }
1094
+
1095
+ #tnp-license-control a {
1096
+ border-bottom: none;
1097
+ color: #27AE60;
1098
+ }
1099
+
1100
+
1101
+ /* Status Box Style */
1102
+
1103
+ #tnp-nl-status {
1104
+ width: 100%;
1105
+ background: #fffafa;
1106
+ padding: 15px 25px 15px 25px;
1107
+ border-left: 10px solid #27AE60;
1108
+ border-radius: 0px 5px 5px 0px;
1109
+ }
1110
+
1111
+ #tnp-nl-status p {
1112
+ font-size: 17px;
1113
+ }
1114
+
1115
+ .tnp-nl-status-row {
1116
+ margin: 10px 0;
1117
+ }
1118
+
1119
+ .tnp-nl-status-title {
1120
+ font-size: 26px;
1121
+ line-height: 32px;
1122
+ margin: 5px 0px 0px 0px;
1123
+ color: #3498DB;
1124
+ font-weight: 900;
1125
+ vertical-align: middle;
1126
+ }
1127
+
1128
+ .tnp-nl-status-title-value {
1129
+ font-size: 13px;
1130
+ line-height: 32px;
1131
+ margin: 0px 0px 0px 5px;
1132
+ color: #fff;
1133
+ background-color: #95A5A6;
1134
+ border-radius: 4px;
1135
+ text-transform: uppercase;
1136
+ letter-spacing: 1px;
1137
+ vertical-align: sub;
1138
+ }
1139
+
1140
+ .tnp-nl-status-schedule-targeting {
1141
+ font-size: 15px;
1142
+ color: #34495E;
1143
+ }
1144
+
1145
+ .tnp-nl-status-schedule-value {
1146
+ font-size: 15px;
1147
+ color: #34495E;
1148
+ }
1149
+
1150
+ .tnp-status-header #options-subject {
1151
+ width: calc(100% - 150px);
1152
+ }
1153
+
1154
+ /* Grid Helpers */
1155
+
1156
+ .tnp-one-third {
1157
+ width: 40%;
1158
+ display: inline-block;
1159
+ vertical-align: top;
1160
+ }
1161
+
1162
+ .tnp-two-thirds {
1163
+ width: 59%;
1164
+ display: inline-block;
1165
+ vertical-align: top;
1166
+ }
1167
+
1168
+ /* Progress bar */
1169
+ .tnp-progress {
1170
+ display: flex;
1171
+ height: 1.5rem;
1172
+ overflow: hidden;
1173
+ font-size: .75rem;
1174
+ background-color: #c9cccf;
1175
+ border-radius: .25rem;
1176
+ margin: 0px 0px 0px;
1177
+ min-width: 100px;
1178
+ }
1179
+
1180
+ .tnp-progress-bar {
1181
+ display: -ms-flexbox;
1182
+ display: flex;
1183
+ -ms-flex-direction: column;
1184
+ flex-direction: column;
1185
+ -ms-flex-pack: center;
1186
+ justify-content: center;
1187
+ color: #fff;
1188
+ text-align: center;
1189
+ white-space: nowrap;
1190
+ background-color: #007bff;
1191
+ transition: width .6s ease;
1192
+ }
1193
+
1194
+ .tnp-progress--sent .tnp-progress-bar {
1195
+ background-color: green;
1196
+ }
1197
+
1198
+ .tnp-progress--error .tnp-progress-bar {
1199
+ background-color: #E74C3C;
1200
+ }
1201
+
1202
+ .tnp-progress-numbers {
1203
+ text-align: center;
1204
+ color: #666;
1205
+ }
1206
+
1207
+ .tnp-progress-date {
1208
+ color: #666;
1209
+ font-style: italic;
1210
+ }
1211
+
1212
+ span.tnp-email-status {
1213
+ background-color: #95A5A6;
1214
+ padding: 2px 10px;
1215
+ border-radius: 4px;
1216
+ color: #fff;
1217
+ white-space: nowrap;
1218
+ }
1219
+
1220
+ /* Email status label */
1221
+ span.tnp-email-status.tnp-email-status--new {
1222
+ background-color: #8E44AD;
1223
+ }
1224
+
1225
+ span.tnp-email-status.tnp-email-status--paused {
1226
+ background-color: #95A5A6;
1227
+ }
1228
+
1229
+ span.tnp-email-status.tnp-email-status--sending {
1230
+ background-color: #27AE60;
1231
+ }
1232
+
1233
+ span.tnp-email-status.tnp-email-status--scheduled {
1234
+ background-color: #E67E22;
1235
+ }
1236
+
1237
+ span.tnp-email-status.tnp-email-status--sent {
1238
+ background-color: #95A5A6;
1239
+ }
1240
+
1241
+ span.tnp-email-status.tnp-email-status--error {
1242
+ background-color: #E74C3C;
1243
+ }
1244
+
1245
+ /* Schedule buttons styles */
1246
+
1247
+ #tnp-schedule-button {
1248
+ background-color: #E67E22 !important;
1249
+ }
1250
+
1251
+ #tnp-schedule-button:hover {
1252
+ background-color: #ec913f !important;
1253
+ }
1254
+
1255
+ .tnp-button-cancel {
1256
+ background-color: #E74C3C !important;
1257
+ }
1258
+
1259
+ /* Newsletter preview on targeting panel */
1260
+ .tnpc-preview {
1261
+ margin-top: 10px;
1262
+ }
1263
+
1264
+ .tnpc-preview .fake-browser-ui iframe {
1265
+ width: 700px;
1266
+ }
1267
+
1268
+ .tnpc-preview .fake-mobile-browser-ui iframe {
1269
+ width: 320px;
1270
+ }
1271
+
1272
+ .fake-browser-ui {
1273
+ padding: 30px 0 0;
1274
+ border-radius: 3px;
1275
+ border-bottom: 10px solid #ccc;
1276
+ background: #ddd;
1277
+ display: inline-block;
1278
+ position: relative;
1279
+ line-height: 0;
1280
+ vertical-align: top;
1281
+ margin-left: 20px;
1282
+ }
1283
+
1284
+ .fake-mobile-browser-ui {
1285
+ padding: 30px 10px 37px;
1286
+ border-radius: 10px;
1287
+ border-bottom: 10px solid #ccc;
1288
+ background: #ddd;
1289
+ display: inline-block;
1290
+ position: relative;
1291
+ line-height: 0;
1292
+ margin-left: 30px;
1293
+ }
1294
+
1295
+ .fake-browser-ui .frame {
1296
+ display: block;
1297
+ height: 25px;
1298
+ position: absolute;
1299
+ top: 12px;
1300
+ left: 8px;
1301
+ }
1302
+
1303
+ .fake-mobile-browser-ui .frame {
1304
+ display: block;
1305
+ height: 25px;
1306
+ margin-top: 10px;
1307
+ }
1308
+
1309
+ .fake-browser-ui span {
1310
+ height: 12px;
1311
+ width: 12px;
1312
+ border-radius: 8px;
1313
+ background-color: #eee;
1314
+ border: 1px solid #dadada;
1315
+ float: left;
1316
+ margin: 0 0 0 4px;
1317
+ }
1318
+
1319
+ .fake-mobile-browser-ui span {
1320
+ height: 50px;
1321
+ width: 50px;
1322
+ border-radius: 60px;
1323
+ background-color: #eee;
1324
+ border: 2px solid #ccc;
1325
+ display: block;
1326
+ margin: auto;
1327
+ }
1328
+
1329
+ .fake-browser-ui .bt-1 {
1330
+ background-color: #ED594A;
1331
+ }
1332
+
1333
+ .fake-browser-ui .bt-2 {
1334
+ background-color: #FDD800;
1335
+ }
1336
+
1337
+ .fake-browser-ui .bt-3 {
1338
+ background-color: #5AC05A;
1339
+ }
1340
+
1341
+ /* Addons page */
1342
+
1343
+ #tnp-promo {
1344
+ text-align: left;
1345
+ background-color: #222b36;
1346
+ margin: 20px;
1347
+ border-radius: 5px;
1348
+ padding: 20px 40px;
1349
+ }
1350
+ #tnp-promo .tnp-promo-how-to {
1351
+ width: 50%;
1352
+ padding: 5px 20px;
1353
+ margin-top: 30px;
1354
+ margin-bottom: 30px;
1355
+ border-left: 2px solid #F1C40F;
1356
+ }
1357
+
1358
+ #tnp-promo .tnp-promo-how-to h3 {
1359
+ color: #ECF0F1;
1360
+ margin: 0px;
1361
+ line-height: 36px;
1362
+ }
1363
+
1364
+ #tnp-promo .tnp-promo-how-to p {
1365
+ color: #ECF0F1;
1366
+ margin: 0px;
1367
+ font-size: 16px;
1368
+ line-height: 26px;
1369
+ }
1370
+
1371
+ #tnp-promo .tnp-promo-buttons {
1372
+ margin: 50px 0px;
1373
+ }
1374
+
1375
+ #tnp-promo .tnp-promo-button {
1376
+ background: #27AE60;
1377
+ text-decoration: none;
1378
+ color: white;
1379
+ padding: 15px 20px;
1380
+ font-size: 15px;
1381
+ border-radius: 2px;
1382
+ }
1383
+
1384
+ #tnp-promo .tnp-promo-button:hover {
1385
+ background: #2ECC71;
1386
+ color: white;
1387
+ }
1388
+
1389
+ #tnp-promo .tnp-promo-button i {
1390
+ margin-right: 3px;
1391
+ }
1392
+
1393
+ #tnp-body td a.tnp-table-link,
1394
+ #tnp-body td a.tnp-table-link:visited {
1395
+ color: #444;
1396
+ }
1397
+
1398
+ #tnp-body td a.tnp-table-link:hover {
1399
+ color: #3498DB;
1400
+ }
1401
+
1402
+ .text-left {
1403
+ text-align: left;
1404
+ }
1405
+
1406
+ .tab-min-height {
1407
+ min-height: 500px;
1408
+ }
1409
+
1410
+ .tnp-control-all-languages-notice {
1411
+ padding: 15px;
1412
+ border: 1px dashed #999;
1413
+ }
1414
+
1415
+ /* Spectru, color picker */
1416
+
1417
+ /* Down arrow */
1418
+ .sp-dd {
1419
+ display: none;
1420
+ }
1421
+
1422
+ .sp-replacer {
1423
+ width: 30px!important;
1424
+ height: 30px!important;
1425
+ }
1426
+
1427
+
1428
+ /* Subscriber status labels */
1429
+
1430
+ #tnp-body .unsubscribed {
1431
+ color: gray;
1432
+ }
1433
+
1434
+ #tnp-body .confirmed {
1435
+ color: darkgreen;
1436
+ }
1437
+
1438
+ #tnp-body .not-confirmed {
1439
+ color: darkgray;
1440
+ }
1441
+
1442
+ #tnp-body .complained {
1443
+ color: red;
1444
+ }
1445
+
1446
+ #tnp-body .bounced {
1447
+ color: darkorange;
1448
+ }
emails/emails.php CHANGED
@@ -1,1351 +1,1351 @@
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
- preg_match_all('/data-json="(.*?)"/m', $email->message, $matches, PREG_PATTERN_ORDER);
350
-
351
- $result = '';
352
- $subject = '';
353
-
354
- foreach ($matches[1] as $match) {
355
- $a = html_entity_decode($match, ENT_QUOTES, 'UTF-8');
356
- $options = $this->options_decode($a);
357
-
358
- $block = $this->get_block($options['block_id']);
359
- if (!$block) {
360
- $this->logger->debug('Unable to load the block ' . $options['block_id']);
361
- //continue;
362
- }
363
-
364
- ob_start();
365
- $out = $this->render_block($options['block_id'], true, $options, $context);
366
- if (is_array($out)) {
367
- if ($out['return_empty_message'] || $out['stop']) {
368
- return false;
369
- }
370
- if ($out['skip']) {
371
- continue;
372
- }
373
- if (empty($subject) && !empty($out['subject'])) {
374
- $subject = $out['subject'];
375
- }
376
- }
377
- $block_html = ob_get_clean();
378
- $result .= $block_html;
379
- }
380
-
381
- $email->message = TNP_Composer::get_html_open($email) . TNP_Composer::get_main_wrapper_open($email) .
382
- $result . TNP_Composer::get_main_wrapper_close($email) . TNP_Composer::get_html_close($email);
383
- $email->subject = $subject;
384
- return true;
385
- }
386
-
387
- function remove_block_data($text) {
388
- // TODO: Lavorare!
389
- return $text;
390
- }
391
-
392
- static function get_outlook_wrapper_open($width = 600) {
393
- 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]-->';
394
- }
395
-
396
- static function get_outlook_wrapper_close() {
397
- return "<!--[if mso | IE]></td></tr></table><![endif]-->";
398
- }
399
-
400
- function hook_safe_style_css($rules) {
401
- $rules[] = 'display';
402
- return $rules;
403
- }
404
-
405
- /**
406
- * Renders a block identified by its id, using the block options and adding a wrapper
407
- * if required (for the first block rendering).
408
- *
409
- * @param string $block_id
410
- * @param boolean $wrapper
411
- * @param array $options
412
- * @param array $context
413
- * @param array $composer
414
- */
415
- function render_block($block_id = null, $wrapper = false, $options = [], $context = [], $composer = []) {
416
- static $kses_style_filter = false;
417
- include_once NEWSLETTER_INCLUDES_DIR . '/helper.php';
418
-
419
- //Remove 'options_composer_' prefix
420
- $composer_defaults = [];
421
- foreach (TNP_Composer::get_global_style_defaults() as $global_option_name => $global_option) {
422
- $composer_defaults[str_replace('options_composer_', '', $global_option_name)] = $global_option;
423
- }
424
- $composer = array_merge($composer_defaults, $composer);
425
-
426
- $width = 600;
427
- $font_family = 'Helvetica, Arial, sans-serif';
428
-
429
- $global_title_font_family = $composer['title_font_family'];
430
- $global_title_font_size = $composer['title_font_size'];
431
- $global_title_font_color = $composer['title_font_color'];
432
- $global_title_font_weight = $composer['title_font_weight'];
433
-
434
- $global_text_font_family = $composer['text_font_family'];
435
- $global_text_font_size = $composer['text_font_size'];
436
- $global_text_font_color = $composer['text_font_color'];
437
- $global_text_font_weight = $composer['text_font_weight'];
438
-
439
- $global_button_font_family = $composer['button_font_family'];
440
- $global_button_font_size = $composer['button_font_size'];
441
- $global_button_font_color = $composer['button_font_color'];
442
- $global_button_font_weight = $composer['button_font_weight'];
443
- $global_button_background_color = $composer['button_background_color'];
444
-
445
- $global_block_background = $composer['block_background'];
446
-
447
- $info = Newsletter::instance()->get_options('info');
448
-
449
- // Just in case...
450
- if (!is_array($options)) {
451
- $options = array();
452
- }
453
-
454
- // This code filters the HTML to remove javascript and unsecure attributes and enable the
455
- // "display" rule for CSS which is needed in blocks to force specific "block" or "inline" or "table".
456
- add_filter('safe_style_css', [$this, 'hook_safe_style_css'], 9999);
457
- $options = wp_kses_post_deep($options);
458
- remove_filter('safe_style_css', [$this, 'hook_safe_style_css']);
459
-
460
- $block_options = get_option('newsletter_main');
461
-
462
- $block = $this->get_block($block_id);
463
-
464
- if (!isset($context['type']))
465
- $context['type'] = '';
466
-
467
- // Block not found
468
- if (!$block) {
469
- if ($wrapper) {
470
- 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), '">';
471
- echo '<tr>';
472
- echo '<td data-options="" bgcolor="#ffffff" align="center" style="padding: 0; font-family: Helvetica, Arial, sans-serif;" class="edit-block">';
473
- }
474
- echo $this->get_outlook_wrapper_open($width);
475
-
476
- echo '<p>Ops, this block type is not avalable.</p>';
477
-
478
- echo $this->get_outlook_wrapper_close();
479
-
480
- if ($wrapper) {
481
- echo '</td></tr></table>';
482
- }
483
- return;
484
- }
485
-
486
- $out = ['subject' => '', 'return_empty_message' => false, 'stop' => false, 'skip' => false];
487
-
488
- $dir = is_rtl() ? 'rtl' : 'ltr';
489
- $align_left = is_rtl() ? 'right' : 'left';
490
- $align_right = is_rtl() ? 'left' : 'right';
491
-
492
- ob_start();
493
- $logger = $this->logger;
494
- include $block['dir'] . '/block.php';
495
- $content = trim(ob_get_clean());
496
-
497
- if (empty($content)) {
498
- return $out;
499
- }
500
-
501
- $common_defaults = array(
502
- 'block_padding_top' => 0,
503
- 'block_padding_bottom' => 0,
504
- 'block_padding_right' => 0,
505
- 'block_padding_left' => 0,
506
- 'block_background' => '',
507
- 'block_background_2' => '',
508
- 'block_width' => 600,
509
- 'block_align' => 'center'
510
- );
511
-
512
- $options = array_merge($common_defaults, $options);
513
-
514
- // Obsolete
515
- $content = str_replace('{width}', $width, $content);
516
-
517
- $content = $this->inline_css($content, true);
518
-
519
- // CSS driven by the block
520
- // Requited for the server side parsing and rendering
521
- $options['block_id'] = $block_id;
522
-
523
- $options['block_padding_top'] = (int) str_replace('px', '', $options['block_padding_top']);
524
- $options['block_padding_bottom'] = (int) str_replace('px', '', $options['block_padding_bottom']);
525
- $options['block_padding_right'] = (int) str_replace('px', '', $options['block_padding_right']);
526
- $options['block_padding_left'] = (int) str_replace('px', '', $options['block_padding_left']);
527
-
528
- $block_background = empty($options['block_background']) ? $global_block_background : $options['block_background'];
529
-
530
- // Internal TD wrapper
531
- $style = 'text-align: center; ';
532
- $style .= 'width: 100% !important; ';
533
- $style .= 'line-height: normal !important; ';
534
- $style .= 'letter-spacing: normal; ';
535
- $style .= 'padding-top: ' . $options['block_padding_top'] . 'px; ';
536
- $style .= 'padding-left: ' . $options['block_padding_left'] . 'px; ';
537
- $style .= 'padding-right: ' . $options['block_padding_right'] . 'px; ';
538
- $style .= 'padding-bottom: ' . $options['block_padding_bottom'] . 'px; ';
539
- $style .= 'background-color: ' . $block_background . ';';
540
-
541
- if (isset($options['block_background_gradient'])) {
542
- $style .= 'background: linear-gradient(180deg, ' . $block_background . ' 0%, ' . $options['block_background_2'] . ' 100%);';
543
- }
544
-
545
- $data = $this->options_encode($options);
546
- // First time block creation wrapper
547
- if ($wrapper) {
548
- 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";
549
- echo "<tr>";
550
- echo '<td align="center" style="padding: 0;" class="edit-block">', "\n";
551
- }
552
-
553
- // Container that fixes the width and makes the block responsive
554
- echo $this->get_outlook_wrapper_open($options['block_width']);
555
-
556
- 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";
557
- echo "<tr>";
558
- echo '<td align="', esc_attr($options['block_align']), '" style="', $style, '" bgcolor="', $block_background, '" width="100%">';
559
-
560
- //echo "<!-- block generated content -->\n";
561
- echo trim($content);
562
- //echo "\n<!-- /block generated content -->\n";
563
-
564
- echo "</td></tr></table>";
565
- echo $this->get_outlook_wrapper_close();
566
-
567
- // First time block creation wrapper
568
- if ($wrapper) {
569
- echo "</td></tr></table>";
570
- }
571
-
572
- return $out;
573
- }
574
-
575
- /**
576
- * Ajax call to render a block with a new set of options after the settings popup
577
- * has been saved.
578
- *
579
- * @param type $block_id
580
- * @param type $wrapper
581
- */
582
- function tnpc_render_callback() {
583
- if (!check_ajax_referer('save')) {
584
- $this->dienow('Expired request');
585
- }
586
-
587
- $block_id = $_POST['id'];
588
- $wrapper = isset($_POST['full']);
589
- $options = $this->restore_options_from_request();
590
-
591
- $this->render_block($block_id, $wrapper, $options, [], $_POST['composer']);
592
- wp_die();
593
- }
594
-
595
- function hook_wp_ajax_tnpc_regenerate_email() {
596
-
597
- $content = stripslashes($_POST['content']);
598
- $global_options = $_POST['composer'];
599
-
600
- $regenerated_content = $this->regenerate_email_blocks($content, $global_options);
601
-
602
- wp_send_json_success([
603
- 'content' => $regenerated_content,
604
- 'message' => __('Successfully updated', 'newsletter')
605
- ]);
606
- }
607
-
608
- private function regenerate_email_blocks($content, $global_options) {
609
-
610
- $raw_block_options = $this->extract_encoded_blocks_options($content);
611
-
612
- $regenerated_content = '';
613
-
614
- foreach ($raw_block_options as $raw_block_option) {
615
-
616
- /* $a = html_entity_decode( $raw_block_option, ENT_QUOTES, 'UTF-8' );
617
- $block_options = $this->options_decode( $a ); */
618
-
619
- $block_options = $this->options_decode($raw_block_option);
620
-
621
- $block = $this->get_block($block_options['block_id']);
622
- if (!$block) {
623
- $this->logger->debug('Unable to load the block ' . $block_options['block_id']);
624
- }
625
-
626
- ob_start();
627
- $this->render_block($block_options['block_id'], true, $block_options, [], $global_options);
628
- $block_html = ob_get_clean();
629
-
630
- $regenerated_content .= $block_html;
631
- }
632
-
633
- return $regenerated_content;
634
- }
635
-
636
- /**
637
- * @param string $html_email_content Email html content
638
- *
639
- * @return string[] Encoded options of email blocks
640
- */
641
- private function extract_encoded_blocks_options($html_email_content) {
642
-
643
- preg_match_all('/data-json="(.*?)"/m', $html_email_content, $raw_block_options, PREG_PATTERN_ORDER);
644
-
645
- return $raw_block_options[1];
646
- }
647
-
648
- function tnpc_preview_callback() {
649
- $email = Newsletter::instance()->get_email($_REQUEST['id'], ARRAY_A);
650
-
651
- if (empty($email)) {
652
- echo 'Wrong email identifier';
653
- return;
654
- }
655
-
656
- echo $email['message'];
657
-
658
- wp_die();
659
- }
660
-
661
- function tnpc_css_callback() {
662
- include NEWSLETTER_DIR . '/emails/tnp-composer/css/newsletter.css';
663
- wp_die();
664
- }
665
-
666
- /** Returns the correct admin page to edit the newsletter with the correct editor. */
667
- function get_editor_url($email_id, $editor_type) {
668
- switch ($editor_type) {
669
- case NewsletterEmails::EDITOR_COMPOSER:
670
- return admin_url("admin.php") . '?page=newsletter_emails_composer&id=' . $email_id;
671
- case NewsletterEmails::EDITOR_HTML:
672
- return admin_url("admin.php") . '?page=newsletter_emails_editorhtml&id=' . $email_id;
673
- case NewsletterEmails::EDITOR_TINYMCE:
674
- return admin_url("admin.php") . '?page=newsletter_emails_editortinymce&id=' . $email_id;
675
- }
676
- }
677
-
678
- /**
679
- * Returns the button linked to the correct "edit" page for the passed newsletter. The edit page can be an editor
680
- * or the targeting page (it depends on newsletter status).
681
- *
682
- * @param TNP_Email $email
683
- */
684
- function get_edit_button($email, $only_icon = false) {
685
-
686
- $editor_type = $this->get_editor_type($email);
687
- if ($email->status == 'new') {
688
- $edit_url = $this->get_editor_url($email->id, $editor_type);
689
- } else {
690
- $edit_url = 'admin.php?page=newsletter_emails_edit&id=' . $email->id;
691
- }
692
- switch ($editor_type) {
693
- case NewsletterEmails::EDITOR_COMPOSER:
694
- $icon_class = 'th-large';
695
- break;
696
- case NewsletterEmails::EDITOR_HTML:
697
- $icon_class = 'code';
698
- break;
699
- default:
700
- $icon_class = 'edit';
701
- break;
702
- }
703
- if ($only_icon) {
704
- return '<a class="button-primary" href="' . $edit_url . '" title="' . esc_attr__('Edit', 'newsletter') . '">' .
705
- '<i class="fas fa-' . $icon_class . '"></i></a>';
706
- } else {
707
- return '<a class="button-primary" href="' . $edit_url . '" title="' . esc_attr__('Edit', 'newsletter') . '">' .
708
- '<i class="fas fa-' . $icon_class . '"></i> ' . __('Edit', 'newsletter') . '</a>';
709
- }
710
- }
711
-
712
- /** Returns the correct editor type for the provided newsletter. Contains backward compatibility code. */
713
- function get_editor_type($email) {
714
- $email = (object) $email;
715
- $editor_type = $email->editor;
716
-
717
- // Backward compatibility
718
- $email_options = maybe_unserialize($email->options);
719
- if (isset($email_options['composer'])) {
720
- $editor_type = NewsletterEmails::EDITOR_COMPOSER;
721
- }
722
- // End backward compatibility
723
-
724
- return $editor_type;
725
- }
726
-
727
- /**
728
- *
729
- * @param type $action
730
- * @param type $user
731
- * @param type $email
732
- * @return type
733
- * @global wpdb $wpdb
734
- */
735
- function hook_newsletter_action($action, $user, $email) {
736
- global $wpdb;
737
-
738
- switch ($action) {
739
- case 'v':
740
- case 'view':
741
- $id = $_GET['id'];
742
- if ($id == 'last') {
743
- $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");
744
- } else {
745
- $email = $this->get_email($_GET['id']);
746
- }
747
- if (empty($email)) {
748
- header("HTTP/1.0 404 Not Found");
749
- die('Email not found');
750
- }
751
-
752
- if (!Newsletter::instance()->is_allowed()) {
753
-
754
- if ($email->status == 'new') {
755
- header("HTTP/1.0 404 Not Found");
756
- die('Not sent yet');
757
- }
758
-
759
- if ($email->private == 1) {
760
- if (!$user) {
761
- header("HTTP/1.0 404 Not Found");
762
- die('No available for online view');
763
- }
764
- $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));
765
- if (!$sent) {
766
- header("HTTP/1.0 404 Not Found");
767
- die('No available for online view');
768
- }
769
- }
770
- }
771
-
772
-
773
- header('Content-Type: text/html;charset=UTF-8');
774
- header('X-Robots-Tag: noindex,nofollow,noarchive');
775
- header('Cache-Control: no-cache,no-store,private');
776
-
777
- echo $this->replace($email->message, $user, $email);
778
-
779
- die();
780
- break;
781
-
782
- case 'emails-css':
783
- $email_id = (int) $_GET['id'];
784
-
785
- $body = Newsletter::instance()->get_email_field($email_id, 'message');
786
-
787
- $x = strpos($body, '<style');
788
- if ($x === false)
789
- return;
790
-
791
- $x = strpos($body, '>', $x);
792
- $y = strpos($body, '</style>');
793
-
794
- header('Content-Type: text/css;charset=UTF-8');
795
-
796
- echo substr($body, $x + 1, $y - $x - 1);
797
-
798
- die();
799
- break;
800
-
801
- case 'emails-composer-css':
802
- header('Cache: no-cache');
803
- header('Content-Type: text/css');
804
- echo $this->get_composer_css();
805
- die();
806
- break;
807
-
808
- case 'emails-preview':
809
- if (!Newsletter::instance()->is_allowed()) {
810
- die('Not enough privileges');
811
- }
812
-
813
- if (!check_admin_referer('view')) {
814
- die();
815
- }
816
-
817
- $theme_id = $_GET['id'];
818
- $theme = $this->themes->get_theme($theme_id);
819
-
820
- // Used by theme code
821
- $theme_options = $this->themes->get_options($theme_id);
822
-
823
- $theme_url = $theme['url'];
824
-
825
- header('Content-Type: text/html;charset=UTF-8');
826
-
827
- include $theme['dir'] . '/theme.php';
828
-
829
- die();
830
- break;
831
-
832
- case 'emails-preview-text':
833
- header('Content-Type: text/plain;charset=UTF-8');
834
- if (!Newsletter::instance()->is_allowed()) {
835
- die('Not enough privileges');
836
- }
837
-
838
- if (!check_admin_referer('view')) {
839
- die();
840
- }
841
-
842
- // Used by theme code
843
- $theme_options = $this->get_current_theme_options();
844
-
845
- $file = include $theme['dir'] . '/theme-text.php';
846
-
847
- if (is_file($file)) {
848
- include $file;
849
- }
850
-
851
- die();
852
- break;
853
-
854
- case 'emails-create':
855
- // Newsletter from themes are created on frontend context because sometime WP themes change the way the content,
856
- // excerpt, thumbnail are extracted.
857
- if (!Newsletter::instance()->is_allowed()) {
858
- die('Not enough privileges');
859
- }
860
-
861
- require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
862
- $controls = new NewsletterControls();
863
-
864
- if (!$controls->is_action('create')) {
865
- die('Wrong call');
866
- }
867
-
868
- $theme_id = $controls->data['id'];
869
- $theme = $this->themes->get_theme($theme_id);
870
-
871
- if (!$theme) {
872
- die('invalid theme');
873
- }
874
-
875
- $this->themes->save_options($theme_id, $controls->data);
876
-
877
- $email = array();
878
- $email['status'] = 'new';
879
- $email['subject'] = ''; //__('Here the email subject', 'newsletter');
880
- $email['track'] = Newsletter::instance()->options['track'];
881
- $email['send_on'] = time();
882
- $email['editor'] = NewsletterEmails::EDITOR_TINYMCE;
883
- $email['type'] = 'message';
884
-
885
- $theme_options = $this->themes->get_options($theme_id);
886
-
887
- $theme_url = $theme['url'];
888
- $theme_subject = '';
889
-
890
- ob_start();
891
- include $theme['dir'] . '/theme.php';
892
- $email['message'] = ob_get_clean();
893
-
894
- if (!empty($theme_subject)) {
895
- $email['subject'] = $theme_subject;
896
- }
897
-
898
- if (file_exists($theme['dir'] . '/theme-text.php')) {
899
- ob_start();
900
- include $theme['dir'] . '/theme-text.php';
901
- $email['message_text'] = ob_get_clean();
902
- } else {
903
- $email['message_text'] = 'You need a modern email client to read this email. Read it online: {email_url}.';
904
- }
905
-
906
- $email = $this->save_email($email);
907
-
908
- $edit_url = $this->get_editor_url($email->id, $email->editor);
909
-
910
- header('Location: ' . $edit_url);
911
-
912
- die();
913
- break;
914
- }
915
- }
916
-
917
- function admin_menu() {
918
- $this->add_menu_page('index', 'Newsletters');
919
- $this->add_admin_page('list', 'Email List');
920
- $this->add_admin_page('new', 'Email New');
921
- $this->add_admin_page('edit', 'Email Edit');
922
- $this->add_admin_page('theme', 'Email Themes');
923
- $this->add_admin_page('composer', 'The Composer');
924
- $this->add_admin_page('editorhtml', 'HTML Editor');
925
- $this->add_admin_page('editortinymce', 'TinyMCE Editor');
926
- }
927
-
928
- /**
929
- * Builds a block data structure starting from the folder containing the block
930
- * files.
931
- *
932
- * @param string $dir
933
- * @return array | WP_Error
934
- */
935
- function build_block($dir) {
936
- $dir = realpath($dir);
937
- $dir = wp_normalize_path($dir);
938
- $full_file = $dir . '/block.php';
939
- if (!is_file($full_file)) {
940
- return new WP_Error('1', 'Missing block.php file in ' . $dir);
941
- }
942
-
943
- $relative_dir = substr($dir, strlen(WP_CONTENT_DIR));
944
- $file = basename($dir);
945
-
946
- $data = get_file_data($full_file, ['name' => 'Name', 'section' => 'Section', 'description' => 'Description', 'type' => 'Type']);
947
- $defaults = ['section' => 'content', 'name' => ucfirst($file), 'descritpion' => '', 'icon' => plugins_url('newsletter') . '/admin/images/block-icon.png'];
948
- $data = array_merge($defaults, $data);
949
-
950
- if (is_file($dir . '/icon.png')) {
951
- $data['icon'] = content_url($relative_dir . '/icon.png');
952
- }
953
-
954
- $data['id'] = sanitize_key($file);
955
-
956
- // Absolute path of the block files
957
- $data['dir'] = $dir;
958
- $data['url'] = content_url($relative_dir);
959
-
960
- return $data;
961
- }
962
-
963
- /**
964
- *
965
- * @param type $dir
966
- * @return type
967
- */
968
- function scan_blocks_dir($dir) {
969
- $dir = realpath($dir);
970
- if (!$dir) {
971
- return [];
972
- }
973
- $dir = wp_normalize_path($dir);
974
-
975
- $list = [];
976
- $handle = opendir($dir);
977
- while ($file = readdir($handle)) {
978
-
979
- $data = $this->build_block($dir . '/' . $file);
980
-
981
- if (is_wp_error($data)) {
982
- $this->logger->error($data);
983
- continue;
984
- }
985
- $list[$data['id']] = $data;
986
- }
987
- closedir($handle);
988
- return $list;
989
- }
990
-
991
- /**
992
- * Array of arrays with every registered block and legacy block converted to the new
993
- * format.
994
- *
995
- * @return array
996
- */
997
- function get_blocks() {
998
-
999
- if (!is_null($this->blocks)) {
1000
- return $this->blocks;
1001
- }
1002
-
1003
- $this->blocks = $this->scan_blocks_dir(__DIR__ . '/blocks');
1004
-
1005
- $extended = $this->scan_blocks_dir(WP_CONTENT_DIR . '/extensions/newsletter/blocks');
1006
-
1007
- $this->blocks = array_merge($extended, $this->blocks);
1008
-
1009
- $dirs = apply_filters('newsletter_blocks_dir', array());
1010
-
1011
- //$this->logger->debug('Block dirs:');
1012
- //$this->logger->debug($dirs);
1013
-
1014
- foreach ($dirs as $dir) {
1015
- $list = $this->scan_blocks_dir($dir);
1016
- $this->blocks = array_merge($list, $this->blocks);
1017
- }
1018
-
1019
- do_action('newsletter_register_blocks');
1020
-
1021
- foreach (TNP_Composer::$block_dirs as $dir) {
1022
- $block = $this->build_block($dir);
1023
- if (is_wp_error($block)) {
1024
- $this->logger->error($block);
1025
- continue;
1026
- }
1027
- if (!isset($this->blocks[$block['id']])) {
1028
- $this->blocks[$block['id']] = $block;
1029
- } else {
1030
- $this->logger->error('The block "' . $block['id'] . '" has already been registered');
1031
- }
1032
- }
1033
-
1034
- $this->blocks = array_reverse($this->blocks);
1035
- return $this->blocks;
1036
- }
1037
-
1038
- /**
1039
- * Return a single block (associative array) checking for legacy ID as well.
1040
- *
1041
- * @param string $id
1042
- * @return array
1043
- */
1044
- function get_block($id) {
1045
- switch ($id) {
1046
- case 'content-03-text.block':
1047
- $id = 'text';
1048
- break;
1049
- case 'footer-03-social.block':
1050
- $id = 'social';
1051
- break;
1052
- case 'footer-02-canspam.block':
1053
- $id = 'canspam';
1054
- break;
1055
- case 'content-05-image.block':
1056
- $id = 'image';
1057
- break;
1058
- case 'header-01-header.block':
1059
- $id = 'header';
1060
- break;
1061
- case 'footer-01-footer.block':
1062
- $id = 'footer';
1063
- break;
1064
- case 'content-02-heading.block':
1065
- $id = 'heading';
1066
- break;
1067
- case 'content-07-twocols.block':
1068
- case 'content-06-posts.block':
1069
- $id = 'posts';
1070
- break;
1071
- case 'content-04-cta.block':
1072
- $id = 'cta';
1073
- break;
1074
- case 'content-01-hero.block':
1075
- $id = 'hero';
1076
- break;
1077
- // case 'content-02-heading.block': $id = '/plugins/newsletter/emails/blocks/heading';
1078
- // break;
1079
- }
1080
-
1081
- // Conversion for old full path ID
1082
- $id = sanitize_key(basename($id));
1083
-
1084
- // TODO: Correct id for compatibility
1085
- $blocks = $this->get_blocks();
1086
- if (!isset($blocks[$id])) {
1087
- return null;
1088
- }
1089
- return $blocks[$id];
1090
- }
1091
-
1092
- function scan_presets_dir($dir = null) {
1093
-
1094
- if (is_null($dir)) {
1095
- $dir = __DIR__ . '/presets';
1096
- }
1097
-
1098
- if (!is_dir($dir)) {
1099
- return array();
1100
- }
1101
-
1102
- $handle = opendir($dir);
1103
- $list = array();
1104
- $relative_dir = substr($dir, strlen(WP_CONTENT_DIR));
1105
- while ($file = readdir($handle)) {
1106
-
1107
- if ($file == '.' || $file == '..')
1108
- continue;
1109
-
1110
- // The block unique key, we should find out how to build it, maybe an hash of the (relative) dir?
1111
- $preset_id = sanitize_key($file);
1112
-
1113
- $full_file = $dir . '/' . $file . '/preset.json';
1114
-
1115
- if (!is_file($full_file)) {
1116
- continue;
1117
- }
1118
-
1119
- $icon = content_url($relative_dir . '/' . $file . '/icon.png');
1120
-
1121
- $list[$preset_id] = $icon;
1122
- }
1123
- closedir($handle);
1124
- return $list;
1125
- }
1126
-
1127
- function get_preset_from_file($id, $dir = null) {
1128
-
1129
- if (is_null($dir)) {
1130
- $dir = __DIR__ . '/presets';
1131
- }
1132
-
1133
- $id = $this->sanitize_file_name($id);
1134
-
1135
- if (!is_dir($dir . '/' . $id) || !in_array($id, self::$PRESETS_LIST)) {
1136
- return array();
1137
- }
1138
-
1139
- $json_content = file_get_contents("$dir/$id/preset.json");
1140
- $json_content = str_replace("{placeholder_base_url}", plugins_url('newsletter') . '/emails/presets', $json_content);
1141
- $json = json_decode($json_content);
1142
- $json->icon = NEWSLETTER_URL . "/emails/presets/$id/icon.png?ver=2";
1143
-
1144
- return $json;
1145
- }
1146
-
1147
- function get_composer_css() {
1148
- $css = file_get_contents(__DIR__ . '/tnp-composer/css/newsletter.css');
1149
- $css .= "\n\n";
1150
- $css .= file_get_contents(__DIR__ . '/tnp-composer/css/backend.css');
1151
- $blocks = $this->get_blocks();
1152
- foreach ($blocks as $block) {
1153
- if (!file_exists($block['dir'] . '/style.css')) {
1154
- continue;
1155
- }
1156
- $css .= "\n\n";
1157
- $css .= "/* " . $block['name'] . " */\n";
1158
- $css .= file_get_contents($block['dir'] . '/style.css');
1159
- }
1160
- return $css;
1161
- }
1162
-
1163
- /**
1164
- * Send an email to the test subscribers.
1165
- *
1166
- * @param TNP_Email $email Could be any object with the TNP_Email attributes
1167
- * @param NewsletterControls $controls
1168
- */
1169
- function send_test_email($email, $controls) {
1170
- if (!$email) {
1171
- $controls->errors = __('Newsletter should be saved before send a test', 'newsletter');
1172
- return;
1173
- }
1174
-
1175
- $original_subject = $email->subject;
1176
- $this->set_test_subject_to($email);
1177
-
1178
- $users = NewsletterUsers::instance()->get_test_users();
1179
- if (count($users) == 0) {
1180
- $controls->errors = '' . __('There are no test subscribers to send to', 'newsletter') .
1181
- '. <a href="https://www.thenewsletterplugin.com/plugins/newsletter/subscribers-module#test" target="_blank"><strong>' .
1182
- __('Read more', 'newsletter') . '</strong></a>.';
1183
- } else {
1184
- $r = Newsletter::instance()->send($email, $users, true);
1185
- $emails = array();
1186
- foreach ($users as $user) {
1187
- $emails[] = '<a href="admin.php?page=newsletter_users_edit&id=' . $user->id . '" target="_blank">' . $user->email . '</a>';
1188
- }
1189
- if (is_wp_error($r)) {
1190
- $controls->errors = 'Something went wrong. Check the error logs on status page.<br>';
1191
- $controls->errors .= __('Test subscribers:', 'newsletter');
1192
- $controls->errors .= ' ' . implode(', ', $emails);
1193
- $controls->errors .= '<br>';
1194
- $controls->errors .= '<strong>' . esc_html($r->get_error_message()) . '</strong><br>';
1195
- $controls->errors .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
1196
- } else {
1197
- $controls->messages = __('Test subscribers:', 'newsletter');
1198
-
1199
- $controls->messages .= ' ' . implode(', ', $emails);
1200
- $controls->messages .= '.<br>';
1201
- $controls->messages .= '<a href="https://www.thenewsletterplugin.com/documentation/subscribers#test" target="_blank"><strong>' .
1202
- __('Read more about test subscribers', 'newsletter') . '</strong></a>.<br>';
1203
- $controls->messages .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
1204
- }
1205
- }
1206
- $email->subject = $original_subject;
1207
- }
1208
-
1209
- /**
1210
- * Send an email to the test subscribers.
1211
- *
1212
- * @param TNP_Email $email Could be any object with the TNP_Email attributes
1213
- * @param string $email_address
1214
- *
1215
- * @throws Exception
1216
- */
1217
- function send_test_newsletter_to_email_address($email, $email_address) {
1218
-
1219
- if (!$email) {
1220
- throw new Exception(__('Newsletter should be saved before send a test', 'newsletter'));
1221
- }
1222
-
1223
- $this->set_test_subject_to($email);
1224
-
1225
- $dummy_subscriber = $this->make_dummy_subscriber();
1226
- $dummy_subscriber->email = $email_address;
1227
-
1228
- $result = Newsletter::instance()->send($email, [$dummy_subscriber], true);
1229
-
1230
- $email = '<a href="admin.php?page=newsletter_users_edit&id=' . $dummy_subscriber->id . '" target="_blank">' . $dummy_subscriber->email . '</a>';
1231
-
1232
- if (is_wp_error($result)) {
1233
- $error_message = 'Something went wrong. Check the error logs on status page.<br>';
1234
- $error_message .= __('Test subscribers:', 'newsletter');
1235
- $error_message .= ' ' . $email;
1236
- $error_message .= '<br>';
1237
- $error_message .= '<strong>' . esc_html($result->get_error_message()) . '</strong><br>';
1238
- $error_message .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
1239
- throw new Exception($error_message);
1240
- }
1241
-
1242
- $messages = __('Test subscribers:', 'newsletter');
1243
-
1244
- $messages .= ' ' . $email;
1245
- $messages .= '.<br>';
1246
- $messages .= '<a href="https://www.thenewsletterplugin.com/documentation/subscribers#test" target="_blank"><strong>' .
1247
- __('Read more about test subscribers', 'newsletter') . '</strong></a>.<br>';
1248
- $messages .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
1249
-
1250
- return $messages;
1251
- }
1252
-
1253
- private function set_test_subject_to($email) {
1254
- if ($email->subject == '') {
1255
- $email->subject = '[TEST] Dummy subject, it was empty (remember to set it)';
1256
- } else {
1257
- $email->subject = $email->subject . ' (TEST)';
1258
- }
1259
- }
1260
-
1261
- private function make_dummy_subscriber() {
1262
- $dummy_user = new TNP_User();
1263
- $dummy_user->id = 0;
1264
- $dummy_user->email = 'john.doe@example.org';
1265
- $dummy_user->name = 'John';
1266
- $dummy_user->surname = 'Doe';
1267
- $dummy_user->sex = 'n';
1268
- $dummy_user->language = '';
1269
- $dummy_user->ip = '';
1270
-
1271
- for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
1272
- $profile_key = "profile_$i";
1273
- $dummy_user->$profile_key = '';
1274
- }
1275
-
1276
- return $dummy_user;
1277
- }
1278
-
1279
- function restore_options_from_request() {
1280
-
1281
- require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
1282
- $controls = new NewsletterControls();
1283
- $options = $controls->data;
1284
-
1285
- if (isset($_POST['options']) && is_array($_POST['options'])) {
1286
- // Get all block options
1287
- //$options = stripslashes_deep($_POST['options']);
1288
- // Deserialize inline edits when
1289
- // render is preformed on saving block options
1290
- if (isset($options['inline_edits']) && !is_array($options['inline_edits'])) {
1291
- $options['inline_edits'] = $this->options_decode($options['inline_edits']);
1292
- }
1293
-
1294
- // Restore inline edits from data-json
1295
- // coming from inline editing
1296
- // and merge with current inline edit
1297
- if (isset($_POST['encoded_options'])) {
1298
- $decoded_options = $this->options_decode($_POST['encoded_options']);
1299
-
1300
- $to_merge_inline_edits = [];
1301
-
1302
- if (isset($decoded_options['inline_edits'])) {
1303
- foreach ($decoded_options['inline_edits'] as $decoded_inline_edit) {
1304
- $to_merge_inline_edits[$decoded_inline_edit['post_id'] . $decoded_inline_edit['type']] = $decoded_inline_edit;
1305
- }
1306
- }
1307
-
1308
- //Overwrite with new edited content
1309
- if (isset($options['inline_edits'])) {
1310
- foreach ($options['inline_edits'] as $inline_edit) {
1311
- $to_merge_inline_edits[$inline_edit['post_id'] . $inline_edit['type']] = $inline_edit;
1312
- }
1313
- }
1314
-
1315
- $options['inline_edits'] = array_values($to_merge_inline_edits);
1316
- $options = array_merge($decoded_options, $options);
1317
- }
1318
-
1319
- return $options;
1320
- }
1321
-
1322
- return array();
1323
- }
1324
-
1325
- public function hook_wp_ajax_tnpc_delete_preset() {
1326
-
1327
- if (!wp_verify_nonce($_POST['_wpnonce'], 'preset')) {
1328
- wp_send_json_error('Expired request');
1329
- }
1330
-
1331
- $preset_id = (int) $_REQUEST['presetId'];
1332
-
1333
- $newsletter = Newsletter::instance();
1334
-
1335
- if ($preset_id > 0) {
1336
- $preset = $newsletter->get_email($preset_id);
1337
-
1338
- if ($preset && $preset->type === self::PRESET_EMAIL_TYPE) {
1339
- Newsletter::instance()->delete_email($preset_id);
1340
- wp_send_json_success();
1341
- } else {
1342
- wp_send_json_error(__('Is not a preset!', 'newsletter'));
1343
- }
1344
- } else {
1345
- wp_send_json_error();
1346
- }
1347
- }
1348
-
1349
- }
1350
-
1351
- 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
+ preg_match_all('/data-json="(.*?)"/m', $email->message, $matches, PREG_PATTERN_ORDER);
350
+
351
+ $result = '';
352
+ $subject = '';
353
+
354
+ foreach ($matches[1] as $match) {
355
+ $a = html_entity_decode($match, ENT_QUOTES, 'UTF-8');
356
+ $options = $this->options_decode($a);
357
+
358
+ $block = $this->get_block($options['block_id']);
359
+ if (!$block) {
360
+ $this->logger->debug('Unable to load the block ' . $options['block_id']);
361
+ //continue;
362
+ }
363
+
364
+ ob_start();
365
+ $out = $this->render_block($options['block_id'], true, $options, $context);
366
+ if (is_array($out)) {
367
+ if ($out['return_empty_message'] || $out['stop']) {
368
+ return false;
369
+ }
370
+ if ($out['skip']) {
371
+ continue;
372
+ }
373
+ if (empty($subject) && !empty($out['subject'])) {
374
+ $subject = $out['subject'];
375
+ }
376
+ }
377
+ $block_html = ob_get_clean();
378
+ $result .= $block_html;
379
+ }
380
+
381
+ $email->message = TNP_Composer::get_html_open($email) . TNP_Composer::get_main_wrapper_open($email) .
382
+ $result . TNP_Composer::get_main_wrapper_close($email) . TNP_Composer::get_html_close($email);
383
+ $email->subject = $subject;
384
+ return true;
385
+ }
386
+
387
+ function remove_block_data($text) {
388
+ // TODO: Lavorare!
389
+ return $text;
390
+ }
391
+
392
+ static function get_outlook_wrapper_open($width = 600) {
393
+ 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]-->';
394
+ }
395
+
396
+ static function get_outlook_wrapper_close() {
397
+ return "<!--[if mso | IE]></td></tr></table><![endif]-->";
398
+ }
399
+
400
+ function hook_safe_style_css($rules) {
401
+ $rules[] = 'display';
402
+ return $rules;
403
+ }
404
+
405
+ /**
406
+ * Renders a block identified by its id, using the block options and adding a wrapper
407
+ * if required (for the first block rendering).
408
+ *
409
+ * @param string $block_id
410
+ * @param boolean $wrapper
411
+ * @param array $options
412
+ * @param array $context
413
+ * @param array $composer
414
+ */
415
+ function render_block($block_id = null, $wrapper = false, $options = [], $context = [], $composer = []) {
416
+ static $kses_style_filter = false;
417
+ include_once NEWSLETTER_INCLUDES_DIR . '/helper.php';
418
+
419
+ //Remove 'options_composer_' prefix
420
+ $composer_defaults = [];
421
+ foreach (TNP_Composer::get_global_style_defaults() as $global_option_name => $global_option) {
422
+ $composer_defaults[str_replace('options_composer_', '', $global_option_name)] = $global_option;
423
+ }
424
+ $composer = array_merge($composer_defaults, $composer);
425
+
426
+ $width = 600;
427
+ $font_family = 'Helvetica, Arial, sans-serif';
428
+
429
+ $global_title_font_family = $composer['title_font_family'];
430
+ $global_title_font_size = $composer['title_font_size'];
431
+ $global_title_font_color = $composer['title_font_color'];
432
+ $global_title_font_weight = $composer['title_font_weight'];
433
+
434
+ $global_text_font_family = $composer['text_font_family'];
435
+ $global_text_font_size = $composer['text_font_size'];
436
+ $global_text_font_color = $composer['text_font_color'];
437
+ $global_text_font_weight = $composer['text_font_weight'];
438
+
439
+ $global_button_font_family = $composer['button_font_family'];
440
+ $global_button_font_size = $composer['button_font_size'];
441
+ $global_button_font_color = $composer['button_font_color'];
442
+ $global_button_font_weight = $composer['button_font_weight'];
443
+ $global_button_background_color = $composer['button_background_color'];
444
+
445
+ $global_block_background = $composer['block_background'];
446
+
447
+ $info = Newsletter::instance()->get_options('info');
448
+
449
+ // Just in case...
450
+ if (!is_array($options)) {
451
+ $options = array();
452
+ }
453
+
454
+ // This code filters the HTML to remove javascript and unsecure attributes and enable the
455
+ // "display" rule for CSS which is needed in blocks to force specific "block" or "inline" or "table".
456
+ add_filter('safe_style_css', [$this, 'hook_safe_style_css'], 9999);
457
+ $options = wp_kses_post_deep($options);
458
+ remove_filter('safe_style_css', [$this, 'hook_safe_style_css']);
459
+
460
+ $block_options = get_option('newsletter_main');
461
+
462
+ $block = $this->get_block($block_id);
463
+
464
+ if (!isset($context['type']))
465
+ $context['type'] = '';
466
+
467
+ // Block not found
468
+ if (!$block) {
469
+ if ($wrapper) {
470
+ 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), '">';
471
+ echo '<tr>';
472
+ echo '<td data-options="" bgcolor="#ffffff" align="center" style="padding: 0; font-family: Helvetica, Arial, sans-serif;" class="edit-block">';
473
+ }
474
+ echo $this->get_outlook_wrapper_open($width);
475
+
476
+ echo '<p>Ops, this block type is not avalable.</p>';
477
+
478
+ echo $this->get_outlook_wrapper_close();
479
+
480
+ if ($wrapper) {
481
+ echo '</td></tr></table>';
482
+ }
483
+ return;
484
+ }
485
+
486
+ $out = ['subject' => '', 'return_empty_message' => false, 'stop' => false, 'skip' => false];
487
+
488
+ $dir = is_rtl() ? 'rtl' : 'ltr';
489
+ $align_left = is_rtl() ? 'right' : 'left';
490
+ $align_right = is_rtl() ? 'left' : 'right';
491
+
492
+ ob_start();
493
+ $logger = $this->logger;
494
+ include $block['dir'] . '/block.php';
495
+ $content = trim(ob_get_clean());
496
+
497
+ if (empty($content)) {
498
+ return $out;
499
+ }
500
+
501
+ $common_defaults = array(
502
+ 'block_padding_top' => 0,
503
+ 'block_padding_bottom' => 0,
504
+ 'block_padding_right' => 0,
505
+ 'block_padding_left' => 0,
506
+ 'block_background' => '',
507
+ 'block_background_2' => '',
508
+ 'block_width' => 600,
509
+ 'block_align' => 'center'
510
+ );
511
+
512
+ $options = array_merge($common_defaults, $options);
513
+
514
+ // Obsolete
515
+ $content = str_replace('{width}', $width, $content);
516
+
517
+ $content = $this->inline_css($content, true);
518
+
519
+ // CSS driven by the block
520
+ // Requited for the server side parsing and rendering
521
+ $options['block_id'] = $block_id;
522
+
523
+ $options['block_padding_top'] = (int) str_replace('px', '', $options['block_padding_top']);
524
+ $options['block_padding_bottom'] = (int) str_replace('px', '', $options['block_padding_bottom']);
525
+ $options['block_padding_right'] = (int) str_replace('px', '', $options['block_padding_right']);
526
+ $options['block_padding_left'] = (int) str_replace('px', '', $options['block_padding_left']);
527
+
528
+ $block_background = empty($options['block_background']) ? $global_block_background : $options['block_background'];
529
+
530
+ // Internal TD wrapper
531
+ $style = 'text-align: center; ';
532
+ $style .= 'width: 100% !important; ';
533
+ $style .= 'line-height: normal !important; ';
534
+ $style .= 'letter-spacing: normal; ';
535
+ $style .= 'padding-top: ' . $options['block_padding_top'] . 'px; ';
536
+ $style .= 'padding-left: ' . $options['block_padding_left'] . 'px; ';
537
+ $style .= 'padding-right: ' . $options['block_padding_right'] . 'px; ';
538
+ $style .= 'padding-bottom: ' . $options['block_padding_bottom'] . 'px; ';
539
+ $style .= 'background-color: ' . $block_background . ';';
540
+
541
+ if (isset($options['block_background_gradient'])) {
542
+ $style .= 'background: linear-gradient(180deg, ' . $block_background . ' 0%, ' . $options['block_background_2'] . ' 100%);';
543
+ }
544
+
545
+ $data = $this->options_encode($options);
546
+ // First time block creation wrapper
547
+ if ($wrapper) {
548
+ 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";
549
+ echo "<tr>";
550
+ echo '<td align="center" style="padding: 0;" class="edit-block">', "\n";
551
+ }
552
+
553
+ // Container that fixes the width and makes the block responsive
554
+ echo $this->get_outlook_wrapper_open($options['block_width']);
555
+
556
+ 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";
557
+ echo "<tr>";
558
+ echo '<td align="', esc_attr($options['block_align']), '" style="', $style, '" bgcolor="', $block_background, '" width="100%">';
559
+
560
+ //echo "<!-- block generated content -->\n";
561
+ echo trim($content);
562
+ //echo "\n<!-- /block generated content -->\n";
563
+
564
+ echo "</td></tr></table>";
565
+ echo $this->get_outlook_wrapper_close();
566
+
567
+ // First time block creation wrapper
568
+ if ($wrapper) {
569
+ echo "</td></tr></table>";
570
+ }
571
+
572
+ return $out;
573
+ }
574
+
575
+ /**
576
+ * Ajax call to render a block with a new set of options after the settings popup
577
+ * has been saved.
578
+ *
579
+ * @param type $block_id
580
+ * @param type $wrapper
581
+ */
582
+ function tnpc_render_callback() {
583
+ if (!check_ajax_referer('save')) {
584
+ $this->dienow('Expired request');
585
+ }
586
+
587
+ $block_id = $_POST['id'];
588
+ $wrapper = isset($_POST['full']);
589
+ $options = $this->restore_options_from_request();
590
+
591
+ $this->render_block($block_id, $wrapper, $options, [], $_POST['composer']);
592
+ wp_die();
593
+ }
594
+
595
+ function hook_wp_ajax_tnpc_regenerate_email() {
596
+
597
+ $content = stripslashes($_POST['content']);
598
+ $global_options = $_POST['composer'];
599
+
600
+ $regenerated_content = $this->regenerate_email_blocks($content, $global_options);
601
+
602
+ wp_send_json_success([
603
+ 'content' => $regenerated_content,
604
+ 'message' => __('Successfully updated', 'newsletter')
605
+ ]);
606
+ }
607
+
608
+ private function regenerate_email_blocks($content, $global_options) {
609
+
610
+ $raw_block_options = $this->extract_encoded_blocks_options($content);
611
+
612
+ $regenerated_content = '';
613
+
614
+ foreach ($raw_block_options as $raw_block_option) {
615
+
616
+ /* $a = html_entity_decode( $raw_block_option, ENT_QUOTES, 'UTF-8' );
617
+ $block_options = $this->options_decode( $a ); */
618
+
619
+ $block_options = $this->options_decode($raw_block_option);
620
+
621
+ $block = $this->get_block($block_options['block_id']);
622
+ if (!$block) {
623
+ $this->logger->debug('Unable to load the block ' . $block_options['block_id']);
624
+ }
625
+
626
+ ob_start();
627
+ $this->render_block($block_options['block_id'], true, $block_options, [], $global_options);
628
+ $block_html = ob_get_clean();
629
+
630
+ $regenerated_content .= $block_html;
631
+ }
632
+
633
+ return $regenerated_content;
634
+ }
635
+
636
+ /**
637
+ * @param string $html_email_content Email html content
638
+ *
639
+ * @return string[] Encoded options of email blocks
640
+ */
641
+ private function extract_encoded_blocks_options($html_email_content) {
642
+
643
+ preg_match_all('/data-json="(.*?)"/m', $html_email_content, $raw_block_options, PREG_PATTERN_ORDER);
644
+
645
+ return $raw_block_options[1];
646
+ }
647
+
648
+ function tnpc_preview_callback() {
649
+ $email = Newsletter::instance()->get_email($_REQUEST['id'], ARRAY_A);
650
+
651
+ if (empty($email)) {
652
+ echo 'Wrong email identifier';
653
+ return;
654
+ }
655
+
656
+ echo $email['message'];
657
+
658
+ wp_die();
659
+ }
660
+
661
+ function tnpc_css_callback() {
662
+ include NEWSLETTER_DIR . '/emails/tnp-composer/css/newsletter.css';
663
+ wp_die();
664
+ }
665
+
666
+ /** Returns the correct admin page to edit the newsletter with the correct editor. */
667
+ function get_editor_url($email_id, $editor_type) {
668
+ switch ($editor_type) {
669
+ case NewsletterEmails::EDITOR_COMPOSER:
670
+ return admin_url("admin.php") . '?page=newsletter_emails_composer&id=' . $email_id;
671
+ case NewsletterEmails::EDITOR_HTML:
672
+ return admin_url("admin.php") . '?page=newsletter_emails_editorhtml&id=' . $email_id;
673
+ case NewsletterEmails::EDITOR_TINYMCE:
674
+ return admin_url("admin.php") . '?page=newsletter_emails_editortinymce&id=' . $email_id;
675
+ }
676
+ }
677
+
678
+ /**
679
+ * Returns the button linked to the correct "edit" page for the passed newsletter. The edit page can be an editor
680
+ * or the targeting page (it depends on newsletter status).
681
+ *
682
+ * @param TNP_Email $email
683
+ */
684
+ function get_edit_button($email, $only_icon = false) {
685
+
686
+ $editor_type = $this->get_editor_type($email);
687
+ if ($email->status == 'new') {
688
+ $edit_url = $this->get_editor_url($email->id, $editor_type);
689
+ } else {
690
+ $edit_url = 'admin.php?page=newsletter_emails_edit&id=' . $email->id;
691
+ }
692
+ switch ($editor_type) {
693
+ case NewsletterEmails::EDITOR_COMPOSER:
694
+ $icon_class = 'th-large';
695
+ break;
696
+ case NewsletterEmails::EDITOR_HTML:
697
+ $icon_class = 'code';
698
+ break;
699
+ default:
700
+ $icon_class = 'edit';
701
+ break;
702
+ }
703
+ if ($only_icon) {
704
+ return '<a class="button-primary" href="' . $edit_url . '" title="' . esc_attr__('Edit', 'newsletter') . '">' .
705
+ '<i class="fas fa-' . $icon_class . '"></i></a>';
706
+ } else {
707
+ return '<a class="button-primary" href="' . $edit_url . '" title="' . esc_attr__('Edit', 'newsletter') . '">' .
708
+ '<i class="fas fa-' . $icon_class . '"></i> ' . __('Edit', 'newsletter') . '</a>';
709
+ }
710
+ }
711
+
712
+ /** Returns the correct editor type for the provided newsletter. Contains backward compatibility code. */
713
+ function get_editor_type($email) {
714
+ $email = (object) $email;
715
+ $editor_type = $email->editor;
716
+
717
+ // Backward compatibility
718
+ $email_options = maybe_unserialize($email->options);
719
+ if (isset($email_options['composer'])) {
720
+ $editor_type = NewsletterEmails::EDITOR_COMPOSER;
721
+ }
722
+ // End backward compatibility
723
+
724
+ return $editor_type;
725
+ }
726
+
727
+ /**
728
+ *
729
+ * @param type $action
730
+ * @param type $user
731
+ * @param type $email
732
+ * @return type
733
+ * @global wpdb $wpdb
734
+ */
735
+ function hook_newsletter_action($action, $user, $email) {
736
+ global $wpdb;
737
+
738
+ switch ($action) {
739
+ case 'v':
740
+ case 'view':
741
+ $id = $_GET['id'];
742
+ if ($id == 'last') {
743
+ $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");
744
+ } else {
745
+ $email = $this->get_email($_GET['id']);
746
+ }
747
+ if (empty($email)) {
748
+ header("HTTP/1.0 404 Not Found");
749
+ die('Email not found');
750
+ }
751
+
752
+ if (!Newsletter::instance()->is_allowed()) {
753
+
754
+ if ($email->status == 'new') {
755
+ header("HTTP/1.0 404 Not Found");
756
+ die('Not sent yet');
757
+ }
758
+
759
+ if ($email->private == 1) {
760
+ if (!$user) {
761
+ header("HTTP/1.0 404 Not Found");
762
+ die('No available for online view');
763
+ }
764
+ $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));
765
+ if (!$sent) {
766
+ header("HTTP/1.0 404 Not Found");
767
+ die('No available for online view');
768
+ }
769
+ }
770
+ }
771
+
772
+
773
+ header('Content-Type: text/html;charset=UTF-8');
774
+ header('X-Robots-Tag: noindex,nofollow,noarchive');
775
+ header('Cache-Control: no-cache,no-store,private');
776
+
777
+ echo $this->replace($email->message, $user, $email);
778
+
779
+ die();
780
+ break;
781
+
782
+ case 'emails-css':
783
+ $email_id = (int) $_GET['id'];
784
+
785
+ $body = Newsletter::instance()->get_email_field($email_id, 'message');
786
+
787
+ $x = strpos($body, '<style');
788
+ if ($x === false)
789
+ return;
790
+
791
+ $x = strpos($body, '>', $x);
792
+ $y = strpos($body, '</style>');
793
+
794
+ header('Content-Type: text/css;charset=UTF-8');
795
+
796
+ echo substr($body, $x + 1, $y - $x - 1);
797
+
798
+ die();
799
+ break;
800
+
801
+ case 'emails-composer-css':
802
+ header('Cache: no-cache');
803
+ header('Content-Type: text/css');
804
+ echo $this->get_composer_css();
805
+ die();
806
+ break;
807
+
808
+ case 'emails-preview':
809
+ if (!Newsletter::instance()->is_allowed()) {
810
+ die('Not enough privileges');
811
+ }
812
+
813
+ if (!check_admin_referer('view')) {
814
+ die();
815
+ }
816
+
817
+ $theme_id = $_GET['id'];
818
+ $theme = $this->themes->get_theme($theme_id);
819
+
820
+ // Used by theme code
821
+ $theme_options = $this->themes->get_options($theme_id);
822
+
823
+ $theme_url = $theme['url'];
824
+
825
+ header('Content-Type: text/html;charset=UTF-8');
826
+
827
+ include $theme['dir'] . '/theme.php';
828
+
829
+ die();
830
+ break;
831
+
832
+ case 'emails-preview-text':
833
+ header('Content-Type: text/plain;charset=UTF-8');
834
+ if (!Newsletter::instance()->is_allowed()) {
835
+ die('Not enough privileges');
836
+ }
837
+
838
+ if (!check_admin_referer('view')) {
839
+ die();
840
+ }
841
+
842
+ // Used by theme code
843
+ $theme_options = $this->get_current_theme_options();
844
+
845
+ $file = include $theme['dir'] . '/theme-text.php';
846
+
847
+ if (is_file($file)) {
848
+ include $file;
849
+ }
850
+
851
+ die();
852
+ break;
853
+
854
+ case 'emails-create':
855
+ // Newsletter from themes are created on frontend context because sometime WP themes change the way the content,
856
+ // excerpt, thumbnail are extracted.
857
+ if (!Newsletter::instance()->is_allowed()) {
858
+ die('Not enough privileges');
859
+ }
860
+
861
+ require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
862
+ $controls = new NewsletterControls();
863
+
864
+ if (!$controls->is_action('create')) {
865
+ die('Wrong call');
866
+ }
867
+
868
+ $theme_id = $controls->data['id'];
869
+ $theme = $this->themes->get_theme($theme_id);
870
+
871
+ if (!$theme) {
872
+ die('invalid theme');
873
+ }
874
+
875
+ $this->themes->save_options($theme_id, $controls->data);
876
+
877
+ $email = array();
878
+ $email['status'] = 'new';
879
+ $email['subject'] = ''; //__('Here the email subject', 'newsletter');
880
+ $email['track'] = Newsletter::instance()->options['track'];
881
+ $email['send_on'] = time();
882
+ $email['editor'] = NewsletterEmails::EDITOR_TINYMCE;
883
+ $email['type'] = 'message';
884
+
885
+ $theme_options = $this->themes->get_options($theme_id);
886
+
887
+ $theme_url = $theme['url'];
888
+ $theme_subject = '';
889
+
890
+ ob_start();
891
+ include $theme['dir'] . '/theme.php';
892
+ $email['message'] = ob_get_clean();
893
+
894
+ if (!empty($theme_subject)) {
895
+ $email['subject'] = $theme_subject;
896
+ }
897
+
898
+ if (file_exists($theme['dir'] . '/theme-text.php')) {
899
+ ob_start();
900
+ include $theme['dir'] . '/theme-text.php';
901
+ $email['message_text'] = ob_get_clean();
902
+ } else {
903
+ $email['message_text'] = 'You need a modern email client to read this email. Read it online: {email_url}.';
904
+ }
905
+
906
+ $email = $this->save_email($email);
907
+
908
+ $edit_url = $this->get_editor_url($email->id, $email->editor);
909
+
910
+ header('Location: ' . $edit_url);
911
+
912
+ die();
913
+ break;
914
+ }
915
+ }
916
+
917
+ function admin_menu() {
918
+ $this->add_menu_page('index', 'Newsletters');
919
+ $this->add_admin_page('list', 'Email List');
920
+ $this->add_admin_page('new', 'Email New');
921
+ $this->add_admin_page('edit', 'Email Edit');
922
+ $this->add_admin_page('theme', 'Email Themes');
923
+ $this->add_admin_page('composer', 'The Composer');
924
+ $this->add_admin_page('editorhtml', 'HTML Editor');
925
+ $this->add_admin_page('editortinymce', 'TinyMCE Editor');
926
+ }
927
+
928
+ /**
929
+ * Builds a block data structure starting from the folder containing the block
930
+ * files.
931
+ *
932
+ * @param string $dir
933
+ * @return array | WP_Error
934
+ */
935
+ function build_block($dir) {
936
+ $dir = realpath($dir);
937
+ $dir = wp_normalize_path($dir);
938
+ $full_file = $dir . '/block.php';
939
+ if (!is_file($full_file)) {
940
+ return new WP_Error('1', 'Missing block.php file in ' . $dir);
941
+ }
942
+
943
+ $relative_dir = substr($dir, strlen(WP_CONTENT_DIR));
944
+ $file = basename($dir);
945
+
946
+ $data = get_file_data($full_file, ['name' => 'Name', 'section' => 'Section', 'description' => 'Description', 'type' => 'Type']);
947
+ $defaults = ['section' => 'content', 'name' => ucfirst($file), 'descritpion' => '', 'icon' => plugins_url('newsletter') . '/admin/images/block-icon.png'];
948
+ $data = array_merge($defaults, $data);
949
+
950
+ if (is_file($dir . '/icon.png')) {
951
+ $data['icon'] = content_url($relative_dir . '/icon.png');
952
+ }
953
+
954
+ $data['id'] = sanitize_key($file);
955
+
956
+ // Absolute path of the block files
957
+ $data['dir'] = $dir;
958
+ $data['url'] = content_url($relative_dir);
959
+
960
+ return $data;
961
+ }
962
+
963
+ /**
964
+ *
965
+ * @param type $dir
966
+ * @return type
967
+ */
968
+ function scan_blocks_dir($dir) {
969
+ $dir = realpath($dir);
970
+ if (!$dir) {
971
+ return [];
972
+ }
973
+ $dir = wp_normalize_path($dir);
974
+
975
+ $list = [];
976
+ $handle = opendir($dir);
977
+ while ($file = readdir($handle)) {
978
+
979
+ $data = $this->build_block($dir . '/' . $file);
980
+
981
+ if (is_wp_error($data)) {
982
+ $this->logger->error($data);
983
+ continue;
984
+ }
985
+ $list[$data['id']] = $data;
986
+ }
987
+ closedir($handle);
988
+ return $list;
989
+ }
990
+
991
+ /**
992
+ * Array of arrays with every registered block and legacy block converted to the new
993
+ * format.
994
+ *
995
+ * @return array
996
+ */
997
+ function get_blocks() {
998
+
999
+ if (!is_null($this->blocks)) {
1000
+ return $this->blocks;
1001
+ }
1002
+
1003
+ $this->blocks = $this->scan_blocks_dir(__DIR__ . '/blocks');
1004
+
1005
+ $extended = $this->scan_blocks_dir(WP_CONTENT_DIR . '/extensions/newsletter/blocks');
1006
+
1007
+ $this->blocks = array_merge($extended, $this->blocks);
1008
+
1009
+ $dirs = apply_filters('newsletter_blocks_dir', array());
1010
+
1011
+ //$this->logger->debug('Block dirs:');
1012
+ //$this->logger->debug($dirs);
1013
+
1014
+ foreach ($dirs as $dir) {
1015
+ $list = $this->scan_blocks_dir($dir);
1016
+ $this->blocks = array_merge($list, $this->blocks);
1017
+ }
1018
+
1019
+ do_action('newsletter_register_blocks');
1020
+
1021
+ foreach (TNP_Composer::$block_dirs as $dir) {
1022
+ $block = $this->build_block($dir);
1023
+ if (is_wp_error($block)) {
1024
+ $this->logger->error($block);
1025
+ continue;
1026
+ }
1027
+ if (!isset($this->blocks[$block['id']])) {
1028
+ $this->blocks[$block['id']] = $block;
1029
+ } else {
1030
+ $this->logger->error('The block "' . $block['id'] . '" has already been registered');
1031
+ }
1032
+ }
1033
+
1034
+ $this->blocks = array_reverse($this->blocks);
1035
+ return $this->blocks;
1036
+ }
1037
+
1038
+ /**
1039
+ * Return a single block (associative array) checking for legacy ID as well.
1040
+ *
1041
+ * @param string $id
1042
+ * @return array
1043
+ */
1044
+ function get_block($id) {
1045
+ switch ($id) {
1046
+ case 'content-03-text.block':
1047
+ $id = 'text';
1048
+ break;
1049
+ case 'footer-03-social.block':
1050
+ $id = 'social';
1051
+ break;
1052
+ case 'footer-02-canspam.block':
1053
+ $id = 'canspam';
1054
+ break;
1055
+ case 'content-05-image.block':
1056
+ $id = 'image';
1057
+ break;
1058
+ case 'header-01-header.block':
1059
+ $id = 'header';
1060
+ break;
1061
+ case 'footer-01-footer.block':
1062
+ $id = 'footer';
1063
+ break;
1064
+ case 'content-02-heading.block':
1065
+ $id = 'heading';
1066
+ break;
1067
+ case 'content-07-twocols.block':
1068
+ case 'content-06-posts.block':
1069
+ $id = 'posts';
1070
+ break;
1071
+ case 'content-04-cta.block':
1072
+ $id = 'cta';
1073
+ break;
1074
+ case 'content-01-hero.block':
1075
+ $id = 'hero';
1076
+ break;
1077
+ // case 'content-02-heading.block': $id = '/plugins/newsletter/emails/blocks/heading';
1078
+ // break;
1079
+ }
1080
+
1081
+ // Conversion for old full path ID
1082
+ $id = sanitize_key(basename($id));
1083
+
1084
+ // TODO: Correct id for compatibility
1085
+ $blocks = $this->get_blocks();
1086
+ if (!isset($blocks[$id])) {
1087
+ return null;
1088
+ }
1089
+ return $blocks[$id];
1090
+ }
1091
+
1092
+ function scan_presets_dir($dir = null) {
1093
+
1094
+ if (is_null($dir)) {
1095
+ $dir = __DIR__ . '/presets';
1096
+ }
1097
+
1098
+ if (!is_dir($dir)) {
1099
+ return array();
1100
+ }
1101
+
1102
+ $handle = opendir($dir);
1103
+ $list = array();
1104
+ $relative_dir = substr($dir, strlen(WP_CONTENT_DIR));
1105
+ while ($file = readdir($handle)) {
1106
+
1107
+ if ($file == '.' || $file == '..')
1108
+ continue;
1109
+
1110
+ // The block unique key, we should find out how to build it, maybe an hash of the (relative) dir?
1111
+ $preset_id = sanitize_key($file);
1112
+
1113
+ $full_file = $dir . '/' . $file . '/preset.json';
1114
+
1115
+ if (!is_file($full_file)) {
1116
+ continue;
1117
+ }
1118
+
1119
+ $icon = content_url($relative_dir . '/' . $file . '/icon.png');
1120
+
1121
+ $list[$preset_id] = $icon;
1122
+ }
1123
+ closedir($handle);
1124
+ return $list;
1125
+ }
1126
+
1127
+ function get_preset_from_file($id, $dir = null) {
1128
+
1129
+ if (is_null($dir)) {
1130
+ $dir = __DIR__ . '/presets';
1131
+ }
1132
+
1133
+ $id = $this->sanitize_file_name($id);
1134
+
1135
+ if (!is_dir($dir . '/' . $id) || !in_array($id, self::$PRESETS_LIST)) {
1136
+ return array();
1137
+ }
1138
+
1139
+ $json_content = file_get_contents("$dir/$id/preset.json");
1140
+ $json_content = str_replace("{placeholder_base_url}", plugins_url('newsletter') . '/emails/presets', $json_content);
1141
+ $json = json_decode($json_content);
1142
+ $json->icon = NEWSLETTER_URL . "/emails/presets/$id/icon.png?ver=2";
1143
+
1144
+ return $json;
1145
+ }
1146
+
1147
+ function get_composer_css() {
1148
+ $css = file_get_contents(__DIR__ . '/tnp-composer/css/newsletter.css');
1149
+ $css .= "\n\n";
1150
+ $css .= file_get_contents(__DIR__ . '/tnp-composer/css/backend.css');
1151
+ $blocks = $this->get_blocks();
1152
+ foreach ($blocks as $block) {
1153
+ if (!file_exists($block['dir'] . '/style.css')) {
1154
+ continue;
1155
+ }
1156
+ $css .= "\n\n";
1157
+ $css .= "/* " . $block['name'] . " */\n";
1158
+ $css .= file_get_contents($block['dir'] . '/style.css');
1159
+ }
1160
+ return $css;
1161
+ }
1162
+
1163
+ /**
1164
+ * Send an email to the test subscribers.
1165
+ *
1166
+ * @param TNP_Email $email Could be any object with the TNP_Email attributes
1167
+ * @param NewsletterControls $controls
1168
+ */
1169
+ function send_test_email($email, $controls) {
1170
+ if (!$email) {
1171
+ $controls->errors = __('Newsletter should be saved before send a test', 'newsletter');
1172
+ return;
1173
+ }
1174
+
1175
+ $original_subject = $email->subject;
1176
+ $this->set_test_subject_to($email);
1177
+
1178
+ $users = NewsletterUsers::instance()->get_test_users();
1179
+ if (count($users) == 0) {
1180
+ $controls->errors = '' . __('There are no test subscribers to send to', 'newsletter') .
1181
+ '. <a href="https://www.thenewsletterplugin.com/plugins/newsletter/subscribers-module#test" target="_blank"><strong>' .
1182
+ __('Read more', 'newsletter') . '</strong></a>.';
1183
+ } else {
1184
+ $r = Newsletter::instance()->send($email, $users, true);
1185
+ $emails = array();
1186
+ foreach ($users as $user) {
1187
+ $emails[] = '<a href="admin.php?page=newsletter_users_edit&id=' . $user->id . '" target="_blank">' . $user->email . '</a>';
1188
+ }
1189
+ if (is_wp_error($r)) {
1190
+ $controls->errors = 'Something went wrong. Check the error logs on status page.<br>';
1191
+ $controls->errors .= __('Test subscribers:', 'newsletter');
1192
+ $controls->errors .= ' ' . implode(', ', $emails);
1193
+ $controls->errors .= '<br>';
1194
+ $controls->errors .= '<strong>' . esc_html($r->get_error_message()) . '</strong><br>';
1195
+ $controls->errors .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
1196
+ } else {
1197
+ $controls->messages = __('Test subscribers:', 'newsletter');
1198
+
1199
+ $controls->messages .= ' ' . implode(', ', $emails);
1200
+ $controls->messages .= '.<br>';
1201
+ $controls->messages .= '<a href="https://www.thenewsletterplugin.com/documentation/subscribers#test" target="_blank"><strong>' .
1202
+ __('Read more about test subscribers', 'newsletter') . '</strong></a>.<br>';
1203
+ $controls->messages .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
1204
+ }
1205
+ }
1206
+ $email->subject = $original_subject;
1207
+ }
1208
+
1209
+ /**
1210
+ * Send an email to the test subscribers.
1211
+ *
1212
+ * @param TNP_Email $email Could be any object with the TNP_Email attributes
1213
+ * @param string $email_address
1214
+ *
1215
+ * @throws Exception
1216
+ */
1217
+ function send_test_newsletter_to_email_address($email, $email_address) {
1218
+
1219
+ if (!$email) {
1220
+ throw new Exception(__('Newsletter should be saved before send a test', 'newsletter'));
1221
+ }
1222
+
1223
+ $this->set_test_subject_to($email);
1224
+
1225
+ $dummy_subscriber = $this->make_dummy_subscriber();
1226
+ $dummy_subscriber->email = $email_address;
1227
+
1228
+ $result = Newsletter::instance()->send($email, [$dummy_subscriber], true);
1229
+
1230
+ $email = '<a href="admin.php?page=newsletter_users_edit&id=' . $dummy_subscriber->id . '" target="_blank">' . $dummy_subscriber->email . '</a>';
1231
+
1232
+ if (is_wp_error($result)) {
1233
+ $error_message = 'Something went wrong. Check the error logs on status page.<br>';
1234
+ $error_message .= __('Test subscribers:', 'newsletter');
1235
+ $error_message .= ' ' . $email;
1236
+ $error_message .= '<br>';
1237
+ $error_message .= '<strong>' . esc_html($result->get_error_message()) . '</strong><br>';
1238
+ $error_message .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
1239
+ throw new Exception($error_message);
1240
+ }
1241
+
1242
+ $messages = __('Test subscribers:', 'newsletter');
1243
+
1244
+ $messages .= ' ' . $email;
1245
+ $messages .= '.<br>';
1246
+ $messages .= '<a href="https://www.thenewsletterplugin.com/documentation/subscribers#test" target="_blank"><strong>' .
1247
+ __('Read more about test subscribers', 'newsletter') . '</strong></a>.<br>';
1248
+ $messages .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
1249
+
1250
+ return $messages;
1251
+ }
1252
+
1253
+ private function set_test_subject_to($email) {
1254
+ if ($email->subject == '') {
1255
+ $email->subject = '[TEST] Dummy subject, it was empty (remember to set it)';
1256
+ } else {
1257
+ $email->subject = $email->subject . ' (TEST)';
1258
+ }
1259
+ }
1260
+
1261
+ private function make_dummy_subscriber() {
1262
+ $dummy_user = new TNP_User();
1263
+ $dummy_user->id = 0;
1264
+ $dummy_user->email = 'john.doe@example.org';
1265
+ $dummy_user->name = 'John';
1266
+ $dummy_user->surname = 'Doe';
1267
+ $dummy_user->sex = 'n';
1268
+ $dummy_user->language = '';
1269
+ $dummy_user->ip = '';
1270
+
1271
+ for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
1272
+ $profile_key = "profile_$i";
1273
+ $dummy_user->$profile_key = '';
1274
+ }
1275
+
1276
+ return $dummy_user;
1277
+ }
1278
+
1279
+ function restore_options_from_request() {
1280
+
1281
+ require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
1282
+ $controls = new NewsletterControls();
1283
+ $options = $controls->data;
1284
+
1285
+ if (isset($_POST['options']) && is_array($_POST['options'])) {
1286
+ // Get all block options
1287
+ //$options = stripslashes_deep($_POST['options']);
1288
+ // Deserialize inline edits when
1289
+ // render is preformed on saving block options
1290
+ if (isset($options['inline_edits']) && !is_array($options['inline_edits'])) {
1291
+ $options['inline_edits'] = $this->options_decode($options['inline_edits']);
1292
+ }
1293
+
1294
+ // Restore inline edits from data-json
1295
+ // coming from inline editing
1296
+ // and merge with current inline edit
1297
+ if (isset($_POST['encoded_options'])) {
1298
+ $decoded_options = $this->options_decode($_POST['encoded_options']);
1299
+
1300
+ $to_merge_inline_edits = [];
1301
+
1302
+ if (isset($decoded_options['inline_edits'])) {
1303
+ foreach ($decoded_options['inline_edits'] as $decoded_inline_edit) {
1304
+ $to_merge_inline_edits[$decoded_inline_edit['post_id'] . $decoded_inline_edit['type']] = $decoded_inline_edit;
1305
+ }
1306
+ }
1307
+
1308
+ //Overwrite with new edited content
1309
+ if (isset($options['inline_edits'])) {
1310
+ foreach ($options['inline_edits'] as $inline_edit) {
1311
+ $to_merge_inline_edits[$inline_edit['post_id'] . $inline_edit['type']] = $inline_edit;
1312
+ }
1313
+ }
1314
+
1315
+ $options['inline_edits'] = array_values($to_merge_inline_edits);
1316
+ $options = array_merge($decoded_options, $options);
1317
+ }
1318
+
1319
+ return $options;
1320
+ }
1321
+
1322
+ return array();
1323
+ }
1324
+
1325
+ public function hook_wp_ajax_tnpc_delete_preset() {
1326
+
1327
+ if (!wp_verify_nonce($_POST['_wpnonce'], 'preset')) {
1328
+ wp_send_json_error('Expired request');
1329
+ }
1330
+
1331
+ $preset_id = (int) $_REQUEST['presetId'];
1332
+
1333
+ $newsletter = Newsletter::instance();
1334
+
1335
+ if ($preset_id > 0) {
1336
+ $preset = $newsletter->get_email($preset_id);
1337
+
1338
+ if ($preset && $preset->type === self::PRESET_EMAIL_TYPE) {
1339
+ Newsletter::instance()->delete_email($preset_id);
1340
+ wp_send_json_success();
1341
+ } else {
1342
+ wp_send_json_error(__('Is not a preset!', 'newsletter'));
1343
+ }
1344
+ } else {
1345
+ wp_send_json_error();
1346
+ }
1347
+ }
1348
+
1349
+ }
1350
+
1351
+ NewsletterEmails::instance();
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.3.9
8
  Author: Stefano Lissa & The Newsletter Team
9
  Author URI: https://www.thenewsletterplugin.com
10
  Disclaimer: Use at your own risk. No warranty expressed or implied is provided.
@@ -37,7 +37,7 @@ if (version_compare(phpversion(), '5.6', '<')) {
37
  return;
38
  }
39
 
40
- define('NEWSLETTER_VERSION', '7.3.9');
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.4.0
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.4.0');
41
 
42
  global $newsletter, $wpdb;
43
 
readme.txt CHANGED
@@ -1,7 +1,7 @@
1
  === Newsletter ===
2
  Tags: newsletter, email marketing, welcome email, signup forms, contact, lead generation, marketing automation
3
  Tested up to: 5.9
4
- Stable tag: 7.3.9
5
  Contributors: satollo,webagile,michael-travan
6
  License: GPLv2 or later
7
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
@@ -125,6 +125,11 @@ Thank you, The Newsletter Team
125
 
126
  == Changelog ==
127
 
 
 
 
 
 
128
  = 7.3.9 =
129
 
130
  * Fixed grid layout not showing correctly on gmail
1
  === Newsletter ===
2
  Tags: newsletter, email marketing, welcome email, signup forms, contact, lead generation, marketing automation
3
  Tested up to: 5.9
4
+ Stable tag: 7.4.0
5
  Contributors: satollo,webagile,michael-travan
6
  License: GPLv2 or later
7
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
125
 
126
  == Changelog ==
127
 
128
+ = 7.4.0 =
129
+
130
+ * Added privacy links
131
+ * Added filter "newsletter_subscription" (documentation is under writing)
132
+
133
  = 7.3.9 =
134
 
135
  * Fixed grid layout not showing correctly on gmail
subscription/subscription.php CHANGED
@@ -530,13 +530,15 @@ class NewsletterSubscription extends NewsletterModule {
530
 
531
  // Exists?
532
  $user = $this->get_user_by_email($subscription->data->email);
 
 
533
 
534
  // Do we accept repeated subscriptions?
535
  if ($user != null && $subscription->if_exists === TNP_Subscription::EXISTING_ERROR) {
536
  //$this->show_message('error', $user);
537
  return new WP_Error('exists', 'Email address already registered and Newsletter sets to block repeated registrations. You can change this behavior or the user message above on subscription configuration panel.');
538
  }
539
-
540
 
541
  if ($user != null) {
542
 
530
 
531
  // Exists?
532
  $user = $this->get_user_by_email($subscription->data->email);
533
+
534
+ $subscription = apply_filters('newsletter_subscription', $subscription, $user);
535
 
536
  // Do we accept repeated subscriptions?
537
  if ($user != null && $subscription->if_exists === TNP_Subscription::EXISTING_ERROR) {
538
  //$this->show_message('error', $user);
539
  return new WP_Error('exists', 'Email address already registered and Newsletter sets to block repeated registrations. You can change this behavior or the user message above on subscription configuration panel.');
540
  }
541
+
542
 
543
  if ($user != null) {
544
 
system/status.php CHANGED
@@ -1,1077 +1,1091 @@
1
- <?php
2
- /* @var $this NewsletterSystem */
3
- /* @var $wpdb wpdb */
4
-
5
- defined('ABSPATH') || exit;
6
-
7
- wp_enqueue_script('tnp-chart');
8
-
9
- include_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
10
- $controls = new NewsletterControls();
11
-
12
- $newsletter = Newsletter::instance();
13
- $mailer = $newsletter->get_mailer();
14
-
15
- if ($controls->is_action('delete_logs')) {
16
- $files = glob(WP_CONTENT_DIR . '/logs/newsletter/*.txt');
17
- foreach ($files as $file) {
18
- if (is_file($file))
19
- unlink($file);
20
- }
21
- $secret = NewsletterModule::get_token(8);
22
- update_option('newsletter_logger_secret', $secret);
23
- $controls->messages = __('Logs deleted', 'newsletter');
24
- }
25
-
26
- if ($controls->is_action('conversion')) {
27
- $this->logger->info('Maybe convert to utf8mb4');
28
- require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
29
- if (function_exists('maybe_convert_table_to_utf8mb4')) {
30
- $r = maybe_convert_table_to_utf8mb4(NEWSLETTER_EMAILS_TABLE);
31
- if (!$r) {
32
- $controls->errors .= 'It was not possible to run the conversion for the table ' . NEWSLETTER_EMAILS_TABLE . ' - ';
33
- $controls->errors .= $wpdb->last_error . '<br>';
34
- }
35
- $r = maybe_convert_table_to_utf8mb4(NEWSLETTER_USERS_TABLE);
36
- if (!$r) {
37
- $controls->errors .= 'It was not possible to run the conversion for the table ' . NEWSLETTER_EMAILS_TABLE . ' - ';
38
- $controls->errors .= $wpdb->last_error . '<br>';
39
- }
40
- $controls->messages .= 'Done.';
41
- } else {
42
- $controls->errors = 'Table conversion function not available';
43
- }
44
- }
45
-
46
- if ($controls->is_action('reset_send_stats')) {
47
- $this->reset_send_stats();
48
- $controls->add_message_done();
49
- }
50
-
51
- if ($controls->is_action('stats_email_column_upgrade')) {
52
- $this->query("alter table " . NEWSLETTER_STATS_TABLE . " drop index email_id");
53
- $this->query("alter table " . NEWSLETTER_STATS_TABLE . " drop index user_id");
54
- $this->query("alter table `" . NEWSLETTER_STATS_TABLE . "` modify column `email_id` int(11) not null default 0");
55
- $this->query("create index email_id on " . NEWSLETTER_STATS_TABLE . " (email_id)");
56
- $this->query("create index user_id on " . NEWSLETTER_STATS_TABLE . " (user_id)");
57
- $controls->add_message_done();
58
- update_option('newsletter_stats_email_column_upgraded', true);
59
- }
60
-
61
- // Compute the number of newsletters ongoing and other stats
62
- $emails = $wpdb->get_results("select * from " . NEWSLETTER_EMAILS_TABLE . " where status='sending' and send_on<" . time() . " order by id asc");
63
- $total = 0;
64
- $queued = 0;
65
- foreach ($emails as $email) {
66
- $total += $email->total;
67
- $queued += $email->total - $email->sent;
68
- }
69
- $speed = $newsletter->get_send_speed();
70
-
71
- // Trick to access the private function (!)
72
- class TNP_WPDB extends wpdb {
73
-
74
- public function get_table_charset($table) {
75
- return parent::get_table_charset($table);
76
- }
77
-
78
- }
79
-
80
- $tnp_wpdb = new TNP_WPDB(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
81
- ?>
82
-
83
- <style>
84
- <?php include __DIR__ . '/css/system.css' ?>
85
- </style>
86
-
87
- <div class="wrap tnp-system tnp-system-status" id="tnp-wrap">
88
-
89
- <?php include NEWSLETTER_DIR . '/tnp-header.php'; ?>
90
-
91
- <div id="tnp-heading">
92
-
93
- <h2><?php _e('System Status', 'newsletter') ?></h2>
94
-
95
- </div>
96
-
97
- <div id="tnp-body">
98
-
99
- <form method="post" action="">
100
- <?php $controls->init(); ?>
101
-
102
-
103
- <h3>Delivery</h3>
104
- <table class="widefat" id="tnp-status-table">
105
-
106
- <thead>
107
- <tr>
108
- <th>Parameter</th>
109
- <th><?php _e('Status', 'newsletter') ?></th>
110
- <th>Action</th>
111
- </tr>
112
-
113
- </thead>
114
-
115
- <tbody>
116
-
117
- <tr>
118
- <td>Delivering</td>
119
- <td class="status">
120
- &nbsp;
121
- </td>
122
- <td>
123
- <?php if (count($emails)) { ?>
124
- Delivering <?php echo count($emails) ?> newsletters to about <?php echo $queued ?> recipients.
125
- At speed of <?php echo $speed ?> emails per hour it will take <?php printf('%.1f', $queued / $speed) ?> hours to finish.
126
-
127
- <?php } else { ?>
128
- Nothing delivering right now
129
- <?php } ?>
130
- </td>
131
-
132
- </tr>
133
- <tr>
134
- <td>Mailer</td>
135
- <td>
136
- &nbsp;
137
- </td>
138
- <td>
139
- <?php echo esc_html($mailer->get_description()) ?>
140
- </td>
141
- </tr>
142
- <?php
143
- $stats = $this->get_send_stats();
144
-
145
- if ($stats) {
146
- $condition = $stats->mean > 5 ? 2 : 1;
147
- ?>
148
- <tr>
149
- <td id="tnp-speed">
150
- Send details
151
- </td>
152
- <td class="status">
153
- <?php $this->condition_flag($condition) ?>
154
-
155
- </td>
156
- <td>
157
- <?php if ($condition == 2) { ?>
158
- <strong>Sending an email is taking more than 5 seconds (by mean), rather slow.</strong>
159
- <a href="https://www.thenewsletterplugin.com/documentation/installation/status-panel/#email-speed" target="_blank">Read more</a>.
160
- <br>
161
- <?php } ?>
162
- Average time to send an email: <?php echo $stats->mean ?> seconds<br>
163
- <?php if ($stats->mean > 0) { ?>
164
- Max speed: <?php echo sprintf("%.2f", 1.0 / $stats->mean * 3600) ?> emails per hour<br>
165
- <?php } ?>
166
-
167
- Max mean time measured: <?php echo $stats->max ?> seconds<br>
168
- Min mean time measured: <?php echo $stats->min ?> seconds<br>
169
- Total emails in the sample: <?php echo $stats->total_emails ?><br>
170
- Total sending time: <?php echo $stats->total_time ?> seconds<br>
171
- Runs in the sample: <?php echo $stats->total_runs ?><br>
172
- Runs prematurely interrupted: <?php echo $stats->interrupted ?><br>
173
-
174
-
175
- <canvas id="tnp-send-chart" style="width: 550px; height: 150px"></canvas>
176
- <script>
177
- jQuery(function () {
178
- var sendChartData = {
179
- labels: <?php echo json_encode(range(1, count($stats->means))) ?>,
180
- datasets: [
181
- {
182
- label: "Batch Average Time",
183
- data: <?php echo json_encode($stats->means) ?>,
184
- borderColor: '#2980b9',
185
- fill: false
186
- }/*,
187
- {
188
- label: "Batch Average Time",
189
- data: <?php echo json_encode($stats->sizes) ?>,
190
- borderColor: '#b98028',
191
- fill: false
192
- }*/]
193
- };
194
- var sendChartConfig = {
195
- type: "line",
196
- data: sendChartData,
197
- options: {
198
- responsive: false,
199
- maintainAspectRatio: false
200
- }
201
- };
202
- new Chart('tnp-send-chart', sendChartConfig);
203
- });
204
- </script>
205
- <br>
206
- <?php $controls->button_reset('reset_send_stats') ?>
207
- </td>
208
- </tr>
209
- <?php } else { ?>
210
- <tr>
211
- <td>
212
- Sending statistics
213
- </td>
214
- <td>
215
- &nbsp;
216
- </td>
217
- <td>
218
- Not enough data available.
219
- </td>
220
- </tr>
221
- <?php } ?>
222
- </tbody>
223
- </table>
224
-
225
- <h3>General checks</h3>
226
- <table class="widefat" id="tnp-status-table">
227
-
228
- <thead>
229
- <tr>
230
- <th>Parameter</th>
231
- <th><?php _e('Status', 'newsletter') ?></th>
232
- <th>Action</th>
233
- </tr>
234
-
235
- </thead>
236
-
237
- <tbody>
238
-
239
- <tr>
240
- <?php
241
- $page_id = $newsletter->get_newsletter_page_id();
242
- $page = $newsletter->get_newsletter_page();
243
- $condition = 1;
244
- if ($page_id) {
245
- if (!$page || $page->post_status !== 'publish') {
246
- $condition = 0;
247
- }
248
- } else {
249
- $condition = 2;
250
- }
251
- ?>
252
- <td>
253
- Dedicated page<br>
254
- <small>The blog page Newsletter uses for messages</small>
255
- </td>
256
- <td>
257
- <?php $this->condition_flag($condition) ?>
258
- </td>
259
- <td>
260
- <?php if ($condition == 2) { ?>
261
- Newsletter is using a neutral page to show messages, if you want to use a dedicated page, configure it on
262
- <a href="?page=newsletter_main_main">main settings</a>.
263
- <?php } else if ($condition == 0) { ?>
264
- A dedicated page is set but it is no more available or no more published. Review the dedicated page on
265
- <a href="?page=newsletter_main_main">main settings</a>.
266
- <?php } ?>
267
- </td>
268
- </tr>
269
-
270
- <tr>
271
- <?php
272
- $page_id = $newsletter->get_newsletter_page_id();
273
- $page = $newsletter->get_newsletter_page();
274
- $condition = 1;
275
- if ($page_id) {
276
- if (!$page) {
277
- $condition = 0;
278
- } else {
279
- $content = $page->post_content;
280
- if (strpos($content, '[newsletter]') === false && strpos($content, '[newsletter ') === false) {
281
- $condition = 2;
282
- }
283
- }
284
- }
285
- ?>
286
- <td>
287
- Dedicated page content<br>
288
- </td>
289
- <td>
290
- <?php $this->condition_flag($condition) ?>
291
- </td>
292
- <td>
293
- <?php if ($condition == 2) { ?>
294
- The page seems to not contain the <code>[newsletter]</code>, but sometime it cannot be detected if you use
295
- a visual composer. <a href="post.php?post=<?php echo $page->ID ?>&action=edit" target="_blank">Please, check the page</a>.
296
- <?php } else if ($condition == 0) { ?>
297
- The dedicated page seems to not be available.
298
- <?php } ?>
299
- </td>
300
- </tr>
301
-
302
- <?php
303
- $method = '';
304
- if (function_exists('get_filesystem_method')) {
305
- $method = get_filesystem_method(array(), WP_PLUGIN_DIR);
306
- }
307
- if (empty($method))
308
- $condition = 2;
309
- else if ($method == 'direct')
310
- $condition = 1;
311
- else
312
- $condition = 0;
313
- ?>
314
- <tr>
315
- <td>Add-ons installable</td>
316
- <td>
317
- <?php $this->condition_flag($condition) ?>
318
- </td>
319
- <td>
320
- <?php if ($condition == 2) { ?>
321
- No able to check, just try the add-ons manager one click install
322
- <?php } else if ($condition == 1) { ?>
323
- The add-ons manager can install our add-ons
324
- <?php } else { ?>
325
- The plugins dir could be read-only, you can install add-ons uploading the package from the
326
- plugins panel (or uploading them directly via FTP). This is unusual you should ask te provider
327
- about file and folder permissions.
328
- <?php } ?>
329
- </td>
330
-
331
- </tr>
332
-
333
-
334
- <?php
335
- $return_path = $newsletter->options['return_path'];
336
- if (!empty($return_path)) {
337
- list($return_path_local, $return_path_domain) = explode('@', $return_path);
338
- }
339
- $sender = $newsletter->options['sender_email'];
340
- if (!empty($sender)) {
341
- list($sender_local, $sender_domain) = explode('@', $sender);
342
- }
343
- ?>
344
- <tr>
345
- <td>Return path</td>
346
- <td>
347
- <?php if (empty($return_path)) { ?>
348
- <span class="tnp-ok">OK</span>
349
- <?php } else { ?>
350
- <?php if ($sender_domain != $return_path_domain) { ?>
351
- <span class="tnp-maybe">MAYBE</span>
352
- <?php } else { ?>
353
- <span class="tnp-ok">OK</span>
354
- <?php } ?>
355
- <?php } ?>
356
-
357
- </td>
358
- <td>
359
- <?php if (!empty($return_path)) { ?>
360
- Some providers require the return path domain <code><?php echo esc_html($return_path_domain) ?></code> to be identical
361
- to the sender domain <code><?php echo esc_html($sender_domain) ?></code>. See the main settings.
362
- <?php } else { ?>
363
- <?php } ?>
364
- </td>
365
-
366
- </tr>
367
-
368
-
369
-
370
-
371
-
372
- <tr>
373
- <?php
374
- $condition = NEWSLETTER_EXTENSION_UPDATE ? 1 : 0;
375
- ?>
376
- <td>Addons update</td>
377
- <td>
378
- <?php $this->condition_flag($condition) ?>
379
- </td>
380
- <td>
381
- <?php if ($condition == 0) { ?>
382
- Newsletter Addons update is disabled (probably in your <code>wp-config.php</code> file the constant
383
- <code>NEWSLETTER_EXTENSION_UPDATE</code> is set to <code>true</code>)
384
- <?php } else { ?>
385
- Newsletter Addons can be updated
386
- <?php } ?>
387
- </td>
388
-
389
- </tr>
390
-
391
- <tr>
392
- <?php
393
- $res = true;
394
- $response = wp_remote_get('http://www.thenewsletterplugin.com/wp-content/extensions.json');
395
- $condition = 1;
396
- if (is_wp_error($response)) {
397
- $res = false;
398
- $condition = 0;
399
- $message = $response->get_error_message();
400
- } else {
401
- if (wp_remote_retrieve_response_code($response) != 200) {
402
- $res = false;
403
- $condition = 0;
404
- $message = wp_remote_retrieve_response_message($response);
405
- }
406
- }
407
- ?>
408
-
409
- <td>
410
- Addons version check<br>
411
- <small>Your blog can check the professional addon updates?</small>
412
- </td>
413
- <td>
414
- <?php $this->condition_flag($condition) ?>
415
- </td>
416
- <td>
417
- <?php if ($condition == 0) { ?>
418
- The blog cannot contact www.thenewsletterplugin.com to check the license or the extension versions.<br>
419
- Error: <?php echo esc_html($message) ?><br>
420
- <?php } else { ?>
421
-
422
- <?php } ?>
423
- </td>
424
- </tr>
425
-
426
-
427
-
428
-
429
-
430
-
431
-
432
-
433
-
434
- <?php /*
435
- $memory = intval(WP_MEMORY_LIMIT);
436
- if (false !== strpos(WP_MEMORY_LIMIT, 'G'))
437
- $memory *= 1024;
438
- ?>
439
- <tr>
440
- <td>
441
- PHP memory limit
442
- </td>
443
- <td>
444
- <?php if ($memory < 64) { ?>
445
- <span class="tnp-ko">MAYBE</span>
446
- <?php } else if ($memory < 128) { ?>
447
- <span class="tnp-maybe">MAYBE</span>
448
- <?php } else { ?>
449
- <span class="tnp-ok">OK</span>
450
- <?php } ?>
451
- </td>
452
- <td>
453
- WordPress WP_MEMORY_LIMIT is set to <?php echo $memory ?> megabyte but your PHP setting could allow more than that.
454
- Anyway we suggest to set the value to at least 64M.
455
- <a href="https://www.thenewsletterplugin.com/documentation/status-panel#status-memory" target="_blank">Read more</a>.
456
- <?php if ($memory < 64) { ?>
457
- This value is too low you should increase it adding <code>define('WP_MEMORY_LIMIT', '64M');</code> to your <code>wp-config.php</code>.
458
- <a href="https://www.thenewsletterplugin.com/documentation/status-panel#status-memory" target="_blank">Read more</a>.
459
- <?php } else if ($memory < 128) { ?>
460
- The value should be fine, it depends on how many plugins you're running and how many resource are required by your theme.
461
- Blank pages may happen with low memory problems. Eventually increase it adding <code>define('WP_MEMORY_LIMIT', '128M');</code>
462
- to your <code>wp-config.php</code>.
463
- <a href="https://www.thenewsletterplugin.com/documentation/status-panel#status-memory" target="_blank">Read more</a>.
464
- <?php } else { ?>
465
-
466
- <?php } ?>
467
-
468
- </td>
469
- </tr>
470
- */ ?>
471
-
472
- <?php
473
- $ip = gethostbyname($_SERVER['HTTP_HOST']);
474
- $name = gethostbyaddr($ip);
475
- $res = true;
476
- if (strpos($name, '.secureserver.net') !== false) {
477
- //$smtp = get_option('newsletter_main_smtp');
478
- //if (!empty($smtp['enabled']))
479
- $res = false;
480
- $message = 'If you\'re hosted with GoDaddy, be sure to set their SMTP (relay-hosting.secureserver.net, without username and password) to send emails
481
- on Newsletter SMTP panel.
482
- Remember they limits you to 250 emails per day. Open them a ticket for more details.';
483
- }
484
- if (strpos($name, '.aruba.it') !== false) {
485
- $res = false;
486
- $message = 'If you\'re hosted with Aruba consider to use an external SMTP (Sendgrid, Mailjet, Mailgun, Amazon SES, Elasticemail, Sparkpost, ...)
487
- since their mail service is not good. If you have your personal email with them, you can try to use the SMTP of your
488
- pesonal account. Ask the support for the SMTP parameters and configure them on Newsletter SMTP panel.';
489
- }
490
- ?>
491
- <tr>
492
- <td>Your Server</td>
493
- <td>
494
- <?php if ($res === false) { ?>
495
- <span class="tnp-maybe">MAYBE</span>
496
- <?php } else { ?>
497
- <span class="tnp-ok">OK</span>
498
- <?php } ?>
499
-
500
-
501
- </td>
502
- <td>
503
- <?php if ($res === false) { ?>
504
- <?php echo $message ?>
505
- <?php } else { ?>
506
-
507
- <?php } ?>
508
- IP: <?php echo $ip ?><br>
509
- Name: <?php echo $name ?><br>
510
- </td>
511
- </tr>
512
-
513
- <?php
514
- wp_mkdir_p(NEWSLETTER_LOG_DIR);
515
- $condition = is_dir(NEWSLETTER_LOG_DIR) && is_writable(NEWSLETTER_LOG_DIR) ? 1 : 0;
516
- if ($condition) {
517
- @file_put_contents(NEWSLETTER_LOG_DIR . '/test.txt', "");
518
- $condition = is_file(NEWSLETTER_LOG_DIR . '/test.txt') ? 1 : 0;
519
- if ($condition) {
520
- @unlink(NEWSLETTER_LOG_DIR . '/test.txt');
521
- }
522
- }
523
- ?>
524
- <tr>
525
- <td>
526
- Log folder
527
- </td>
528
- <td>
529
- <?php $this->condition_flag($condition) ?>
530
- </td>
531
- <td>
532
- The log folder is <?php echo esc_html(NEWSLETTER_LOG_DIR) ?><br>
533
- <?php if (!$res) { ?>
534
- Cannot create the folder or it is not writable.
535
- <?php } ?>
536
- </td>
537
- </tr>
538
- </tbody>
539
- </table>
540
-
541
-
542
- <h3>WordPress</h3>
543
-
544
- <table class="widefat" id="tnp-status-table">
545
- <thead>
546
- <tr>
547
- <th>Parameter</th>
548
- <th><?php _e('Status', 'newsletter') ?></th>
549
- <th>Action</th>
550
- </tr>
551
- </thead>
552
- <tbody>
553
-
554
- <tr>
555
- <?php
556
- $condition = (defined('WP_DEBUG') && WP_DEBUG) ? 2 : 1;
557
- ?>
558
- <td>
559
- WordPress debug mode
560
- </td>
561
- <td>
562
- <?php $this->condition_flag($condition) ?>
563
- </td>
564
- <td>
565
- <?php if (defined('WP_DEBUG') && WP_DEBUG) { ?>
566
- WordPress is in debug mode it is not recommended on a production system. See the constant <code>WP_DEBUG</code> inside the <code>wp-config.php</code>.
567
- <?php } else { ?>
568
-
569
- <?php } ?>
570
- </td>
571
- </tr>
572
-
573
-
574
-
575
- <tr>
576
- <?php
577
- $charset = get_option('blog_charset');
578
- $condition = $charset === 'UTF-8' ? 1 : 0;
579
- ?>
580
- <td>Blog Charset</td>
581
- <td>
582
- <?php $this->condition_flag($condition) ?>
583
- </td>
584
- <td>
585
- Charset: <?php echo esc_html($charset) ?>
586
- <br>
587
-
588
- <?php if ($condition == 1) { ?>
589
-
590
- <?php } else { ?>
591
- It is recommended to use
592
- the <code>UTF-8</code> charset but the <a href="https://codex.wordpress.org/Converting_Database_Character_Sets" target="_blank">conversion</a>
593
- could be tricky. If you're not experiencing problem, leave things as is.
594
- <?php } ?>
595
- </td>
596
- </tr>
597
-
598
- <tr>
599
- <?php
600
- $condition = (strpos(home_url('/'), 'http') !== 0) ? 0 : 1;
601
- ?>
602
- <td>Home URL</td>
603
- <td>
604
- <?php $this->condition_flag($condition) ?>
605
- </td>
606
- <td>
607
- Value: <?php echo home_url('/'); ?>
608
- <br>
609
- <?php if ($condition == 0) { ?>
610
- Your home URL is not absolute, emails require absolute URLs.
611
- Probably you have a protocol agnostic plugin installed to manage both HTTPS and HTTP in your
612
- blog.
613
- <?php } else { ?>
614
-
615
- <?php } ?>
616
- </td>
617
- </tr>
618
-
619
- <tr>
620
- <?php
621
- $condition = (strpos(WP_CONTENT_URL, 'http') !== 0) ? 0 : 1;
622
- ?>
623
- <td>WP_CONTENT_URL</td>
624
- <td>
625
- <?php $this->condition_flag($condition) ?>
626
- </td>
627
- <td>
628
- Value: <?php echo esc_html(WP_CONTENT_URL); ?>
629
- <br>
630
- <?php if ($condition == 0) { ?>
631
- Your content URL is not absolute, emails require absolute URLs when they have images inside.
632
- Newsletter tries to deal with this problem but when a problem with images persists, you should try to remove
633
- from your <code>wp-config.php</code> the <code>WP_CONTENT_URL</code> define and check again.
634
- <?php } else { ?>
635
-
636
- <?php } ?>
637
- </td>
638
- </tr>
639
-
640
- <tr>
641
- <?php
642
- set_transient('newsletter_transient_test', 1, 300);
643
- delete_transient('newsletter_transient_test');
644
- $res = get_transient('newsletter_transient_test');
645
- $condition = ($res !== false) ? 0 : 1;
646
- ?>
647
- <td>WordPress transients</td>
648
- <td>
649
- <?php $this->condition_flag($condition) ?>
650
- </td>
651
- <td>
652
- <?php if ($res !== false) { ?>
653
- Transients cannot be delete. This can block the delivery engine. Usually it is due to a not well coded plugin installed.
654
- <?php } else { ?>
655
- <?php } ?>
656
- </td>
657
- </tr>
658
- </tbody>
659
- </table>
660
-
661
-
662
-
663
- <h3>PHP</h3>
664
- <table class="widefat" id="tnp-status-table">
665
- <thead>
666
- <tr>
667
- <th>Parameter</th>
668
- <th><?php _e('Status', 'newsletter') ?></th>
669
- <th>Action</th>
670
- </tr>
671
- </thead>
672
- <tbody>
673
- <tr>
674
- <td>PHP version</td>
675
- <td>
676
- <?php if (version_compare(phpversion(), '5.6', '<')) { ?>
677
- <span class="tnp-ko">KO</span>
678
- <?php } else { ?>
679
- <span class="tnp-ok">OK</span>
680
- <?php } ?>
681
-
682
- </td>
683
- <td>
684
- Your PHP version is <?php echo phpversion() ?><br>
685
- <?php if (version_compare(phpversion(), '5.3', '<')) { ?>
686
- Newsletter plugin works correctly with PHP version 5.6 or greater. Ask your provider to upgrade your PHP. Your version is
687
- unsupported even by the PHP community.
688
- <?php } ?>
689
- </td>
690
-
691
- </tr>
692
-
693
- <tr>
694
- <?php
695
- $value = (int) ini_get('max_execution_time');
696
- $res = true;
697
- $condition = 1;
698
- if ($value != 0 && $value < NEWSLETTER_CRON_INTERVAL) {
699
- $res = set_time_limit(NEWSLETTER_CRON_INTERVAL);
700
- if ($res)
701
- $condition = 1;
702
- else
703
- $condition = 0;
704
- }
705
- ?>
706
- <td>PHP execution time limit</td>
707
- <td>
708
- <?php $this->condition_flag($condition) ?>
709
- </td>
710
- <td>
711
- <?php if (!$res) { ?>
712
- Your PHP execution time limit is <?php echo $value ?> seconds. It cannot be changed and it is too lower to grant the maximum delivery rate of Newsletter.
713
- <?php } else { ?>
714
- Your PHP execution time limit is <?php echo $value ?> seconds and can be eventually changed by Newsletter.<br>
715
- <?php } ?>
716
-
717
- </td>
718
-
719
- </tr>
720
-
721
-
722
- <tr>
723
- <?php
724
- $condition = function_exists('curl_version');
725
- ?>
726
- <td>Curl version</td>
727
- <td>
728
- <?php if (!$condition) { ?>
729
- <span class="tnp-ko">KO</span>
730
- <?php } else { ?>
731
- <span class="tnp-ok">OK</span>
732
- <?php } ?>
733
-
734
- </td>
735
- <td>
736
- <?php
737
- if (!$condition) {
738
- echo 'cUrl is not available, ask the provider to install it and activate the PHP cUrl library';
739
- } else {
740
- $version = curl_version();
741
- echo 'Version: ' . $version['version'] . '<br>';
742
- echo 'SSL Version: ' . $version['ssl_version'] . '<br>';
743
- }
744
- ?>
745
- </td>
746
-
747
- </tr>
748
- <?php if (ini_get('opcache.validate_timestamps') === '0') { ?>
749
- <tr>
750
- <td>
751
- Opcache
752
- </td>
753
-
754
- <td>
755
- <span class="tnp-ko">KO</span>
756
- </td>
757
-
758
- <td>
759
- You have the PHP opcache active with file validation disable so every blog plugins update needs a webserver restart!
760
- </td>
761
- </tr>
762
- <?php } ?>
763
- </tbody>
764
- </table>
765
-
766
- <h3>Database</h3>
767
- <table class="widefat" id="tnp-status-table">
768
- <thead>
769
- <tr>
770
- <th>Parameter</th>
771
- <th><?php _e('Status', 'newsletter') ?></th>
772
- <th>Action</th>
773
- </tr>
774
- </thead>
775
- <tbody>
776
- <tr>
777
- <td>Database Charset</td>
778
- <td>
779
- <?php if ($wpdb->charset != 'utf8mb4') { ?>
780
- <span class="tnp-ko">KO</span>
781
- <?php } else { ?>
782
- <span class="tnp-ok">OK</span>
783
- <?php } ?>
784
-
785
- </td>
786
- <td>
787
- Charset: <?php echo $wpdb->charset; ?>
788
- <br>
789
- <?php if ($wpdb->charset != 'utf8mb4') { ?>
790
- The recommended charset for your database is <code>utf8mb4</code> to avoid possible saving errors when you use emoji.
791
- Read the WordPress Codex <a href="https://codex.wordpress.org/Converting_Database_Character_Sets" target="_blank">conversion
792
- instructions</a> (skilled technicia required).
793
- <?php } else { ?>
794
- If you experience newsletter saving database error
795
- <?php $controls->button('conversion', 'Try tables upgrade') ?>
796
- <?php } ?>
797
- </td>
798
- </tr>
799
-
800
- <tr>
801
- <td>get_table_charset()</td>
802
- <td>
803
-
804
- </td>
805
- <td>
806
- <?php echo esc_html(NEWSLETTER_USERS_TABLE), ': ', esc_html($tnp_wpdb->get_table_charset(NEWSLETTER_USERS_TABLE)) ?>
807
- </td>
808
- </tr>
809
-
810
-
811
-
812
-
813
- <?php
814
- $wait_timeout = $wpdb->get_var("select @@wait_timeout");
815
- $condition = ($wait_timeout < 30) ? 0 : 1;
816
- ?>
817
- <tr>
818
- <td>Database wait timeout</td>
819
- <td>
820
- <?php $this->condition_flag($condition) ?>
821
- </td>
822
- <td>
823
- Your database wait timeout is <?php echo $wait_timeout; ?> seconds<br>
824
- <?php if ($wait_timeout < 30) { ?>
825
- That value is low and could produce database connection errors while sending emails or during long import
826
- sessions. Ask the provider to raise it at least to 60 seconds.
827
- <?php } ?>
828
- </td>
829
- </tr>
830
-
831
- <?php
832
- $res = $wpdb->query("drop table if exists {$wpdb->prefix}newsletter_test");
833
- $res = $wpdb->query("create table if not exists {$wpdb->prefix}newsletter_test (id int(20))");
834
- $condition = $res === false ? 0 : 1;
835
- ?>
836
- <tr>
837
- <td>Database table creation</td>
838
- <td>
839
- <?php $this->condition_flag($condition) ?>
840
- </td>
841
- <td>
842
- <?php if ($res === false) { ?>
843
- Check the privileges of the user you use to connect to the database, it seems it cannot create tables.<br>
844
- (<?php echo esc_html($wpdb->last_error) ?>)
845
- <?php } else { ?>
846
- <?php } ?>
847
- </td>
848
- </tr>
849
-
850
- <?php
851
- $res = $wpdb->query("alter table {$wpdb->prefix}newsletter_test add column id1 int(20)");
852
- $condition = $res === false ? 0 : 1;
853
- ?>
854
- <tr>
855
- <td>Database table change</td>
856
- <td>
857
- <?php $this->condition_flag($condition) ?>
858
- </td>
859
- <td>
860
- <?php if ($res === false) { ?>
861
- Check the privileges of the user you use to connect to the database, it seems it cannot change the tables. It's require to update the
862
- plugin.<br>
863
- (<?php echo esc_html($wpdb->last_error) ?>)
864
- <?php } else { ?>
865
- <?php } ?>
866
- </td>
867
- </tr>
868
-
869
- <?php
870
- // Clean up
871
- $res = $wpdb->query("drop table if exists {$wpdb->prefix}newsletter_test");
872
- ?>
873
-
874
- <?php if (!get_option('newsletter_stats_email_column_upgraded', false)) { ?>
875
- <?php
876
- $data_type = $wpdb->get_var(
877
- $wpdb->prepare('SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s',
878
- DB_NAME, NEWSLETTER_STATS_TABLE, 'email_id'));
879
- $to_upgrade = strtoupper($data_type) == 'INT' ? false : true;
880
- ?>
881
- <?php if ($to_upgrade) { ?>
882
- <tr>
883
- <td>Database stats table upgrade</td>
884
- <td><?php $this->condition_flag(0) ?></td>
885
- <td><?php $controls->button('stats_email_column_upgrade', 'Stats table upgrade') ?></td>
886
- </tr>
887
- <?php } ?>
888
- <?php } ?>
889
-
890
- </tbody>
891
- </table>
892
-
893
- <h3>3rd party plugins</h3>
894
- <table class="widefat" id="tnp-status-table">
895
- <thead>
896
- <tr>
897
- <th>Plugin</th>
898
- <th><?php _e('Status', 'newsletter') ?></th>
899
- <th>Action</th>
900
- </tr>
901
- </thead>
902
- <tbody>
903
- <?php if (is_plugin_active('plugin-load-filter/plugin-load-filter.php')) { ?>
904
- <tr>
905
- <td><a href="https://wordpress.org/plugins/plugin-load-filter/" target="_blank">Plugin load filter</a></td>
906
- <td>
907
- <span class="tnp-maybe">MAY BE</span>
908
- </td>
909
- <td>
910
- Be sure Newsletter is set as active in EVERY context.
911
- </td>
912
- </tr>
913
- <?php } ?>
914
- </tbody>
915
- </table>
916
-
917
- <h3>General parameters</h3>
918
- <table class="widefat" id="tnp-parameters-table">
919
- <thead>
920
- <tr>
921
- <th>Parameter</th>
922
- <th>Value</th>
923
- </tr>
924
- </thead>
925
- <tbody>
926
-
927
- <tr>
928
- <td>Newsletter version</td>
929
- <td>
930
- <?php echo NEWSLETTER_VERSION ?>
931
- </td>
932
- </tr>
933
-
934
- <tr>
935
- <td>NEWSLETTER_MAX_EXECUTION_TIME</td>
936
- <td>
937
- <?php
938
- if (defined('NEWSLETTER_MAX_EXECUTION_TIME')) {
939
- echo NEWSLETTER_MAX_EXECUTION_TIME . ' (seconds)';
940
- } else {
941
- echo 'Not set';
942
- }
943
- ?>
944
- </td>
945
- </tr>
946
-
947
-
948
-
949
-
950
- <?php /*
951
- <tr>
952
- <td>WordPress plugin url</td>
953
- <td>
954
- <?php echo WP_PLUGIN_URL; ?>
955
- <br>
956
- Filters:
957
-
958
- <?php
959
- if (isset($wp_filter))
960
- $filters = $wp_filter['plugins_url'];
961
- if (!isset($filters) || !is_array($filters))
962
- echo 'no filters attached to "plugin_urls"';
963
- else {
964
- echo '<ul>';
965
- foreach ($filters as &$filter) {
966
- foreach ($filter as &$entry) {
967
- echo '<li>';
968
- if (is_array($entry['function']))
969
- echo esc_html(get_class($entry['function'][0]) . '->' . $entry['function'][1]);
970
- else
971
- echo esc_html($entry['function']);
972
- echo '</li>';
973
- }
974
- }
975
- echo '</ul>';
976
- }
977
- ?>
978
- <p class="description">
979
- This value should contains the full URL to your plugin folder. If there are filters
980
- attached, the value can be different from the original generated by WordPress and sometime worng.
981
- </p>
982
- </td>
983
- </tr>
984
- */ ?>
985
-
986
- <tr>
987
- <td>Absolute path</td>
988
- <td>
989
- <?php echo esc_html(ABSPATH); ?>
990
- </td>
991
- </tr>
992
- <tr>
993
- <td>Tables Prefix</td>
994
- <td>
995
- <?php echo $wpdb->prefix; ?>
996
- </td>
997
- </tr>
998
- </tbody>
999
- </table>
1000
-
1001
-
1002
- <?php if (isset($_GET['debug'])) { ?>
1003
-
1004
- <h3>Database Tables</h3>
1005
- <h4><?php echo $wpdb->prefix ?>newsletter</h4>
1006
- <?php
1007
- $rs = $wpdb->get_results("describe {$wpdb->prefix}newsletter");
1008
- ?>
1009
- <table class="tnp-db-table">
1010
- <thead>
1011
- <tr>
1012
- <th>Field</th>
1013
- <th>Type</th>
1014
- <th>Null</th>
1015
- <th>Key</th>
1016
- <th>Default</th>
1017
- <th>Extra</th>
1018
- </tr>
1019
- </thead>
1020
- <tbody>
1021
- <?php foreach ($rs as $r) { ?>
1022
- <tr>
1023
- <td><?php echo esc_html($r->Field) ?></td>
1024
- <td><?php echo esc_html($r->Type) ?></td>
1025
- <td><?php echo esc_html($r->Null) ?></td>
1026
- <td><?php echo esc_html($r->Key) ?></td>
1027
- <td><?php echo esc_html($r->Default) ?></td>
1028
- <td><?php echo esc_html($r->Extra) ?></td>
1029
- </tr>
1030
- <?php } ?>
1031
- </tbody>
1032
- </table>
1033
-
1034
- <h4><?php echo $wpdb->prefix ?>newsletter_emails</h4>
1035
- <?php
1036
- $rs = $wpdb->get_results("show full columns from {$wpdb->prefix}newsletter_emails");
1037
- ?>
1038
- <table class="tnp-db-table">
1039
- <thead>
1040
- <tr>
1041
- <th>Field</th>
1042
- <th>Type</th>
1043
- <th>Collation</th>
1044
- <th>Null</th>
1045
- <th>Key</th>
1046
- <th>Default</th>
1047
- <th>Extra</th>
1048
- </tr>
1049
- </thead>
1050
- <tbody>
1051
- <?php foreach ($rs as $r) { ?>
1052
- <tr>
1053
- <td><?php echo esc_html($r->Field) ?></td>
1054
- <td><?php echo esc_html($r->Type) ?></td>
1055
- <td><?php echo esc_html($r->Collation) ?></td>
1056
- <td><?php echo esc_html($r->Null) ?></td>
1057
- <td><?php echo esc_html($r->Key) ?></td>
1058
- <td><?php echo esc_html($r->Default) ?></td>
1059
- <td><?php echo esc_html($r->Extra) ?></td>
1060
- </tr>
1061
- <?php } ?>
1062
- </tbody>
1063
- </table>
1064
-
1065
-
1066
- <h3>Extensions</h3>
1067
- <pre style="font-size: 11px; font-family: monospace; background-color: #efefef; color: #444"><?php echo esc_html(print_r(get_option('newsletter_extension_versions'), true)); ?></pre>
1068
-
1069
- <h3>Update plugins data</h3>
1070
- <pre style="font-size: 11px; font-family: monospace; background-color: #efefef; color: #444"><?php echo esc_html(print_r(get_site_transient('update_plugins'), true)); ?></pre>
1071
-
1072
- <?php } ?>
1073
- </div>
1074
-
1075
- <?php include NEWSLETTER_DIR . '/tnp-footer.php'; ?>
1076
-
1077
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* @var $this NewsletterSystem */
3
+ /* @var $wpdb wpdb */
4
+
5
+ defined('ABSPATH') || exit;
6
+
7
+ wp_enqueue_script('tnp-chart');
8
+
9
+ include_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
10
+ $controls = new NewsletterControls();
11
+
12
+ $newsletter = Newsletter::instance();
13
+ $mailer = $newsletter->get_mailer();
14
+
15
+ if ($controls->is_action('delete_logs')) {
16
+ $files = glob(WP_CONTENT_DIR . '/logs/newsletter/*.txt');
17
+ foreach ($files as $file) {
18
+ if (is_file($file))
19
+ unlink($file);
20
+ }
21
+ $secret = NewsletterModule::get_token(8);
22
+ update_option('newsletter_logger_secret', $secret);
23
+ $controls->messages = __('Logs deleted', 'newsletter');
24
+ }
25
+
26
+ if ($controls->is_action('conversion')) {
27
+ $this->logger->info('Maybe convert to utf8mb4');
28
+ require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
29
+ if (function_exists('maybe_convert_table_to_utf8mb4')) {
30
+ $r = maybe_convert_table_to_utf8mb4(NEWSLETTER_EMAILS_TABLE);
31
+ if (!$r) {
32
+ $controls->errors .= 'It was not possible to run the conversion for the table ' . NEWSLETTER_EMAILS_TABLE . ' - ';
33
+ $controls->errors .= $wpdb->last_error . '<br>';
34
+ }
35
+ $r = maybe_convert_table_to_utf8mb4(NEWSLETTER_USERS_TABLE);
36
+ if (!$r) {
37
+ $controls->errors .= 'It was not possible to run the conversion for the table ' . NEWSLETTER_EMAILS_TABLE . ' - ';
38
+ $controls->errors .= $wpdb->last_error . '<br>';
39
+ }
40
+ $controls->messages .= 'Done.';
41
+ } else {
42
+ $controls->errors = 'Table conversion function not available';
43
+ }
44
+ }
45
+
46
+ if ($controls->is_action('reset_send_stats')) {
47
+ $this->reset_send_stats();
48
+ $controls->add_message_done();
49
+ }
50
+
51
+ if ($controls->is_action('stats_email_column_upgrade')) {
52
+ $this->query("alter table " . NEWSLETTER_STATS_TABLE . " drop index email_id");
53
+ $this->query("alter table " . NEWSLETTER_STATS_TABLE . " drop index user_id");
54
+ $this->query("alter table `" . NEWSLETTER_STATS_TABLE . "` modify column `email_id` int(11) not null default 0");
55
+ $this->query("create index email_id on " . NEWSLETTER_STATS_TABLE . " (email_id)");
56
+ $this->query("create index user_id on " . NEWSLETTER_STATS_TABLE . " (user_id)");
57
+ $controls->add_message_done();
58
+ update_option('newsletter_stats_email_column_upgraded', true);
59
+ }
60
+
61
+ // Compute the number of newsletters ongoing and other stats
62
+ $emails = $wpdb->get_results("select * from " . NEWSLETTER_EMAILS_TABLE . " where status='sending' and send_on<" . time() . " order by id asc");
63
+ $total = 0;
64
+ $queued = 0;
65
+ foreach ($emails as $email) {
66
+ $total += $email->total;
67
+ $queued += $email->total - $email->sent;
68
+ }
69
+ $speed = $newsletter->get_send_speed();
70
+
71
+ // Trick to access the private function (!)
72
+ class TNP_WPDB extends wpdb {
73
+
74
+ public function get_table_charset($table) {
75
+ return parent::get_table_charset($table);
76
+ }
77
+
78
+ }
79
+
80
+ $tnp_wpdb = new TNP_WPDB(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
81
+ ?>
82
+
83
+ <style>
84
+ <?php include __DIR__ . '/css/system.css' ?>
85
+ </style>
86
+
87
+ <div class="wrap tnp-system tnp-system-status" id="tnp-wrap">
88
+
89
+ <?php include NEWSLETTER_DIR . '/tnp-header.php'; ?>
90
+
91
+ <div id="tnp-heading">
92
+
93
+ <h2><?php _e('System Status', 'newsletter') ?></h2>
94
+
95
+ </div>
96
+
97
+ <div id="tnp-body">
98
+
99
+ <form method="post" action="">
100
+ <?php $controls->init(); ?>
101
+
102
+
103
+ <h3>Delivery</h3>
104
+ <table class="widefat" id="tnp-status-table">
105
+
106
+ <thead>
107
+ <tr>
108
+ <th>Parameter</th>
109
+ <th><?php _e('Status', 'newsletter') ?></th>
110
+ <th>Action</th>
111
+ </tr>
112
+
113
+ </thead>
114
+
115
+ <tbody>
116
+
117
+ <tr>
118
+ <td>Delivering</td>
119
+ <td class="status">
120
+ &nbsp;
121
+ </td>
122
+ <td>
123
+ <?php if (count($emails)) { ?>
124
+ Delivering <?php echo count($emails) ?> newsletters to about <?php echo $queued ?> recipients.
125
+ At speed of <?php echo $speed ?> emails per hour it will take <?php printf('%.1f', $queued / $speed) ?> hours to finish.
126
+
127
+ <?php } else { ?>
128
+ Nothing delivering right now
129
+ <?php } ?>
130
+ </td>
131
+
132
+ </tr>
133
+ <tr>
134
+ <td>Mailer</td>
135
+ <td>
136
+ &nbsp;
137
+ </td>
138
+ <td>
139
+ <?php echo esc_html($mailer->get_description()) ?>
140
+ </td>
141
+ </tr>
142
+ <?php
143
+ $stats = $this->get_send_stats();
144
+
145
+ if ($stats) {
146
+ $condition = $stats->mean > 5 ? 2 : 1;
147
+ ?>
148
+ <tr>
149
+ <td id="tnp-speed">
150
+ Send details
151
+ </td>
152
+ <td class="status">
153
+ <?php $this->condition_flag($condition) ?>
154
+
155
+ </td>
156
+ <td>
157
+ <?php if ($condition == 2) { ?>
158
+ <strong>Sending an email is taking more than 5 seconds (by mean), rather slow.</strong>
159
+ <a href="https://www.thenewsletterplugin.com/documentation/installation/status-panel/#email-speed" target="_blank">Read more</a>.
160
+ <br>
161
+ <?php } ?>
162
+ Average time to send an email: <?php echo $stats->mean ?> seconds<br>
163
+ <?php if ($stats->mean > 0) { ?>
164
+ Max speed: <?php echo sprintf("%.2f", 1.0 / $stats->mean * 3600) ?> emails per hour<br>
165
+ <?php } ?>
166
+
167
+ Max mean time measured: <?php echo $stats->max ?> seconds<br>
168
+ Min mean time measured: <?php echo $stats->min ?> seconds<br>
169
+ Total emails in the sample: <?php echo $stats->total_emails ?><br>
170
+ Total sending time: <?php echo $stats->total_time ?> seconds<br>
171
+ Runs in the sample: <?php echo $stats->total_runs ?><br>
172
+ Runs prematurely interrupted: <?php echo $stats->interrupted ?><br>
173
+
174
+
175
+ <canvas id="tnp-send-chart" style="width: 550px; height: 150px"></canvas>
176
+ <script>
177
+ jQuery(function () {
178
+ var sendChartData = {
179
+ labels: <?php echo json_encode(range(1, count($stats->means))) ?>,
180
+ datasets: [
181
+ {
182
+ label: "Batch Average Time",
183
+ data: <?php echo json_encode($stats->means) ?>,
184
+ borderColor: '#2980b9',
185
+ fill: false
186
+ }/*,
187
+ {
188
+ label: "Batch Average Time",
189
+ data: <?php echo json_encode($stats->sizes) ?>,
190
+ borderColor: '#b98028',
191
+ fill: false
192
+ }*/]
193
+ };
194
+ var sendChartConfig = {
195
+ type: "line",
196
+ data: sendChartData,
197
+ options: {
198
+ responsive: false,
199
+ maintainAspectRatio: false
200
+ }
201
+ };
202
+ new Chart('tnp-send-chart', sendChartConfig);
203
+ });
204
+ </script>
205
+ <br>
206
+ <?php $controls->button_reset('reset_send_stats') ?>
207
+ </td>
208
+ </tr>
209
+ <?php } else { ?>
210
+ <tr>
211
+ <td>
212
+ Sending statistics
213
+ </td>
214
+ <td>
215
+ &nbsp;
216
+ </td>
217
+ <td>
218
+ Not enough data available.
219
+ </td>
220
+ </tr>
221
+ <?php } ?>
222
+ </tbody>
223
+ </table>
224
+
225
+ <h3>General checks</h3>
226
+ <table class="widefat" id="tnp-status-table">
227
+
228
+ <thead>
229
+ <tr>
230
+ <th>Parameter</th>
231
+ <th><?php _e('Status', 'newsletter') ?></th>
232
+ <th>Action</th>
233
+ </tr>
234
+
235
+ </thead>
236
+
237
+ <tbody>
238
+
239
+ <tr>
240
+ <?php
241
+ $page_id = $newsletter->get_newsletter_page_id();
242
+ $page = $newsletter->get_newsletter_page();
243
+ $condition = 1;
244
+ if ($page_id) {
245
+ if (!$page || $page->post_status !== 'publish') {
246
+ $condition = 0;
247
+ }
248
+ } else {
249
+ $condition = 2;
250
+ }
251
+ ?>
252
+ <td>
253
+ Dedicated page<br>
254
+ <small>The blog page Newsletter uses for messages</small>
255
+ </td>
256
+ <td>
257
+ <?php $this->condition_flag($condition) ?>
258
+ </td>
259
+ <td>
260
+ <?php if ($condition == 2) { ?>
261
+ Newsletter is using a neutral page to show messages, if you want to use a dedicated page, configure it on
262
+ <a href="?page=newsletter_main_main">main settings</a>.
263
+ <?php } else if ($condition == 0) { ?>
264
+ A dedicated page is set but it is no more available or no more published. Review the dedicated page on
265
+ <a href="?page=newsletter_main_main">main settings</a>.
266
+ <?php } ?>
267
+ </td>
268
+ </tr>
269
+
270
+ <tr>
271
+ <?php
272
+ $page_id = $newsletter->get_newsletter_page_id();
273
+ $page = $newsletter->get_newsletter_page();
274
+ $condition = 1;
275
+ if ($page_id) {
276
+ if (!$page) {
277
+ $condition = 0;
278
+ } else {
279
+ $content = $page->post_content;
280
+ if (strpos($content, '[newsletter]') === false && strpos($content, '[newsletter ') === false) {
281
+ $condition = 2;
282
+ }
283
+ }
284
+ }
285
+ ?>
286
+ <td>
287
+ Dedicated page content<br>
288
+ </td>
289
+ <td>
290
+ <?php $this->condition_flag($condition) ?>
291
+ </td>
292
+ <td>
293
+ <?php if ($condition == 2) { ?>
294
+ The page seems to not contain the <code>[newsletter]</code>, but sometime it cannot be detected if you use
295
+ a visual composer. <a href="post.php?post=<?php echo $page->ID ?>&action=edit" target="_blank">Please, check the page</a>.
296
+ <?php } else if ($condition == 0) { ?>
297
+ The dedicated page seems to not be available.
298
+ <?php } ?>
299
+ </td>
300
+ </tr>
301
+
302
+ <?php
303
+ $method = '';
304
+ if (function_exists('get_filesystem_method')) {
305
+ $method = get_filesystem_method(array(), WP_PLUGIN_DIR);
306
+ }
307
+ if (empty($method))
308
+ $condition = 2;
309
+ else if ($method == 'direct')
310
+ $condition = 1;
311
+ else
312
+ $condition = 0;
313
+ ?>
314
+ <tr>
315
+ <td>Add-ons installable</td>
316
+ <td>
317
+ <?php $this->condition_flag($condition) ?>
318
+ </td>
319
+ <td>
320
+ <?php if ($condition == 2) { ?>
321
+ No able to check, just try the add-ons manager one click install
322
+ <?php } else if ($condition == 1) { ?>
323
+ The add-ons manager can install our add-ons
324
+ <?php } else { ?>
325
+ The plugins dir could be read-only, you can install add-ons uploading the package from the
326
+ plugins panel (or uploading them directly via FTP). This is unusual you should ask te provider
327
+ about file and folder permissions.
328
+ <?php } ?>
329
+ </td>
330
+
331
+ </tr>
332
+
333
+
334
+ <?php
335
+ $return_path = $newsletter->options['return_path'];
336
+ if (!empty($return_path)) {
337
+ list($return_path_local, $return_path_domain) = explode('@', $return_path);
338
+ }
339
+ $sender = $newsletter->options['sender_email'];
340
+ if (!empty($sender)) {
341
+ list($sender_local, $sender_domain) = explode('@', $sender);
342
+ }
343
+ ?>
344
+ <tr>
345
+ <td>Return path</td>
346
+ <td>
347
+ <?php if (empty($return_path)) { ?>
348
+ <span class="tnp-ok">OK</span>
349
+ <?php } else { ?>
350
+ <?php if ($sender_domain != $return_path_domain) { ?>
351
+ <span class="tnp-maybe">MAYBE</span>
352
+ <?php } else { ?>
353
+ <span class="tnp-ok">OK</span>
354
+ <?php } ?>
355
+ <?php } ?>
356
+
357
+ </td>
358
+ <td>
359
+ <?php if (!empty($return_path)) { ?>
360
+ Some providers require the return path domain <code><?php echo esc_html($return_path_domain) ?></code> to be identical
361
+ to the sender domain <code><?php echo esc_html($sender_domain) ?></code>. See the main settings.
362
+ <?php } else { ?>
363
+ <?php } ?>
364
+ </td>
365
+
366
+ </tr>
367
+
368
+
369
+
370
+
371
+
372
+ <tr>
373
+ <?php
374
+ $condition = NEWSLETTER_EXTENSION_UPDATE ? 1 : 0;
375
+ ?>
376
+ <td>Addons update</td>
377
+ <td>
378
+ <?php $this->condition_flag($condition) ?>
379
+ </td>
380
+ <td>
381
+ <?php if ($condition == 0) { ?>
382
+ Newsletter Addons update is disabled (probably in your <code>wp-config.php</code> file the constant
383
+ <code>NEWSLETTER_EXTENSION_UPDATE</code> is set to <code>true</code>)
384
+ <?php } else { ?>
385
+ Newsletter Addons can be updated
386
+ <?php } ?>
387
+ </td>
388
+
389
+ </tr>
390
+
391
+ <tr>
392
+ <?php
393
+ $res = true;
394
+ $response = wp_remote_get('http://www.thenewsletterplugin.com/wp-content/extensions.json');
395
+ $condition = 1;
396
+ if (is_wp_error($response)) {
397
+ $res = false;
398
+ $condition = 0;
399
+ $message = $response->get_error_message();
400
+ } else {
401
+ if (wp_remote_retrieve_response_code($response) != 200) {
402
+ $res = false;
403
+ $condition = 0;
404
+ $message = wp_remote_retrieve_response_message($response);
405
+ }
406
+ }
407
+ ?>
408
+
409
+ <td>
410
+ Addons version check<br>
411
+ <small>Your blog can check the professional addon updates?</small>
412
+ </td>
413
+ <td>
414
+ <?php $this->condition_flag($condition) ?>
415
+ </td>
416
+ <td>
417
+ <?php if ($condition == 0) { ?>
418
+ The blog cannot contact www.thenewsletterplugin.com to check the license or the extension versions.<br>
419
+ Error: <?php echo esc_html($message) ?><br>
420
+ <?php } else { ?>
421
+
422
+ <?php } ?>
423
+ </td>
424
+ </tr>
425
+
426
+
427
+
428
+
429
+
430
+
431
+
432
+
433
+
434
+ <?php /*
435
+ $memory = intval(WP_MEMORY_LIMIT);
436
+ if (false !== strpos(WP_MEMORY_LIMIT, 'G'))
437
+ $memory *= 1024;
438
+ ?>
439
+ <tr>
440
+ <td>
441
+ PHP memory limit
442
+ </td>
443
+ <td>
444
+ <?php if ($memory < 64) { ?>
445
+ <span class="tnp-ko">MAYBE</span>
446
+ <?php } else if ($memory < 128) { ?>
447
+ <span class="tnp-maybe">MAYBE</span>
448
+ <?php } else { ?>
449
+ <span class="tnp-ok">OK</span>
450
+ <?php } ?>
451
+ </td>
452
+ <td>
453
+ WordPress WP_MEMORY_LIMIT is set to <?php echo $memory ?> megabyte but your PHP setting could allow more than that.
454
+ Anyway we suggest to set the value to at least 64M.
455
+ <a href="https://www.thenewsletterplugin.com/documentation/status-panel#status-memory" target="_blank">Read more</a>.
456
+ <?php if ($memory < 64) { ?>
457
+ This value is too low you should increase it adding <code>define('WP_MEMORY_LIMIT', '64M');</code> to your <code>wp-config.php</code>.
458
+ <a href="https://www.thenewsletterplugin.com/documentation/status-panel#status-memory" target="_blank">Read more</a>.
459
+ <?php } else if ($memory < 128) { ?>
460
+ The value should be fine, it depends on how many plugins you're running and how many resource are required by your theme.
461
+ Blank pages may happen with low memory problems. Eventually increase it adding <code>define('WP_MEMORY_LIMIT', '128M');</code>
462
+ to your <code>wp-config.php</code>.
463
+ <a href="https://www.thenewsletterplugin.com/documentation/status-panel#status-memory" target="_blank">Read more</a>.
464
+ <?php } else { ?>
465
+
466
+ <?php } ?>
467
+
468
+ </td>
469
+ </tr>
470
+ */ ?>
471
+
472
+ <?php
473
+ $ip = gethostbyname($_SERVER['HTTP_HOST']);
474
+ $name = gethostbyaddr($ip);
475
+ $res = true;
476
+ if (strpos($name, '.secureserver.net') !== false) {
477
+ //$smtp = get_option('newsletter_main_smtp');
478
+ //if (!empty($smtp['enabled']))
479
+ $res = false;
480
+ $message = 'If you\'re hosted with GoDaddy, be sure to set their SMTP (relay-hosting.secureserver.net, without username and password) to send emails
481
+ on Newsletter SMTP panel.
482
+ Remember they limits you to 250 emails per day. Open them a ticket for more details.';
483
+ }
484
+ if (strpos($name, '.aruba.it') !== false) {
485
+ $res = false;
486
+ $message = 'If you\'re hosted with Aruba consider to use an external SMTP (Sendgrid, Mailjet, Mailgun, Amazon SES, Elasticemail, Sparkpost, ...)
487
+ since their mail service is not good. If you have your personal email with them, you can try to use the SMTP of your
488
+ pesonal account. Ask the support for the SMTP parameters and configure them on Newsletter SMTP panel.';
489
+ }
490
+ ?>
491
+ <tr>
492
+ <td>Your Server</td>
493
+ <td>
494
+ <?php if ($res === false) { ?>
495
+ <span class="tnp-maybe">MAYBE</span>
496
+ <?php } else { ?>
497
+ <span class="tnp-ok">OK</span>
498
+ <?php } ?>
499
+
500
+
501
+ </td>
502
+ <td>
503
+ <?php if ($res === false) { ?>
504
+ <?php echo $message ?>
505
+ <?php } else { ?>
506
+
507
+ <?php } ?>
508
+ IP: <?php echo $ip ?><br>
509
+ Name: <?php echo $name ?><br>
510
+ </td>
511
+ </tr>
512
+
513
+ <?php
514
+ wp_mkdir_p(NEWSLETTER_LOG_DIR);
515
+ $condition = is_dir(NEWSLETTER_LOG_DIR) && is_writable(NEWSLETTER_LOG_DIR) ? 1 : 0;
516
+ if ($condition) {
517
+ @file_put_contents(NEWSLETTER_LOG_DIR . '/test.txt', "");
518
+ $condition = is_file(NEWSLETTER_LOG_DIR . '/test.txt') ? 1 : 0;
519
+ if ($condition) {
520
+ @unlink(NEWSLETTER_LOG_DIR . '/test.txt');
521
+ }
522
+ }
523
+ ?>
524
+ <tr>
525
+ <td>
526
+ Log folder
527
+ </td>
528
+ <td>
529
+ <?php $this->condition_flag($condition) ?>
530
+ </td>
531
+ <td>
532
+ The log folder is <?php echo esc_html(NEWSLETTER_LOG_DIR) ?><br>
533
+ <?php if (!$res) { ?>
534
+ Cannot create the folder or it is not writable.
535
+ <?php } ?>
536
+ </td>
537
+ </tr>
538
+ </tbody>
539
+ </table>
540
+
541
+ <h3>3rd party plugins</h3>
542
+ <table class="widefat" id="tnp-status-table">
543
+ <thead>
544
+ <tr>
545
+ <th>Plugin</th>
546
+ <th><?php _e('Status', 'newsletter') ?></th>
547
+ <th>Action</th>
548
+ </tr>
549
+ </thead>
550
+ <tbody>
551
+ <?php if (is_plugin_active('plugin-load-filter/plugin-load-filter.php')) { ?>
552
+ <tr>
553
+ <td><a href="https://wordpress.org/plugins/plugin-load-filter/" target="_blank">Plugin load filter</a></td>
554
+ <td>
555
+ <span class="tnp-maybe">MAY BE</span>
556
+ </td>
557
+ <td>
558
+ Be sure Newsletter is set as active in EVERY context.
559
+ </td>
560
+ </tr>
561
+ <?php } ?>
562
+
563
+ <?php if (is_plugin_active('wp-asset-clean-up/wpacu.php')) { ?>
564
+ <tr>
565
+ <td><a href="https://wordpress.org/plugins/wp-asset-clean-up/" target="_blank">WP Asset Clean Up</a></td>
566
+ <td>
567
+ <span class="tnp-maybe">MAY BE</span>
568
+ </td>
569
+ <td>
570
+ Be sure Newsletter is set as active in EVERY context.
571
+ </td>
572
+ </tr>
573
+ <?php } ?>
574
+ </tbody>
575
+ </table>
576
+
577
+
578
+ <h3>WordPress</h3>
579
+
580
+ <table class="widefat" id="tnp-status-table">
581
+ <thead>
582
+ <tr>
583
+ <th>Parameter</th>
584
+ <th><?php _e('Status', 'newsletter') ?></th>
585
+ <th>Action</th>
586
+ </tr>
587
+ </thead>
588
+ <tbody>
589
+
590
+ <tr>
591
+ <?php
592
+ $condition = (defined('WP_DEBUG') && WP_DEBUG) ? 2 : 1;
593
+ ?>
594
+ <td>
595
+ WordPress debug mode
596
+ </td>
597
+ <td>
598
+ <?php $this->condition_flag($condition) ?>
599
+ </td>
600
+ <td>
601
+ <?php if (defined('WP_DEBUG') && WP_DEBUG) { ?>
602
+ WordPress is in debug mode it is not recommended on a production system. See the constant <code>WP_DEBUG</code> inside the <code>wp-config.php</code>.
603
+ <?php } else { ?>
604
+
605
+ <?php } ?>
606
+ </td>
607
+ </tr>
608
+
609
+
610
+
611
+ <tr>
612
+ <?php
613
+ $charset = get_option('blog_charset');
614
+ $condition = $charset === 'UTF-8' ? 1 : 0;
615
+ ?>
616
+ <td>Blog Charset</td>
617
+ <td>
618
+ <?php $this->condition_flag($condition) ?>
619
+ </td>
620
+ <td>
621
+ Charset: <?php echo esc_html($charset) ?>
622
+ <br>
623
+
624
+ <?php if ($condition == 1) { ?>
625
+
626
+ <?php } else { ?>
627
+ It is recommended to use
628
+ the <code>UTF-8</code> charset but the <a href="https://codex.wordpress.org/Converting_Database_Character_Sets" target="_blank">conversion</a>
629
+ could be tricky. If you're not experiencing problem, leave things as is.
630
+ <?php } ?>
631
+ </td>
632
+ </tr>
633
+
634
+ <tr>
635
+ <?php
636
+ $condition = (strpos(home_url('/'), 'http') !== 0) ? 0 : 1;
637
+ ?>
638
+ <td>Home URL</td>
639
+ <td>
640
+ <?php $this->condition_flag($condition) ?>
641
+ </td>
642
+ <td>
643
+ Value: <?php echo home_url('/'); ?>
644
+ <br>
645
+ <?php if ($condition == 0) { ?>
646
+ Your home URL is not absolute, emails require absolute URLs.
647
+ Probably you have a protocol agnostic plugin installed to manage both HTTPS and HTTP in your
648
+ blog.
649
+ <?php } else { ?>
650
+
651
+ <?php } ?>
652
+ </td>
653
+ </tr>
654
+
655
+ <tr>
656
+ <?php
657
+ $condition = (strpos(WP_CONTENT_URL, 'http') !== 0) ? 0 : 1;
658
+ ?>
659
+ <td>WP_CONTENT_URL</td>
660
+ <td>
661
+ <?php $this->condition_flag($condition) ?>
662
+ </td>
663
+ <td>
664
+ Value: <?php echo esc_html(WP_CONTENT_URL); ?>
665
+ <br>
666
+ <?php if ($condition == 0) { ?>
667
+ Your content URL is not absolute, emails require absolute URLs when they have images inside.
668
+ Newsletter tries to deal with this problem but when a problem with images persists, you should try to remove
669
+ from your <code>wp-config.php</code> the <code>WP_CONTENT_URL</code> define and check again.
670
+ <?php } else { ?>
671
+
672
+ <?php } ?>
673
+ </td>
674
+ </tr>
675
+
676
+ <tr>
677
+ <?php
678
+ set_transient('newsletter_transient_test', 1, 300);
679
+ delete_transient('newsletter_transient_test');
680
+ $res = get_transient('newsletter_transient_test');
681
+ $condition = ($res !== false) ? 0 : 1;
682
+ ?>
683
+ <td>WordPress transients</td>
684
+ <td>
685
+ <?php $this->condition_flag($condition) ?>
686
+ </td>
687
+ <td>
688
+ <?php if ($res !== false) { ?>
689
+ Transients cannot be delete. This can block the delivery engine. Usually it is due to a not well coded plugin installed.
690
+ <?php } else { ?>
691
+ <?php } ?>
692
+ </td>
693
+ </tr>
694
+ </tbody>
695
+ </table>
696
+
697
+
698
+
699
+ <h3>PHP</h3>
700
+ <table class="widefat" id="tnp-status-table">
701
+ <thead>
702
+ <tr>
703
+ <th>Parameter</th>
704
+ <th><?php _e('Status', 'newsletter') ?></th>
705
+ <th>Action</th>
706
+ </tr>
707
+ </thead>
708
+ <tbody>
709
+ <tr>
710
+ <td>PHP version</td>
711
+ <td>
712
+ <?php if (version_compare(phpversion(), '5.6', '<')) { ?>
713
+ <span class="tnp-ko">KO</span>
714
+ <?php } else { ?>
715
+ <span class="tnp-ok">OK</span>
716
+ <?php } ?>
717
+
718
+ </td>
719
+ <td>
720
+ Your PHP version is <?php echo phpversion() ?><br>
721
+ <?php if (version_compare(phpversion(), '5.3', '<')) { ?>
722
+ Newsletter plugin works correctly with PHP version 5.6 or greater. Ask your provider to upgrade your PHP. Your version is
723
+ unsupported even by the PHP community.
724
+ <?php } ?>
725
+ </td>
726
+
727
+ </tr>
728
+
729
+ <tr>
730
+ <?php
731
+ $value = (int) ini_get('max_execution_time');
732
+ $res = true;
733
+ $condition = 1;
734
+ if ($value != 0 && $value < NEWSLETTER_CRON_INTERVAL) {
735
+ $res = set_time_limit(NEWSLETTER_CRON_INTERVAL);
736
+ if ($res)
737
+ $condition = 1;
738
+ else
739
+ $condition = 0;
740
+ }
741
+ ?>
742
+ <td>PHP execution time limit</td>
743
+ <td>
744
+ <?php $this->condition_flag($condition) ?>
745
+ </td>
746
+ <td>
747
+ <?php if (!$res) { ?>
748
+ Your PHP execution time limit is <?php echo $value ?> seconds. It cannot be changed and it is too lower to grant the maximum delivery rate of Newsletter.
749
+ <?php } else { ?>
750
+ Your PHP execution time limit is <?php echo $value ?> seconds and can be eventually changed by Newsletter.<br>
751
+ <?php } ?>
752
+
753
+ </td>
754
+
755
+ </tr>
756
+
757
+
758
+ <tr>
759
+ <?php
760
+ $condition = function_exists('curl_version');
761
+ ?>
762
+ <td>Curl version</td>
763
+ <td>
764
+ <?php if (!$condition) { ?>
765
+ <span class="tnp-ko">KO</span>
766
+ <?php } else { ?>
767
+ <span class="tnp-ok">OK</span>
768
+ <?php } ?>
769
+
770
+ </td>
771
+ <td>
772
+ <?php
773
+ if (!$condition) {
774
+ echo 'cUrl is not available, ask the provider to install it and activate the PHP cUrl library';
775
+ } else {
776
+ $version = curl_version();
777
+ echo 'Version: ' . $version['version'] . '<br>';
778
+ echo 'SSL Version: ' . $version['ssl_version'] . '<br>';
779
+ }
780
+ ?>
781
+ </td>
782
+
783
+ </tr>
784
+ <?php if (ini_get('opcache.validate_timestamps') === '0') { ?>
785
+ <tr>
786
+ <td>
787
+ Opcache
788
+ </td>
789
+
790
+ <td>
791
+ <span class="tnp-ko">KO</span>
792
+ </td>
793
+
794
+ <td>
795
+ You have the PHP opcache active with file validation disable so every blog plugins update needs a webserver restart!
796
+ </td>
797
+ </tr>
798
+ <?php } ?>
799
+ </tbody>
800
+ </table>
801
+
802
+ <h3>Database</h3>
803
+ <table class="widefat" id="tnp-status-table">
804
+ <thead>
805
+ <tr>
806
+ <th>Parameter</th>
807
+ <th><?php _e('Status', 'newsletter') ?></th>
808
+ <th>Action</th>
809
+ </tr>
810
+ </thead>
811
+ <tbody>
812
+ <tr>
813
+ <td>Database Charset</td>
814
+ <td>
815
+ <?php if ($wpdb->charset != 'utf8mb4') { ?>
816
+ <span class="tnp-ko">KO</span>
817
+ <?php } else { ?>
818
+ <span class="tnp-ok">OK</span>
819
+ <?php } ?>
820
+
821
+ </td>
822
+ <td>
823
+ Charset: <?php echo $wpdb->charset; ?>
824
+ <br>
825
+ <?php if ($wpdb->charset != 'utf8mb4') { ?>
826
+ The recommended charset for your database is <code>utf8mb4</code> to avoid possible saving errors when you use emoji.
827
+ Read the WordPress Codex <a href="https://codex.wordpress.org/Converting_Database_Character_Sets" target="_blank">conversion
828
+ instructions</a> (skilled technicia required).
829
+ <?php } else { ?>
830
+ If you experience newsletter saving database error
831
+ <?php $controls->button('conversion', 'Try tables upgrade') ?>
832
+ <?php } ?>
833
+ </td>
834
+ </tr>
835
+
836
+ <tr>
837
+ <td>get_table_charset()</td>
838
+ <td>
839
+
840
+ </td>
841
+ <td>
842
+ <?php echo esc_html(NEWSLETTER_USERS_TABLE), ': ', esc_html($tnp_wpdb->get_table_charset(NEWSLETTER_USERS_TABLE)) ?>
843
+ </td>
844
+ </tr>
845
+
846
+
847
+
848
+
849
+ <?php
850
+ $wait_timeout = $wpdb->get_var("select @@wait_timeout");
851
+ $condition = ($wait_timeout < 30) ? 0 : 1;
852
+ ?>
853
+ <tr>
854
+ <td>Database wait timeout</td>
855
+ <td>
856
+ <?php $this->condition_flag($condition) ?>
857
+ </td>
858
+ <td>
859
+ Your database wait timeout is <?php echo $wait_timeout; ?> seconds<br>
860
+ <?php if ($wait_timeout < 30) { ?>
861
+ That value is low and could produce database connection errors while sending emails or during long import
862
+ sessions. Ask the provider to raise it at least to 60 seconds.
863
+ <?php } ?>
864
+ </td>
865
+ </tr>
866
+
867
+ <?php
868
+ $res = $wpdb->query("drop table if exists {$wpdb->prefix}newsletter_test");
869
+ $res = $wpdb->query("create table if not exists {$wpdb->prefix}newsletter_test (id int(20))");
870
+ $condition = $res === false ? 0 : 1;
871
+ ?>
872
+ <tr>
873
+ <td>Database table creation</td>
874
+ <td>
875
+ <?php $this->condition_flag($condition) ?>
876
+ </td>
877
+ <td>
878
+ <?php if ($res === false) { ?>
879
+ Check the privileges of the user you use to connect to the database, it seems it cannot create tables.<br>
880
+ (<?php echo esc_html($wpdb->last_error) ?>)
881
+ <?php } else { ?>
882
+ <?php } ?>
883
+ </td>
884
+ </tr>
885
+
886
+ <?php
887
+ $res = $wpdb->query("alter table {$wpdb->prefix}newsletter_test add column id1 int(20)");
888
+ $condition = $res === false ? 0 : 1;
889
+ ?>
890
+ <tr>
891
+ <td>Database table change</td>
892
+ <td>
893
+ <?php $this->condition_flag($condition) ?>
894
+ </td>
895
+ <td>
896
+ <?php if ($res === false) { ?>
897
+ Check the privileges of the user you use to connect to the database, it seems it cannot change the tables. It's require to update the
898
+ plugin.<br>
899
+ (<?php echo esc_html($wpdb->last_error) ?>)
900
+ <?php } else { ?>
901
+ <?php } ?>
902
+ </td>
903
+ </tr>
904
+
905
+ <?php
906
+ // Clean up
907
+ $res = $wpdb->query("drop table if exists {$wpdb->prefix}newsletter_test");
908
+ ?>
909
+
910
+ <?php if (!get_option('newsletter_stats_email_column_upgraded', false)) { ?>
911
+ <?php
912
+ $data_type = $wpdb->get_var(
913
+ $wpdb->prepare('SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s',
914
+ DB_NAME, NEWSLETTER_STATS_TABLE, 'email_id'));
915
+ $to_upgrade = strtoupper($data_type) == 'INT' ? false : true;
916
+ ?>
917
+ <?php if ($to_upgrade) { ?>
918
+ <tr>
919
+ <td>Database stats table upgrade</td>
920
+ <td><?php $this->condition_flag(0) ?></td>
921
+ <td><?php $controls->button('stats_email_column_upgrade', 'Stats table upgrade') ?></td>
922
+ </tr>
923
+ <?php } ?>
924
+ <?php } ?>
925
+
926
+ </tbody>
927
+ </table>
928
+
929
+
930
+
931
+ <h3>General parameters</h3>
932
+ <table class="widefat" id="tnp-parameters-table">
933
+ <thead>
934
+ <tr>
935
+ <th>Parameter</th>
936
+ <th>Value</th>
937
+ </tr>
938
+ </thead>
939
+ <tbody>
940
+
941
+ <tr>
942
+ <td>Newsletter version</td>
943
+ <td>
944
+ <?php echo NEWSLETTER_VERSION ?>
945
+ </td>
946
+ </tr>
947
+
948
+ <tr>
949
+ <td>NEWSLETTER_MAX_EXECUTION_TIME</td>
950
+ <td>
951
+ <?php
952
+ if (defined('NEWSLETTER_MAX_EXECUTION_TIME')) {
953
+ echo NEWSLETTER_MAX_EXECUTION_TIME . ' (seconds)';
954
+ } else {
955
+ echo 'Not set';
956
+ }
957
+ ?>
958
+ </td>
959
+ </tr>
960
+
961
+
962
+
963
+
964
+ <?php /*
965
+ <tr>
966
+ <td>WordPress plugin url</td>
967
+ <td>
968
+ <?php echo WP_PLUGIN_URL; ?>
969
+ <br>
970
+ Filters:
971
+
972
+ <?php
973
+ if (isset($wp_filter))
974
+ $filters = $wp_filter['plugins_url'];
975
+ if (!isset($filters) || !is_array($filters))
976
+ echo 'no filters attached to "plugin_urls"';
977
+ else {
978
+ echo '<ul>';
979
+ foreach ($filters as &$filter) {
980
+ foreach ($filter as &$entry) {
981
+ echo '<li>';
982
+ if (is_array($entry['function']))
983
+ echo esc_html(get_class($entry['function'][0]) . '->' . $entry['function'][1]);
984
+ else
985
+ echo esc_html($entry['function']);
986
+ echo '</li>';
987
+ }
988
+ }
989
+ echo '</ul>';
990
+ }
991
+ ?>
992
+ <p class="description">
993
+ This value should contains the full URL to your plugin folder. If there are filters
994
+ attached, the value can be different from the original generated by WordPress and sometime worng.
995
+ </p>
996
+ </td>
997
+ </tr>
998
+ */ ?>
999
+
1000
+ <tr>
1001
+ <td>Absolute path</td>
1002
+ <td>
1003
+ <?php echo esc_html(ABSPATH); ?>
1004
+ </td>
1005
+ </tr>
1006
+ <tr>
1007
+ <td>Tables Prefix</td>
1008
+ <td>
1009
+ <?php echo $wpdb->prefix; ?>
1010
+ </td>
1011
+ </tr>
1012
+ </tbody>
1013
+ </table>
1014
+
1015
+
1016
+ <?php if (isset($_GET['debug'])) { ?>
1017
+
1018
+ <h3>Database Tables</h3>
1019
+ <h4><?php echo $wpdb->prefix ?>newsletter</h4>
1020
+ <?php
1021
+ $rs = $wpdb->get_results("describe {$wpdb->prefix}newsletter");
1022
+ ?>
1023
+ <table class="tnp-db-table">
1024
+ <thead>
1025
+ <tr>
1026
+ <th>Field</th>
1027
+ <th>Type</th>
1028
+ <th>Null</th>
1029
+ <th>Key</th>
1030
+ <th>Default</th>
1031
+ <th>Extra</th>
1032
+ </tr>
1033
+ </thead>
1034
+ <tbody>
1035
+ <?php foreach ($rs as $r) { ?>
1036
+ <tr>
1037
+ <td><?php echo esc_html($r->Field) ?></td>
1038
+ <td><?php echo esc_html($r->Type) ?></td>
1039
+ <td><?php echo esc_html($r->Null) ?></td>
1040
+ <td><?php echo esc_html($r->Key) ?></td>
1041
+ <td><?php echo esc_html($r->Default) ?></td>
1042
+ <td><?php echo esc_html($r->Extra) ?></td>
1043
+ </tr>
1044
+ <?php } ?>
1045
+ </tbody>
1046
+ </table>
1047
+
1048
+ <h4><?php echo $wpdb->prefix ?>newsletter_emails</h4>
1049
+ <?php
1050
+ $rs = $wpdb->get_results("show full columns from {$wpdb->prefix}newsletter_emails");
1051
+ ?>
1052
+ <table class="tnp-db-table">
1053
+ <thead>
1054
+ <tr>
1055
+ <th>Field</th>
1056
+ <th>Type</th>
1057
+ <th>Collation</th>
1058
+ <th>Null</th>
1059
+ <th>Key</th>
1060
+ <th>Default</th>
1061
+ <th>Extra</th>
1062
+ </tr>
1063
+ </thead>
1064
+ <tbody>
1065
+ <?php foreach ($rs as $r) { ?>
1066
+ <tr>
1067
+ <td><?php echo esc_html($r->Field) ?></td>
1068
+ <td><?php echo esc_html($r->Type) ?></td>
1069
+ <td><?php echo esc_html($r->Collation) ?></td>
1070
+ <td><?php echo esc_html($r->Null) ?></td>
1071
+ <td><?php echo esc_html($r->Key) ?></td>
1072
+ <td><?php echo esc_html($r->Default) ?></td>
1073
+ <td><?php echo esc_html($r->Extra) ?></td>
1074
+ </tr>
1075
+ <?php } ?>
1076
+ </tbody>
1077
+ </table>
1078
+
1079
+
1080
+ <h3>Extensions</h3>
1081
+ <pre style="font-size: 11px; font-family: monospace; background-color: #efefef; color: #444"><?php echo esc_html(print_r(get_option('newsletter_extension_versions'), true)); ?></pre>
1082
+
1083
+ <h3>Update plugins data</h3>
1084
+ <pre style="font-size: 11px; font-family: monospace; background-color: #efefef; color: #444"><?php echo esc_html(print_r(get_site_transient('update_plugins'), true)); ?></pre>
1085
+
1086
+ <?php } ?>
1087
+ </div>
1088
+
1089
+ <?php include NEWSLETTER_DIR . '/tnp-footer.php'; ?>
1090
+
1091
+ </div>
tnp-footer.php CHANGED
@@ -16,12 +16,18 @@ defined('ABSPATH') || exit;
16
  </ul>
17
  </div>
18
  <div>
19
- <form target="_blank" action="https://www.thenewsletterplugin.com/?na=s" method="post">
20
- <input type="email" name="ne" placeholder="Your email" required size="20" value="<?php echo esc_attr($current_user->user_email) ?>">
21
  <input type="hidden" value="plugin-footer" name="nr">
22
  <input type="hidden" value="3" name="nl[]">
23
- <input type="hidden" value="single" name="optin">
24
- <input type="submit" value="<?php _e('Stay updated', 'newsletter') ?>">
 
 
 
 
 
 
25
  </form>
26
  </div>
27
  </div>
16
  </ul>
17
  </div>
18
  <div>
19
+ <form target="_blank" action="https://www.thenewsletterplugin.com/?na=s" method="post" style="margin: 0">
20
+ <input type="email" name="ne" placeholder="Your email" required size="20" value="<?php echo esc_attr($current_user_email) ?>">
21
  <input type="hidden" value="plugin-footer" name="nr">
22
  <input type="hidden" value="3" name="nl[]">
23
+ <input type="hidden" value="1" name="nl[]">
24
+ <input type="hidden" value="double" name="optin">
25
+ <input type="submit" value="<?php _e('Get news and promotions', 'newsletter') ?>">
26
+ <span style="color: #bbb; margin-bottom: 0px; display: block; line-height: normal">
27
+ Proceeding you agree to the
28
+ <a href="https://www.thenewsletterplugin.com/privacy" target="_blank" style="color: #2ECC71">privacy policy</a>
29
+ </span>
30
+
31
  </form>
32
  </div>
33
  </div>
tnp-header.php CHANGED
@@ -29,6 +29,11 @@ $status_options = Newsletter::instance()->get_options('status');
29
  $warning = false;
30
 
31
  //$warning |= empty($status_options['mail']);
 
 
 
 
 
32
  ?>
33
 
34
  <div class="tnp-drowpdown" id="tnp-header">
@@ -286,12 +291,15 @@ $warning = false;
286
  <?php if (isset($_GET['debug']) || !isset($dismissed['newsletter-subscribe']) && get_option('newsletter_install_time') && get_option('newsletter_install_time') < time() - 86400 * 15) { ?>
287
  <div class="tnp-notice">
288
  <a href="<?php echo $_SERVER['REQUEST_URI'] . '&noheader=1&dismiss=newsletter-subscribe' ?>" class="tnp-dismiss">&times;</a>
289
- If you want to be informed of important updates of Newsletter, you may want to subscribe to our newsletter<br>
 
 
290
  <form action="https://www.thenewsletterplugin.com/?na=s" target="_blank" method="post">
291
  <input type="hidden" value="plugin-header" name="nr">
292
  <input type="hidden" value="3" name="nl[]">
293
- <input type="hidden" value="single" name="optin">
294
- <input type="email" name="ne" value="<?php echo esc_attr($current_user->user_email) ?>">
 
295
  <input type="submit" value="<?php esc_attr_e('Subscribe', 'newsletter') ?>">
296
  </form>
297
  </div>
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">
291
  <?php if (isset($_GET['debug']) || !isset($dismissed['newsletter-subscribe']) && get_option('newsletter_install_time') && get_option('newsletter_install_time') < time() - 86400 * 15) { ?>
292
  <div class="tnp-notice">
293
  <a href="<?php echo $_SERVER['REQUEST_URI'] . '&noheader=1&dismiss=newsletter-subscribe' ?>" class="tnp-dismiss">&times;</a>
294
+ Subscribe to our news, promotions and getting started lessons!
295
+ Proceeding you agree to the <a href="https://www.thenewsletterplugin.com/privacy" target="_blank">privacy policy</a>.
296
+ <br>
297
  <form action="https://www.thenewsletterplugin.com/?na=s" target="_blank" method="post">
298
  <input type="hidden" value="plugin-header" name="nr">
299
  <input type="hidden" value="3" name="nl[]">
300
+ <input type="hidden" value="1" name="nl[]">
301
+ <input type="hidden" value="double" name="optin">
302
+ <input type="email" name="ne" value="<?php echo esc_attr($current_user_email) ?>">
303
  <input type="submit" value="<?php esc_attr_e('Subscribe', 'newsletter') ?>">
304
  </form>
305
  </div>