Contact Form by WPForms – Drag & Drop Form Builder for WordPress - Version 1.3.6

Version Description

  • Added: Constant Contact integration
  • Changed: Don't strip tags from plain text emails
  • Fixed: Form builder javascript conflict with Clef plugin
  • Fixed: Form builder logo URL double slash
  • Fixed: Form builder embed code field not being selectable
Download this release

Release Info

Developer jaredatch
Plugin Icon 128x128 Contact Form by WPForms – Drag & Drop Form Builder for WordPress
Version 1.3.6
Comparing to
See all releases

Code changes from version 1.3.5 to 1.3.6

assets/css/admin-builder-providers.css ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* ==========================================================================
2
+ Admin Form Builder - providers panel (Providers)
3
+ ========================================================================== */
4
+
5
+ #wpforms-panel-providers {
6
+
7
+ }
8
+
9
+ #wpforms-panel-providers .wpforms-provider-connections-wrap {
10
+ }
11
+
12
+ #wpforms-panel-providers .wpforms-provider-connections-header {
13
+ background-color: #ddd;
14
+ padding: 10px 20px;
15
+ }
16
+
17
+ #wpforms-panel-providers .wpforms-provider-connections-add {
18
+ background-color: #0e6cad;
19
+ color: #fff;
20
+ border: none;
21
+ -webkit-appearance: none;
22
+ border-radius: 2px;
23
+ font-size: 14px;
24
+ font-weight: 500;
25
+ float: right;
26
+ padding: 10px;
27
+ margin-top: -10px;
28
+ cursor: pointer;
29
+ }
30
+
31
+ #wpforms-panel-providers .wpforms-provider-connection-delete {
32
+ background-color: transparent;
33
+ color: #fff;
34
+ cursor: pointer;
35
+ -webkit-appearance: none;
36
+ border: none;
37
+ font-size: 16px;
38
+ color: #d22222;
39
+ line-height: 1;
40
+ margin-top: -2px;
41
+ float: right;
42
+ }
43
+
44
+ #wpforms-panel-providers .wpforms-provider-connections-header h5 {
45
+ float: left;
46
+ padding: 0;
47
+ margin: 0;
48
+ font-size: 18px;
49
+ padding-top: 5px;
50
+ }
51
+
52
+ #wpforms-panel-providers .wpforms-provider-connection {
53
+ border: 1px solid #d3d3d3;
54
+ margin: 0 0 20px 0;
55
+ }
56
+
57
+ #wpforms-panel-providers .wpforms-provider-connection-header {
58
+ background-color: #f1f1f1;
59
+ padding: 10px 20px;
60
+ font-size: 16px;
61
+ }
62
+
63
+ #wpforms-panel-providers .wpforms-connection-block {
64
+ padding: 10px 20px;
65
+ }
66
+
67
+ #wpforms-panel-providers .wpforms-connection-block h4 {
68
+ margin: 0 0 5px 0;
69
+ padding: 0;
70
+ font-size: 13px;
71
+ }
72
+
73
+ #wpforms-panel-providers .wpforms-provider-account-add input[type=text] {
74
+ display: block;
75
+ width: 100%;
76
+ max-width: 350px;
77
+ width: 99%;
78
+ border: 1px solid #d6d6d6;
79
+ padding: 6px 8px;
80
+ line-height: 18px;
81
+ box-shadow: none;
82
+ margin: 0 0 5px 0;
83
+ }
84
+
85
+ #wpforms-panel-providers .wpforms-provider-account-add button {
86
+ display: block;
87
+ width: 100%;
88
+ max-width: 350px;
89
+ background-color: #0e6cad;
90
+ color: #fff;
91
+ font-size: 13px;
92
+ border: none;
93
+ -webkit-appearance: none;
94
+ border-radius: 2px;
95
+ padding: 8px 10px;
96
+ cursor: pointer;
97
+ }
98
+
99
+ #wpforms-panel-providers .wpforms-provider-groups-list p {
100
+ font-size: 11px;
101
+ font-weight: 700;
102
+ text-transform: uppercase;
103
+ }
104
+
105
+ #wpforms-panel-providers .wpforms-provider-groups-list span {
106
+ display: block;
107
+ font-size: 12px;
108
+ margin-bottom: 4px;
109
+ }
110
+
111
+ #wpforms-panel-providers .wpforms-provider-groups-list input {
112
+ margin-right: 8px
113
+ }
114
+
115
+ #wpforms-panel-providers .wpforms-provider-fields table {
116
+ width: 100%;
117
+ border:1px solid #eee;
118
+ }
119
+
120
+ #wpforms-panel-providers .wpforms-provider-fields .required {
121
+ color: red;
122
+ font-weight: 700;
123
+ }
124
+
125
+ #wpforms-panel-providers .wpforms-provider-fields table select {
126
+ width: 100%;
127
+ }
128
+
129
+ #wpforms-panel-providers .wpforms-provider-fields table thead {
130
+ font-size: 11px;
131
+ font-weight: 700;
132
+ text-transform: uppercase;
133
+ }
134
+
135
+ #wpforms-panel-providers .wpforms-provider-fields table tbody td {
136
+ border-top: 1px solid #eee;
137
+ padding: 5px 10px;
138
+ }
139
+
140
+ #wpforms-panel-providers .wpforms-provider-conditionals-groups table {
141
+ width: 100%;
142
+ border:1px solid #eee;
143
+ padding: 5px 0;
144
+ }
145
+
146
+ #wpforms-panel-providers .wpforms-provider-conditionals-group:first-of-type tr:first-of-type .wpforms-provider-conditionals-rule-delete {
147
+ display: none;
148
+ }
149
+
150
+ #wpforms-panel-providers .wpforms-provider-conditionals-groups input[type=text],
151
+ #wpforms-panel-providers .wpforms-provider-conditionals-groups select {
152
+ width: 100%;
153
+ }
154
+
155
+ #wpforms-panel-providers .wpforms-provider-conditionals-groups .field {
156
+ width: 150px;
157
+ }
158
+
159
+ #wpforms-panel-providers .wpforms-provider-conditionals-groups .operator {
160
+ width: 80px;
161
+ }
162
+
163
+ #wpforms-panel-providers .wpforms-provider-conditionals-groups .actions {
164
+ width: 80px;
165
+ }
166
+
167
+ #wpforms-panel-providers .wpforms-provider-options label.block {
168
+ display: block;
169
+ margin: 0 0 5px 0;
170
+ }
171
+
172
+ #wpforms-panel-providers .wpforms-provider-options input[type=text] {
173
+ display: block;
174
+ width: 100%;
175
+ padding: 6px 8px;
176
+ box-shadow: none;
177
+ }
assets/css/admin-builder.css CHANGED
@@ -51,7 +51,7 @@ body {
51
  }
52
 
53
  #wpforms-builder .wpforms-alert {
54
- padding: 10px;
55
  margin-bottom: 18px;
56
  border: 1px solid transparent;
57
  }
@@ -61,13 +61,12 @@ body {
61
  color: inherit;
62
  }
63
 
64
- #wpforms-builder .wpforms-alert > p,
65
- #wpforms-builder .wpforms-alert > ul {
66
- margin-bottom: 0;
67
  }
68
 
69
- #wpforms-builder .wpforms-alert > p + p {
70
- margin-top: 5px;
71
  }
72
 
73
  #wpforms-builder .wpforms-alert-nomargin {
51
  }
52
 
53
  #wpforms-builder .wpforms-alert {
54
+ padding: 16px;
55
  margin-bottom: 18px;
56
  border: 1px solid transparent;
57
  }
61
  color: inherit;
62
  }
63
 
64
+ #wpforms-builder .wpforms-alert p{
65
+ margin: 0 0 15px 0;
 
66
  }
67
 
68
+ #wpforms-builder .wpforms-alert p:last-of-type {
69
+ margin: 0;
70
  }
71
 
72
  #wpforms-builder .wpforms-alert-nomargin {
assets/css/admin-settings.css CHANGED
@@ -10,7 +10,7 @@
10
  #wpforms-settings .wpforms-clear:after {
11
  clear: both;
12
  content: " ";
13
- display: table;
14
  }
15
 
16
  #wpforms-settings .wpforms-circle-loader {
@@ -87,40 +87,40 @@
87
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-11 {
88
  -webkit-transform: rotate(300deg);
89
  -ms-transform: rotate(300deg);
90
- transform: rotate(300deg);
91
  }
92
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-12 {
93
  -webkit-transform: rotate(330deg);
94
  -ms-transform: rotate(330deg);
95
- transform: rotate(330deg);
96
  }
97
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-2:before {
98
  -webkit-animation-delay: -1.1s;
99
- animation-delay: -1.1s;
100
  }
101
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-3:before {
102
  -webkit-animation-delay: -1s;
103
- animation-delay: -1s;
104
  }
105
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-4:before {
106
  -webkit-animation-delay: -0.9s;
107
- animation-delay: -0.9s;
108
  }
109
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-5:before {
110
  -webkit-animation-delay: -0.8s;
111
- animation-delay: -0.8s;
112
  }
113
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-6:before {
114
  -webkit-animation-delay: -0.7s;
115
- animation-delay: -0.7s;
116
  }
117
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-7:before {
118
  -webkit-animation-delay: -0.6s;
119
- animation-delay: -0.6s;
120
  }
121
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-8:before {
122
  -webkit-animation-delay: -0.5s;
123
- animation-delay: -0.5s;
124
  }
125
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-9:before {
126
  -webkit-animation-delay: -0.4s;
@@ -146,7 +146,7 @@
146
 
147
  @keyframes wpforms-circleFadeDelay {
148
  0%, 39%, 100% { opacity: 0; }
149
- 40% { opacity: 1; }
150
  }
151
 
152
  #wpforms-settings .wpforms-tab,
@@ -245,6 +245,10 @@
245
  padding: 20px 0;
246
  }
247
 
 
 
 
 
248
  .wpforms-settings-provider-header {
249
  cursor: pointer;
250
  }
@@ -308,6 +312,10 @@
308
  display: none;
309
  }
310
 
 
 
 
 
311
  .wpforms-settings-provider-accounts-list ul {
312
  padding: 0;
313
  margin: 0;
@@ -316,7 +324,15 @@
316
  .wpforms-settings-provider-accounts-list ul li {
317
  border-bottom: 1px solid #ddd;
318
  margin: 0;
319
- padding: 4px 0;
 
 
 
 
 
 
 
 
320
  }
321
 
322
  .wpforms-settings-provider-accounts-list span.label {
@@ -327,7 +343,7 @@
327
  .wpforms-settings-provider-accounts-list span.date {
328
  color: #999;
329
  display: inline-block;
330
- width: 220px;
331
  }
332
 
333
  .wpforms-settings-provider-accounts-connect {
@@ -335,6 +351,10 @@
335
  padding-top: 10px;
336
  }
337
 
 
 
 
 
338
  .wpforms-settings-provider-accounts-connect .fa {
339
  display: none;
340
  }
@@ -358,7 +378,7 @@
358
  background: #fff;
359
  white-space: pre;
360
  overflow: auto;
361
- display: block;
362
  padding: 20px;
363
  }
364
 
@@ -398,4 +418,59 @@
398
 
399
  #wpforms-import-export .export-list li:last-of-type label {
400
  border-bottom: none;
401
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  #wpforms-settings .wpforms-clear:after {
11
  clear: both;
12
  content: " ";
13
+ display: table;
14
  }
15
 
16
  #wpforms-settings .wpforms-circle-loader {
87
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-11 {
88
  -webkit-transform: rotate(300deg);
89
  -ms-transform: rotate(300deg);
90
+ transform: rotate(300deg);
91
  }
92
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-12 {
93
  -webkit-transform: rotate(330deg);
94
  -ms-transform: rotate(330deg);
95
+ transform: rotate(330deg);
96
  }
97
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-2:before {
98
  -webkit-animation-delay: -1.1s;
99
+ animation-delay: -1.1s;
100
  }
101
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-3:before {
102
  -webkit-animation-delay: -1s;
103
+ animation-delay: -1s;
104
  }
105
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-4:before {
106
  -webkit-animation-delay: -0.9s;
107
+ animation-delay: -0.9s;
108
  }
109
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-5:before {
110
  -webkit-animation-delay: -0.8s;
111
+ animation-delay: -0.8s;
112
  }
113
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-6:before {
114
  -webkit-animation-delay: -0.7s;
115
+ animation-delay: -0.7s;
116
  }
117
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-7:before {
118
  -webkit-animation-delay: -0.6s;
119
+ animation-delay: -0.6s;
120
  }
121
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-8:before {
122
  -webkit-animation-delay: -0.5s;
123
+ animation-delay: -0.5s;
124
  }
125
  #wpforms-settings .wpforms-circle-loader .wpforms-circle-9:before {
126
  -webkit-animation-delay: -0.4s;
146
 
147
  @keyframes wpforms-circleFadeDelay {
148
  0%, 39%, 100% { opacity: 0; }
149
+ 40% { opacity: 1; }
150
  }
151
 
152
  #wpforms-settings .wpforms-tab,
245
  padding: 20px 0;
246
  }
247
 
248
+ .wpforms-settings-provider.focus-out {
249
+ opacity: 0.4;
250
+ }
251
+
252
  .wpforms-settings-provider-header {
253
  cursor: pointer;
254
  }
312
  display: none;
313
  }
314
 
315
+ .focus-in .wpforms-settings-provider-accounts {
316
+ display: block;
317
+ }
318
+
319
  .wpforms-settings-provider-accounts-list ul {
320
  padding: 0;
321
  margin: 0;
324
  .wpforms-settings-provider-accounts-list ul li {
325
  border-bottom: 1px solid #ddd;
326
  margin: 0;
327
+ padding: 6px 0;
328
+ }
329
+
330
+ .wpforms-settings-provider-accounts-list ul li:first-of-type {
331
+ border-top: 1px solid #ddd;
332
+ }
333
+
334
+ .wpforms-settings-provider-accounts-list ul li:last-of-type {
335
+ margin-bottom: 16px;
336
  }
337
 
338
  .wpforms-settings-provider-accounts-list span.label {
343
  .wpforms-settings-provider-accounts-list span.date {
344
  color: #999;
345
  display: inline-block;
346
+ width: 240px;
347
  }
348
 
349
  .wpforms-settings-provider-accounts-connect {
351
  padding-top: 10px;
352
  }
353
 
354
+ .focus-in .wpforms-settings-provider-accounts-connect {
355
+ display: block;
356
+ }
357
+
358
  .wpforms-settings-provider-accounts-connect .fa {
359
  display: none;
360
  }
378
  background: #fff;
379
  white-space: pre;
380
  overflow: auto;
381
+ display: block;
382
  padding: 20px;
383
  }
384
 
418
 
419
  #wpforms-import-export .export-list li:last-of-type label {
420
  border-bottom: none;
421
+ }
422
+
423
+ /* Integrations tab
424
+ -------------------------------------------------------------- */
425
+
426
+ .wpforms-alert {
427
+ padding: 10px;
428
+ margin-bottom: 18px;
429
+ border: 1px solid transparent;
430
+ }
431
+
432
+ .wpforms-alert h4 {
433
+ margin-top: 0;
434
+ color: inherit;
435
+ }
436
+
437
+ .wpforms-alert > p,
438
+ .wpforms-alert > ul {
439
+ margin-bottom: 0;
440
+ }
441
+
442
+ .wpforms-alert > p + p {
443
+ margin-top: 5px;
444
+ }
445
+
446
+ .wpforms-alert-nomargin {
447
+ margin: 0;
448
+ }
449
+
450
+ .wpforms-alert-small {
451
+ font-size: 12px;
452
+ }
453
+
454
+ .wpforms-alert-success {
455
+ background-color: #dff0d8;
456
+ border-color: #d6e9c6;
457
+ color: #3c763d;
458
+ }
459
+
460
+ .wpforms-alert-info {
461
+ background-color: #d9edf7;
462
+ border-color: #bce8f1;
463
+ color: #31708f;
464
+ }
465
+
466
+ .wpforms-alert-warning {
467
+ background-color: #fcf8e3;
468
+ border-color: #faebcc;
469
+ color: #8a6d3b;
470
+ }
471
+
472
+ .wpforms-alert-danger {
473
+ background-color: #f2dede;
474
+ border-color: #ebccd1;
475
+ color: #a94442;
476
+ }
assets/images/cc-about-logo.png ADDED
Binary file
assets/images/cc-about-step1.png ADDED
Binary file
assets/images/cc-about-step2.png ADDED
Binary file
assets/images/cc-about-step3.png ADDED
Binary file
assets/images/cc-about-step4.png ADDED
Binary file
assets/images/icon-provider-constant-contact.png ADDED
Binary file
assets/js/admin-builder-providers.js ADDED
@@ -0,0 +1,731 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ;(function($) {
2
+
3
+ var s;
4
+
5
+ var WPFormsProviders = {
6
+
7
+ settings: {
8
+ form : $('#wpforms-builder-form'),
9
+ spinner: '<i class="fa fa-circle-o-notch fa-spin wpforms-button-icon" />'
10
+ },
11
+
12
+ /**
13
+ * Start the engine.
14
+ *
15
+ * @since 1.0.0
16
+ */
17
+ init: function() {
18
+ s = this.settings;
19
+
20
+ // Document ready
21
+ $(document).ready(WPFormsProviders.ready);
22
+
23
+ WPFormsProviders.bindUIActions();
24
+ },
25
+
26
+ /**
27
+ * Document ready.
28
+ *
29
+ * @since 1.1.1
30
+ */
31
+ ready: function() {
32
+
33
+ // Setup/cache some vars not available before
34
+ s.formID = $('#wpforms-builder-form').data('id');
35
+ },
36
+
37
+ /**
38
+ * Element bindings.
39
+ *
40
+ * @since 1.0.0
41
+ */
42
+ bindUIActions: function() {
43
+
44
+ // Delete connection
45
+ $(document).on('click', '.wpforms-provider-connection-delete', function(e) {
46
+ WPFormsProviders.connectionDelete(this, e);
47
+ });
48
+
49
+ // Add new connection
50
+ $(document).on('click', '.wpforms-provider-connections-add', function(e) {
51
+ WPFormsProviders.connectionAdd(this, e);
52
+ });
53
+
54
+ // Add new provider account
55
+ $(document).on('click', '.wpforms-provider-account-add button', function(e) {
56
+ WPFormsProviders.accountAdd(this, e);
57
+ });
58
+
59
+ // Select provider account
60
+ $(document).on('change', '.wpforms-provider-accounts select', function(e) {
61
+ WPFormsProviders.accountSelect(this, e);
62
+ });
63
+
64
+ // Select account list
65
+ $(document).on('change', '.wpforms-provider-lists select', function(e) {
66
+ WPFormsProviders.accountListSelect(this, e);
67
+ });
68
+
69
+ // Conditional support toggle
70
+ $(document).on('change', '.wpforms-provider-conditionals .toggle', function(e) {
71
+ WPFormsProviders.conditionalToggle(this, e);
72
+ });
73
+
74
+ // Conditional logic real updates
75
+ $(document).on('wpformsFieldUpdate', WPFormsProviders.conditionalUpdateOptions);
76
+
77
+ // Conditional process field
78
+ $(document).on('change', '.wpforms-provider-conditionals .field select', function(e) {
79
+ WPFormsProviders.conditionalField(this, e);
80
+ });
81
+
82
+ // Conditional add new rule
83
+ $(document).on('click', '.wpforms-provider-conditionals-rule-add', function(e) {
84
+ WPFormsProviders.conditionalRuleAdd(this, e);
85
+ });
86
+
87
+ // Conditional delete rule
88
+ $(document).on('click', '.wpforms-provider-conditionals-rule-delete', function(e) {
89
+ WPFormsProviders.conditionalRuleDelete(this, e);
90
+ });
91
+
92
+ // Conditional add new group
93
+ $(document).on('click', '.wpforms-provider-conditionals-groups-add', function(e) {
94
+ WPFormsProviders.conditionalGroupAdd(this, e);
95
+ });
96
+
97
+ $(document).on('wpformsPanelSwitch', function(e, targetPanel) {
98
+ WPFormsProviders.providerPanelConfirm(targetPanel);
99
+ });
100
+ },
101
+
102
+ /**
103
+ * Delete provider connection
104
+ *
105
+ * @since 1.0.0
106
+ */
107
+ connectionDelete: function(el, e) {
108
+ e.preventDefault();
109
+
110
+ var $this = $(el);
111
+ $.confirm({
112
+ title: false,
113
+ content: wpforms_builder_providers.confirm_connection,
114
+ backgroundDismiss: false,
115
+ closeIcon: false,
116
+ confirm: function(){
117
+ $this.closest('.wpforms-provider-connection').remove();
118
+ }
119
+ });
120
+ },
121
+
122
+ /**
123
+ * Add new provider connection.
124
+ *
125
+ * @since 1.0.0
126
+ */
127
+ connectionAdd: function(el, e) {
128
+ e.preventDefault();
129
+
130
+ var $this = $(el),
131
+ $connections = $this.parent().parent(),
132
+ $container = $this.parent(),
133
+ provider = $this.data('provider'),
134
+ type = $this.data('type'),
135
+ namePrompt = wpforms_builder_providers.prompt_connection,
136
+ nameField = '<input autofocus="" type="text" id="provider-connection-name" placeholder="'+wpforms_builder_providers.prompt_placeholder+'">',
137
+ nameError = '<p class="error">'+wpforms_builder_providers.error_name+'</p>',
138
+ modalContent = namePrompt+nameField+nameError;
139
+
140
+ modalContent = modalContent.replace(/%type%/g,type);
141
+
142
+ $.confirm({
143
+ title: false,
144
+ content: modalContent,
145
+ backgroundDismiss: false,
146
+ closeIcon: false,
147
+ confirm: function () {
148
+ var input = this.$b.find('input#provider-connection-name');
149
+ var error = this.$b.find('.error');
150
+ if (input.val() == '') {
151
+ error.show();
152
+ return false;
153
+ } else {
154
+
155
+ var name = input.val();
156
+
157
+ // Disable button
158
+ WPFormsProviders.inputToggle($this, 'disable');
159
+
160
+ // Fire AJAX
161
+ var data = {
162
+ action : 'wpforms_provider_ajax_'+provider,
163
+ provider: provider,
164
+ task : 'new_connection',
165
+ name : name,
166
+ id : s.form.data('id'),
167
+ nonce : wpforms_builder.nonce
168
+ }
169
+ WPFormsProviders.fireAJAX($this, data, function(res) {
170
+ if (res.success) {
171
+ $connections.find('.wpforms-provider-connections').prepend(res.data.html);
172
+ // Process and load the accounts if they exist
173
+ var $connection = $connections.find('.wpforms-provider-connection:first');
174
+ if ($connection.find( '.wpforms-provider-accounts option:selected')) {
175
+ $connection.find( '.wpforms-provider-accounts option:first').prop('selected', true);
176
+ $connection.find('.wpforms-provider-accounts select').trigger('change');
177
+ }
178
+ } else {
179
+ WPFormsProviders.errorDisplay(res.data.error, $container);
180
+ }
181
+ });
182
+ }
183
+ }
184
+ });
185
+ },
186
+
187
+ /**
188
+ * Add and authorize provider account.
189
+ *
190
+ * @since 1.0.0
191
+ */
192
+ accountAdd: function(el, e) {
193
+ e.preventDefault();
194
+
195
+ var $this = $(el),
196
+ provider = $this.data('provider'),
197
+ $connection = $this.closest('.wpforms-provider-connection'),
198
+ $container = $this.parent(),
199
+ $fields = $container.find(':input'),
200
+ errors = WPFormsProviders.requiredCheck($fields, $container);
201
+
202
+ // Disable button
203
+ WPFormsProviders.inputToggle($this, 'disable');
204
+
205
+ // Bail if we have any errors
206
+ if (errors) {
207
+ $this.prop('disabled', false).find('i').remove();
208
+ return false;
209
+ }
210
+
211
+ // Fire AJAX
212
+ data = {
213
+ action : 'wpforms_provider_ajax_'+provider,
214
+ provider : provider,
215
+ connection_id: $connection.data('connection_id'),
216
+ task : 'new_account',
217
+ data : WPFormsProviders.fakeSerialize($fields),
218
+ }
219
+ WPFormsProviders.fireAJAX($this, data, function(res) {
220
+ if (res.success) {
221
+ $container.nextAll('.wpforms-connection-block').remove();
222
+ $container.after(res.data.html);
223
+ $container.slideUp();
224
+ $connection.find('.wpforms-provider-accounts select').trigger('change');
225
+ } else {
226
+ WPFormsProviders.errorDisplay(res.data.error, $container);
227
+ }
228
+ });
229
+ },
230
+
231
+ /**
232
+ * Selecting a provider account
233
+ *
234
+ * @since 1.0.0
235
+ */
236
+ accountSelect: function(el, e) {
237
+ e.preventDefault();
238
+
239
+ var $this = $(el),
240
+ $connection = $this.closest('.wpforms-provider-connection'),
241
+ $container = $this.parent(),
242
+ provider = $connection.data('provider');
243
+
244
+ // Disable select, show loading
245
+ WPFormsProviders.inputToggle($this, 'disable');
246
+
247
+ // Remove any blocks that might exist as we prep for new account
248
+ $container.nextAll('.wpforms-connection-block').remove();
249
+
250
+ if (!$this.val()) {
251
+
252
+ // User selected to option to add new account
253
+ $connection.find('.wpforms-provider-account-add input').val('');
254
+ $connection.find('.wpforms-provider-account-add').slideDown();
255
+ WPFormsProviders.inputToggle($this, 'enable');
256
+
257
+ } else {
258
+
259
+ $connection.find('.wpforms-provider-account-add').slideUp();
260
+
261
+ // Fire AJAX
262
+ data = {
263
+ action : 'wpforms_provider_ajax_'+provider,
264
+ provider : provider,
265
+ connection_id: $connection.data('connection_id'),
266
+ task : 'select_account',
267
+ account_id : $this.find(':selected').val(),
268
+ }
269
+ WPFormsProviders.fireAJAX($this, data, function(res) {
270
+ if (res.success) {
271
+ $container.after(res.data.html);
272
+ // Process first list found
273
+ $connection.find('.wpforms-provider-lists option:first').prop('selected', true);
274
+ $connection.find('.wpforms-provider-lists select').trigger('change');
275
+ } else {
276
+ WPFormsProviders.errorDisplay(res.data.error, $container);
277
+ }
278
+ });
279
+ }
280
+ },
281
+
282
+ /**
283
+ * Selecting a provider account list.
284
+ *
285
+ * @since 1.0.0
286
+ */
287
+ accountListSelect: function(el, e) {
288
+ e.preventDefault();
289
+
290
+ var $this = $(el),
291
+ $connection = $this.closest('.wpforms-provider-connection'),
292
+ $container = $this.parent(),
293
+ provider = $connection.data('provider');
294
+
295
+ // Disable select, show loading
296
+ WPFormsProviders.inputToggle($this, 'disable');
297
+
298
+ // Remove any blocks that might exist as we prep for new account
299
+ $container.nextAll('.wpforms-connection-block').remove();
300
+
301
+ data = {
302
+ action : 'wpforms_provider_ajax_'+provider,
303
+ provider : provider,
304
+ connection_id: $connection.data('connection_id'),
305
+ task : 'select_list',
306
+ account_id : $connection.find('.wpforms-provider-accounts option:selected').val(),
307
+ list_id : $this.find(':selected').val(),
308
+ form_id : s.formID
309
+ }
310
+ console.log(s.formID);
311
+ WPFormsProviders.fireAJAX($this, data, function(res) {
312
+ if (res.success) {
313
+ $container.after(res.data.html);
314
+ } else {
315
+ WPFormsProviders.errorDisplay(res.data.error, $container);
316
+ }
317
+ });
318
+ },
319
+
320
+ /**
321
+ * Toggle conditional field support.
322
+ *
323
+ * @since 1.0.0
324
+ */
325
+ conditionalToggle: function(el, e) {
326
+ e.preventDefault();
327
+
328
+ var $this = $(el);
329
+ if ($this.is(':checked')) {
330
+ $this.parent().parent().find('.wpforms-provider-conditionals-groups').slideDown();
331
+ } else {
332
+ $this.parent().parent().find('.wpforms-provider-conditionals-groups').slideUp();
333
+ }
334
+ },
335
+
336
+ /**
337
+ * Update/refresh the conditional logic fields and associated options.
338
+ *
339
+ * @since 1.0.4
340
+ */
341
+ conditionalUpdateOptions: function(e, fields) {
342
+
343
+ // @toodo
344
+ return;
345
+ var formFields = $.extend({}, fields);
346
+ allowed = ['text', 'textarea', 'select', 'radio', 'checkbox', 'number' ],
347
+ changed = false;
348
+
349
+ // Remove field types that are not allowed and whitelested
350
+ for(var key in formFields) {
351
+ if ($.inArray(formFields[key].type, allowed) == '-1' ){
352
+ delete formFields[key];
353
+ }
354
+ }
355
+
356
+ // Now go through each conditional rule in the builder
357
+ $('.wpforms-provider-conditionals-group-row').each(function(index, ele) {
358
+
359
+ var $this = $(this),
360
+ fieldID = $this.data('field-id'),
361
+ $fields = $this.find('.wpforms-provider-conditionals-field'),
362
+ fieldSelected = $fields.find('option:selected').val(),
363
+ $value = $this.find('.wpforms-provider-conditionals-value'),
364
+ valueSelected = '',
365
+ choiceOrder = [];
366
+
367
+ // Empty the field select box, re-add placeholder option
368
+ $fields.empty().append($('<option>', { value: '', text : '-- Select field --' }));
369
+
370
+ // Add appropriate options for each field. Reference using the
371
+ // field label (if provided) or fallback to the field ID.
372
+ for(var key in formFields) {
373
+ if (formFields[key].label.length) {
374
+ var label = wpf.sanitizeString(formFields[key].label);
375
+ } else {
376
+ var label = 'Field #' + formFields[key].val;
377
+ }
378
+ $fields.append($('<option>', { value: fields[key].id, text : label }));
379
+ }
380
+
381
+ // Check if previous selected field exists in the new options added
382
+ if ($fields.find('option[value="'+fieldSelected+'"]').length) {
383
+
384
+ // Exists, so restore previous selected value
385
+ $fields.find('option[value="'+fieldSelected+'"]').prop('selected', true);
386
+
387
+ // Since the field exist and was selected, now we must proceed
388
+ // to updating the field values. Luckily, we only have to do
389
+ // this for fields that leverage a select element.
390
+ if ( $value.length && $value.is('select') ) {
391
+
392
+ // Define the order of the choices
393
+ $('#wpforms-field-option-row-'+fieldSelected+'-choices li').each(function(index, ele) {
394
+ choiceOrder.push($(ele).data('key'));
395
+ });
396
+
397
+ // Grab the currently selected value to restore later
398
+ valueSelected = $value.find('option:selected').val();
399
+
400
+ // Remove all current options
401
+ $value.empty();
402
+
403
+ // Add new options, in the correct order
404
+ $.each(choiceOrder, function(index, val) {
405
+ var label = wpf.sanitizeString(fields['field_'+fieldSelected].choices[val].label);
406
+ $value.append($('<option>', { value: val, text : label }));
407
+ });
408
+
409
+ // Check if previous selected calue exists in the new options added
410
+ if ($value.find('option[value="'+valueSelected+'"]').length) {
411
+
412
+ $value.find('option[value="'+valueSelected+'"]').prop('selected', true);
413
+
414
+ } else {
415
+
416
+ // Add temporary placeholder value since the old one
417
+ // doesn't exist
418
+ $value.prepend($('<option>', { value: '', text : '-- Select Choice --' }));
419
+
420
+ // Old value does not exist in the new options, likely
421
+ // deleted. Add the field ID to the charged variable,
422
+ // which will let the user know the fields conditional
423
+ // logic has been altered.
424
+ if (valueSelected.length > 0) {
425
+ changed = true;
426
+ }
427
+ }
428
+ }
429
+
430
+ } else {
431
+
432
+ // Old field does not exist in the new options, likely deleted.
433
+ // Add the field ID to the charged variable, which will let
434
+ // the user know the fields conditional logic has been altered.
435
+ changed = true;
436
+
437
+ // Since previously selected field no longer exists, this
438
+ // means this rule is now invalid. So the rule gets
439
+ // deleted as long as it isn't the only rule remaining.
440
+ $group = $this.closest('.wpforms-provider-conditionals-group');
441
+ if ($group.find('table >tbody >tr').length === 1) {
442
+ var $groups = $this.closest('.wpforms-provider-conditionals-groups');
443
+ if ($groups.find('.wpforms-provider-conditionals-group').length > 1) {
444
+ $group.remove();
445
+ } else {
446
+ $this.find('.wpforms-provider-conditionals-value').remove();
447
+ $this.find('.value').append('<select>');
448
+ }
449
+ } else {
450
+ $this.remove();
451
+ }
452
+ }
453
+ });
454
+
455
+ // If conditional rules have been altered due to form updates then
456
+ // we alert the user.
457
+ if ( changed ) {
458
+
459
+ // Build and trigger alert
460
+ var alert = 'Due to form changes, Marketing Provider conditional logic rules have been removed or updated.';
461
+ $.alert({
462
+ title: 'Heads Up!',
463
+ content: alert
464
+ });
465
+ }
466
+
467
+ //console.log('Conditional logic options updated');
468
+ },
469
+
470
+ /**
471
+ * Process conditional field
472
+ *
473
+ * @since 1.0.0
474
+ */
475
+ conditionalField: function(el, e) {
476
+ e.preventDefault();
477
+
478
+ var $this = $(el),
479
+ $rule = $this.parent().parent(),
480
+ data = WPFormsProviders.conditionalData($this),
481
+ name = data.name+'['+data.groupID+']['+data.ruleID+'][value]',
482
+ element;
483
+
484
+ if ( !data.field ) {
485
+ // Placeholder has been selected
486
+ element = $('<select>');
487
+ } else if (data.field.type == 'text' || data.field.type == 'number' || data.field.type == 'textarea') {
488
+ var element = $('<input>').attr({ type: 'text', name: name, class: 'wpforms-provider-conditionals-value' });
489
+ } else {
490
+ var element = $('<select>').attr({ name: name, class: 'wpforms-provider-conditionals-value' });
491
+ $.each(data.field.choices, function( key, ele) {
492
+ if (ele) {
493
+ element.append($('<option>', { value: key, text : wpf.sanitizeString(ele.label) }));
494
+ }
495
+ });
496
+ }
497
+ $rule.find('.value').empty().append(element);
498
+ },
499
+
500
+ /**
501
+ * Add new conditional rule.
502
+ *
503
+ * @since 1.0.0
504
+ */
505
+ conditionalRuleAdd: function(el, e) {
506
+ e.preventDefault();
507
+
508
+ var $this = $(el),
509
+ $group = $this.closest('.wpforms-provider-conditionals-group'),
510
+ $rule = $group.find('tr').last(),
511
+ $newRule = $rule.clone(),
512
+ $field = $newRule.find('.field select'),
513
+ $operator = $newRule.find('.operator select'),
514
+ data = WPFormsProviders.conditionalData($field),
515
+ ruleID = Number(data.ruleID)+1,
516
+ name = data.name+'['+data.groupID+']['+ruleID+']';
517
+
518
+ $newRule.find('option:selected').prop('selected', false);
519
+ $newRule.find('.value').empty().append( $('<select>') );
520
+ $field.attr('name', name+'[field]').attr('data-ruleid', ruleID);
521
+ $operator.attr('name', name+'[operator]');
522
+ $rule.after($newRule);
523
+ },
524
+
525
+ /**
526
+ * Delete conditional rule. If the only rule in group then group will
527
+ * also be removed.
528
+ *
529
+ * @since 1.0.0
530
+ */
531
+ conditionalRuleDelete: function(el, e) {
532
+ e.preventDefault();
533
+
534
+ var $this = $(el),
535
+ $group = $this.closest('.wpforms-provider-conditionals-group');
536
+ $rows = $group.find('table >tbody >tr');
537
+
538
+ if ($rows && $rows.length === 1) {
539
+ var $groups = $this.closest('.wpforms-provider-conditionals-groups');
540
+ if ( $groups.find('.wpforms-provider-conditionals-group').length > 1 ) {
541
+ $group.remove();
542
+ } else {
543
+ return;
544
+ }
545
+ } else {
546
+ $this.parent().parent().remove();
547
+ }
548
+ },
549
+
550
+ /**
551
+ * Add new conditional group.
552
+ *
553
+ * @since 1.0.0
554
+ */
555
+ conditionalGroupAdd: function(el, e) {
556
+ e.preventDefault();
557
+
558
+ var $this = $(el),
559
+ $groupLast = $this.parent().find('.wpforms-provider-conditionals-group').last(),
560
+ $newGroup = $groupLast.clone();
561
+ $newGroup.find('tr').not(':first').remove();
562
+ var $field = $newGroup.find('.field select'),
563
+ $operator = $newGroup.find('.operator select'),
564
+ data = WPFormsProviders.conditionalData($field),
565
+ groupID = Number(data.groupID)+1,
566
+ ruleID = 0,
567
+ name = data.name+'['+groupID+']['+ruleID+']';
568
+
569
+ $newGroup.find('option:selected').prop('selected', false);
570
+ $newGroup.find('.value').empty().append( $('<select>') );
571
+ $field.attr('name', name+'[field]').attr('data-ruleid', ruleID).attr('data-groupid', groupID);
572
+ $operator.attr('name', name+'[operator]');
573
+ $this.before($newGroup);
574
+ },
575
+
576
+ /**
577
+ * Confirm form save before loading Provider panel.
578
+ * If confirmed, save and reload panel.
579
+ *
580
+ * @since 1.0.0
581
+ */
582
+ providerPanelConfirm: function(targetPanel) {
583
+
584
+ wpforms_panel_switch = true;
585
+ if (targetPanel =='providers') {
586
+ var currentState = $('#wpforms-builder-form').serializeJSON();
587
+ if ( currentState != wpforms_builder.saved_state ) {
588
+ wpforms_panel_switch = false;
589
+ $.confirm({
590
+ title: false,
591
+ content: wpforms_builder_providers.confirm_save,
592
+ backgroundDismiss: false,
593
+ closeIcon: false,
594
+ confirm: function(){
595
+ $('#wpforms-save').trigger('click');
596
+ $(document).on('wpformsSaved', function() {
597
+ window.location.href = wpforms_builder_providers.url;
598
+ });
599
+ },
600
+ });
601
+ }
602
+ }
603
+ },
604
+
605
+ //--------------------------------------------------------------------//
606
+ // Helper functions
607
+ //--------------------------------------------------------------------//
608
+
609
+ /**
610
+ * Fire AJAX call.
611
+ *
612
+ * @since 1.0.0
613
+ */
614
+ fireAJAX: function(el, d, success) {
615
+ var $this = $(el);
616
+ var data = {
617
+ id : $('#wpforms-builder-form').data('id'),
618
+ nonce : wpforms_builder.nonce
619
+ }
620
+ $.extend(data, d);
621
+ $.post(wpforms_builder.ajax_url, data, function(res) {
622
+ success(res);
623
+ WPFormsProviders.inputToggle($this, 'enable');
624
+ }).fail(function(xhr, textStatus, e) {
625
+ console.log(xhr.responseText);
626
+ });
627
+ },
628
+
629
+ /**
630
+ * Return various data for the conditional field.
631
+ *
632
+ * @since 1.0.0
633
+ */
634
+ conditionalData: function(el) {
635
+
636
+ var $this = $(el);
637
+ var data = {
638
+ formData : $('#wpforms-builder-form').serializeObject(),
639
+ fieldID : $this.find(':selected').val(),
640
+ ruleID : $this.attr('data-ruleid'),
641
+ groupID : $this.attr('data-groupid'),
642
+ connectionID: $this.attr('data-connectionid'),
643
+ provider : $this.attr('data-provider'),
644
+ selectedID : $this.find(':selected').val()
645
+ }
646
+ if (data.selectedID.length) {
647
+ data.field = data.formData.fields[data.selectedID];
648
+ } else {
649
+ data.field = false;
650
+ }
651
+ data.name = 'providers['+data.provider+']['+data.connectionID+'][conditionals]';
652
+ return data;
653
+ },
654
+
655
+ /**
656
+ * Toggle input with loading indicator.
657
+ *
658
+ * @since 1.0.0
659
+ */
660
+ inputToggle: function(el, status) {
661
+ var $this = $(el);
662
+ if (status == 'enable') {
663
+ if ($this.is('select')) {
664
+ $this.prop('disabled', false).next('i').remove();
665
+ } else {
666
+ $this.prop('disabled', false).find('i').remove();
667
+ }
668
+ } else if (status == 'disable'){
669
+ if ($this.is('select')) {
670
+ $this.prop('disabled', true).after(s.spinner);
671
+ } else {
672
+ $this.prop('disabled', true).prepend(s.spinner);
673
+ }
674
+ }
675
+ },
676
+
677
+ /**
678
+ * Display error.
679
+ *
680
+ * @since 1.0.0
681
+ */
682
+ errorDisplay: function(msg, location) {
683
+ location.find('.wpforms-error-msg').remove();
684
+ location.prepend('<p class="wpforms-alert-danger wpforms-alert wpforms-error-msg">'+msg+'</p>');
685
+ },
686
+
687
+ /**
688
+ * Check for required fields.
689
+ *
690
+ * @since 1.0.0
691
+ */
692
+ requiredCheck: function(fields, location) {
693
+ var error = false;
694
+
695
+ // Remove any previous errors
696
+ location.find('.wpforms-alert-required').remove();
697
+
698
+ // Loop through input fields and check for values
699
+ fields.each(function(index, el) {
700
+ if ( $(el).hasClass('wpforms-required') && $(el).val().length === 0 ) {
701
+ $(el).addClass('wpforms-error');
702
+ error = true;
703
+ } else {
704
+ $(el).removeClass('wpforms-error');
705
+ }
706
+ });
707
+ if (error) {
708
+ location.prepend('<p class="wpforms-alert-danger wpforms-alert wpforms-alert-required">'+wpforms_builder_providers.required_field+'</p>');
709
+ }
710
+ return error;
711
+ },
712
+
713
+ /**
714
+ * Psuedo serializing. Fake it until you make it.
715
+ *
716
+ * @since 1.0.0
717
+ */
718
+ fakeSerialize: function(els) {
719
+ var fields = els.clone();
720
+
721
+ fields.each(function(index, el){
722
+ if ($(el).data('name')) {
723
+ $(el).attr('name', $(el).data('name'));
724
+ }
725
+ });
726
+ return fields.serialize();
727
+ }
728
+ };
729
+
730
+ WPFormsProviders.init();
731
+ })(jQuery);
assets/js/admin-builder.js CHANGED
@@ -1964,7 +1964,7 @@
1964
  $(document).on('click', '#wpforms-embed', function(e) {
1965
  e.preventDefault();
1966
  var content = wpforms_builder.embed_modal;
1967
- content += '<input type=\'text\' value=\'[wpforms id="' + s.formID + '"]\' disabled id=\'wpforms-embed-shortcode\'>';
1968
  content += wpforms_builder.embed_modal_2;
1969
  content += '<br><br><iframe width="600" height="338" src="https://www.youtube-nocookie.com/embed/IxGVz3AjEe0?rel=0&amp;showinfo=0" frameborder="0" allowfullscreen></iframe>';
1970
  $.alert({
1964
  $(document).on('click', '#wpforms-embed', function(e) {
1965
  e.preventDefault();
1966
  var content = wpforms_builder.embed_modal;
1967
+ content += '<input type=\'text\' value=\'[wpforms id="' + s.formID + '"]\' readonly id=\'wpforms-embed-shortcode\'>';
1968
  content += wpforms_builder.embed_modal_2;
1969
  content += '<br><br><iframe width="600" height="338" src="https://www.youtube-nocookie.com/embed/IxGVz3AjEe0?rel=0&amp;showinfo=0" frameborder="0" allowfullscreen></iframe>';
1970
  $.alert({
assets/js/admin-settings.js CHANGED
@@ -35,8 +35,9 @@
35
  */
36
  ready: function() {
37
 
38
- s.tabs = $('#wpforms-tabs');
39
- s.tabs_nav = $('#wpforms-tabs-nav');
 
40
 
41
  // If we have a hash and it begins with "wpforms-tab", set the proper tab to be opened.
42
  if ( s.tabs_hash && s.tabs_hash.indexOf('wpforms-tab-') >= 0 ) {
@@ -44,9 +45,18 @@
44
  s.tabs_nav.find('a[href="' + s.tabs_hash_sani + '"]').addClass('wpforms-active nav-tab-active');
45
  s.tabs.find(s.tabs_hash_sani).addClass('wpforms-active').show();
46
  }
 
 
47
  $('.wpforms-circle-loader').fadeOut('fast', function() {
48
  $('#wpforms-tabs').fadeIn('fast');
49
  $('.wpforms-circle-loader').remove();
 
 
 
 
 
 
 
50
  });
51
 
52
  // Load color pickers
@@ -63,7 +73,7 @@
63
  // Change tabs on click.
64
  $(document).on('click', '#wpforms-tabs-nav a', function(e){
65
  e.preventDefault();
66
-
67
  var $this = $(this);
68
  if ( $this.hasClass('wpforms-active') ) {
69
  return;
@@ -74,13 +84,14 @@
74
  s.tabs.find(current).removeClass('wpforms-active').hide();
75
  s.tabs.find($this.attr('href')).addClass('wpforms-active').show();
76
  }
77
- });
78
 
79
  // Integrations tab accounts toggle
80
  $(document).on('click', '.wpforms-settings-provider-header', function(e) {
81
  e.preventDefault();
82
  $(this).parent().find('.wpforms-settings-provider-accounts').slideToggle();
83
- });
 
84
 
85
  $(document).on('click', '.wpforms-settings-provider-accounts-toggle a', function(e) {
86
  e.preventDefault();
@@ -98,7 +109,7 @@
98
  if ( r != true ) {
99
  return false;
100
  }
101
-
102
  var data = {
103
  action : 'wpforms_settings_provider_disconnect',
104
  provider: $this.data('provider'),
@@ -186,7 +197,18 @@
186
  // Now that everything has been set, let's open up the frame.
187
  s.media_frame.open();
188
  })
189
- }
 
 
 
 
 
 
 
 
 
 
 
190
  }
191
 
192
  WPFormsSettings.init();
35
  */
36
  ready: function() {
37
 
38
+ s.tabs = $('#wpforms-tabs');
39
+ s.tabs_nav = $('#wpforms-tabs-nav');
40
+ s.integrationFocus = WPFormsSettings.getQueryString('wpforms-integration');
41
 
42
  // If we have a hash and it begins with "wpforms-tab", set the proper tab to be opened.
43
  if ( s.tabs_hash && s.tabs_hash.indexOf('wpforms-tab-') >= 0 ) {
45
  s.tabs_nav.find('a[href="' + s.tabs_hash_sani + '"]').addClass('wpforms-active nav-tab-active');
46
  s.tabs.find(s.tabs_hash_sani).addClass('wpforms-active').show();
47
  }
48
+
49
+ // After settings are loaded, fade in the settings
50
  $('.wpforms-circle-loader').fadeOut('fast', function() {
51
  $('#wpforms-tabs').fadeIn('fast');
52
  $('.wpforms-circle-loader').remove();
53
+
54
+ // Scroll to the integration if focused on one
55
+ if ( s.integrationFocus ) {
56
+ $('body').animate({
57
+ scrollTop: $('#wpforms-integration-'+s.integrationFocus).offset().top
58
+ }, 1000);
59
+ }
60
  });
61
 
62
  // Load color pickers
73
  // Change tabs on click.
74
  $(document).on('click', '#wpforms-tabs-nav a', function(e){
75
  e.preventDefault();
76
+
77
  var $this = $(this);
78
  if ( $this.hasClass('wpforms-active') ) {
79
  return;
84
  s.tabs.find(current).removeClass('wpforms-active').hide();
85
  s.tabs.find($this.attr('href')).addClass('wpforms-active').show();
86
  }
87
+ });
88
 
89
  // Integrations tab accounts toggle
90
  $(document).on('click', '.wpforms-settings-provider-header', function(e) {
91
  e.preventDefault();
92
  $(this).parent().find('.wpforms-settings-provider-accounts').slideToggle();
93
+ $(this).parent().find('.wpforms-settings-provider-logo i').toggleClass('fa-chevron-right fa-chevron-down');
94
+ });
95
 
96
  $(document).on('click', '.wpforms-settings-provider-accounts-toggle a', function(e) {
97
  e.preventDefault();
109
  if ( r != true ) {
110
  return false;
111
  }
112
+
113
  var data = {
114
  action : 'wpforms_settings_provider_disconnect',
115
  provider: $this.data('provider'),
197
  // Now that everything has been set, let's open up the frame.
198
  s.media_frame.open();
199
  })
200
+ },
201
+
202
+ /**
203
+ * Get query string in a URL.
204
+ *
205
+ * @since 1.3.6
206
+ */
207
+ getQueryString: function(name) {
208
+
209
+ var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
210
+ return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
211
+ },
212
  }
213
 
214
  WPFormsSettings.init();
includes/admin/builder/class-builder.php CHANGED
@@ -149,6 +149,7 @@ class WPForms_Builder {
149
 
150
  // Remove conflicting scripts
151
  wp_deregister_script( 'serialize-object' );
 
152
 
153
  do_action( 'wpforms_builder_enqueues_before', $this->view );
154
 
@@ -369,7 +370,7 @@ class WPForms_Builder {
369
 
370
  <div class="wpforms-left">
371
 
372
- <img src="<?php echo WPFORMS_PLUGIN_URL; ?>/assets/images/logo-builder.png" alt="Sullie WPForms mascot">
373
 
374
  </div>
375
 
149
 
150
  // Remove conflicting scripts
151
  wp_deregister_script( 'serialize-object' );
152
+ wp_deregister_script( 'wpclef-ajax-settings' );
153
 
154
  do_action( 'wpforms_builder_enqueues_before', $this->view );
155
 
370
 
371
  <div class="wpforms-left">
372
 
373
+ <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/logo-builder.png" alt="Sullie WPForms mascot">
374
 
375
  </div>
376
 
includes/admin/builder/panels/class-providers.php ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Providers panel.
4
+ *
5
+ * @package WPForms
6
+ * @author WPForms
7
+ * @since 1.0.0
8
+ * @license GPL-2.0+
9
+ * @copyright Copyright (c) 2016, WPForms LLC
10
+ */
11
+ class WPForms_Builder_Panel_Providers extends WPForms_Builder_Panel {
12
+
13
+ /**
14
+ * All systems go.
15
+ *
16
+ * @since 1.0.0
17
+ */
18
+ public function init() {
19
+
20
+ // Define panel information
21
+ $this->name = __( 'Marketing', 'wpforms' );
22
+ $this->slug = 'providers';
23
+ $this->icon = 'fa-bullhorn';
24
+ $this->order = 10;
25
+ $this->sidebar = true;
26
+ }
27
+
28
+ /**
29
+ * Enqueue assets for the Providers panel.
30
+ *
31
+ * @since 1.0.0
32
+ */
33
+ public function enqueues() {
34
+
35
+ wp_enqueue_style(
36
+ 'wpforms-builder-providers',
37
+ WPFORMS_PLUGIN_URL . 'assets/css/admin-builder-providers.css',
38
+ null,
39
+ WPFORMS_VERSION
40
+ );
41
+
42
+ wp_enqueue_script(
43
+ 'wpforms-builder-providers',
44
+ WPFORMS_PLUGIN_URL . 'assets/js/admin-builder-providers.js',
45
+ array( 'jquery' ),
46
+ WPFORMS_VERSION,
47
+ false
48
+ );
49
+
50
+ wp_localize_script(
51
+ 'wpforms-builder-providers',
52
+ 'wpforms_builder_providers',
53
+ array(
54
+ 'url' => esc_url( home_url( add_query_arg( array('view' => 'providers' ) ) ) ),
55
+ 'confirm_save' => __( 'We need to save your progress to continue to the Marketing panel. Is that OK?', 'wpforms' ),
56
+ 'confirm_connection' => __( 'Are you sure you want to delete this connecton?', 'wpforms' ),
57
+ 'prompt_connection' => __( 'Enter a %type% nickname', 'wpforms' ),
58
+ 'prompt_placeholder' => __( 'Eg: Newsletter Optin', 'wpforms' ),
59
+ 'error_name' => __( 'You must provide a connection nickname', 'wpforms' ),
60
+ 'required_field' => __( 'Field required', 'wpforms' ),
61
+ )
62
+ );
63
+ }
64
+
65
+ /**
66
+ * Outputs the Provider panel sidebar.
67
+ *
68
+ * @since 1.0.0
69
+ */
70
+ public function panel_sidebar() {
71
+
72
+ // Sidebar contents are not valid unless we have a form
73
+ if ( !$this->form ) {
74
+ return;
75
+ }
76
+
77
+ $this->panel_sidebar_section( 'Default', 'default' );
78
+
79
+ do_action( 'wpforms_providers_panel_sidebar', $this->form );
80
+ }
81
+
82
+ /**
83
+ * Outputs the Provider panel primary content.
84
+ *
85
+ * @since 1.0.0
86
+ */
87
+ public function panel_content() {
88
+
89
+ // An array of all the active provider add-ons
90
+ $providers_active = apply_filters( 'wpforms_providers_available', array() );
91
+
92
+ if ( !$this->form ) {
93
+
94
+ // Check if there is a form created. When no form has been created
95
+ // yet let the user know we need a form to setup a provider.
96
+ echo '<div class="wpforms-alert wpforms-alert-info">';
97
+ _e( 'You need to <a href="#" class="wpforms-panel-switch" data-panel="setup">setup your form</a> before you can manage these settings.', 'wpforms' );
98
+ echo '</div>';
99
+ return;
100
+ } if ( empty( $providers_active ) ) {
101
+
102
+ // Check for active provider add-ons. When no provider add-ons are
103
+ // activated let the user know they need to install/activate an
104
+ // add-on to setup a provider
105
+ echo '<div class="wpforms-panel-content-section wpforms-panel-content-section-info">';
106
+ echo '<h5>' . __( 'Install Your Marketing Integration', 'wpforms' ) . '</h5>';
107
+ echo '<p>' . sprintf( __( 'It seems you do not have any marketing add-ons activated. You can head over to the <a href="%s">Add-Ons page</a> to install and activate the add-on for your provider.', 'wpforms' ), admin_url( 'admin.php?page=wpforms-addons' ) ) . '</p>';
108
+ echo '</div>';
109
+ } else {
110
+
111
+ // Everything is good - display default instructions
112
+ echo '<div class="wpforms-panel-content-section wpforms-panel-content-section-default">';
113
+ echo '<h5>' . __( 'Select Your Marketing Integration', 'wpforms' ) . '</h5>';
114
+ echo '<p>' . __( 'Select your email marketing service provider or CRM from the options on the left. If you don\'t see your email marketing service listed, then let us know and we\'ll do our best to get it added as fast as possible', 'wpforms' ) . '</p>';
115
+ echo '</div>';
116
+ }
117
+
118
+ do_action( 'wpforms_providers_panel_content', $this->form );
119
+ }
120
+ }
121
+ new WPForms_Builder_Panel_Providers;
includes/admin/class-menu.php CHANGED
@@ -84,6 +84,16 @@ class WPForms_Admin_Menu {
84
  array( $this, 'admin_page' )
85
  );
86
 
 
 
 
 
 
 
 
 
 
 
87
  // Addons submenu page
88
  add_submenu_page(
89
  'wpforms-overview',
84
  array( $this, 'admin_page' )
85
  );
86
 
87
+ // Hidden placeholder paged used for misc content.
88
+ add_submenu_page(
89
+ 'wpforms-settings',
90
+ __( 'WPForms', 'wpforms' ),
91
+ __( 'Info', 'wpforms' ),
92
+ $menu_cap,
93
+ 'wpforms-page',
94
+ array( $this, 'admin_page' )
95
+ );
96
+
97
  // Addons submenu page
98
  add_submenu_page(
99
  'wpforms-overview',
includes/class-providers.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Load the providers.
4
+ *
5
+ * @package WPForms
6
+ * @author WPForms
7
+ * @since 1.3.6
8
+ * @license GPL-2.0+
9
+ * @copyright Copyright (c) 2017, WPForms LLC
10
+ */
11
+ class WPForms_Providers {
12
+
13
+ /**
14
+ * Primary class constructor.
15
+ *
16
+ * @since 1.3.6
17
+ */
18
+ public function __construct() {
19
+
20
+ $this->init();
21
+ }
22
+
23
+ /**
24
+ * Load and init the base provider class.
25
+ *
26
+ * @since 1.3.6
27
+ */
28
+ public function init() {
29
+
30
+ // Parent class template
31
+ require_once WPFORMS_PLUGIN_DIR . 'includes/providers/class-base.php';
32
+
33
+ // Load default templates on WP init
34
+ add_action( 'wpforms_loaded', array( $this, 'load' ) );
35
+ }
36
+
37
+ /**
38
+ * Load default marketing providers.
39
+ *
40
+ * @since 1.3.6
41
+ */
42
+ public function load() {
43
+
44
+ $providers = array(
45
+ 'constant-contact',
46
+ );
47
+
48
+ $providers = apply_filters( 'wpforms_load_providers', $providers );
49
+
50
+ foreach ( $providers as $provider ) {
51
+ require_once WPFORMS_PLUGIN_DIR . 'includes/providers/class-' . $provider . '.php';
52
+ }
53
+ }
54
+ }
55
+ new WPForms_Providers;
includes/emails/class-emails.php CHANGED
@@ -248,9 +248,9 @@ class WPForms_WP_Emails {
248
  public function build_email( $message ) {
249
 
250
  if ( false === $this->html ) {
251
- $message = $this->process_tag( $message, true, true );
252
  $message = str_replace( '{all_fields}', $this->wpforms_html_field_value( false ), $message );
253
- return apply_filters( 'wpforms_email_message', wp_strip_all_tags( $message ), $this );
254
  }
255
 
256
  ob_start();
248
  public function build_email( $message ) {
249
 
250
  if ( false === $this->html ) {
251
+ $message = $this->process_tag( $message, false, true );
252
  $message = str_replace( '{all_fields}', $this->wpforms_html_field_value( false ), $message );
253
+ return apply_filters( 'wpforms_email_message', $message, $this );
254
  }
255
 
256
  ob_start();
includes/providers/class-base.php ADDED
@@ -0,0 +1,1313 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Provider class.
4
+ *
5
+ * @package WPForms
6
+ * @author WPForms
7
+ * @since 1.0.0
8
+ * @license GPL-2.0+
9
+ * @copyright Copyright (c) 2016, WPForms LLC
10
+ */
11
+ abstract class WPForms_Provider {
12
+
13
+ /**
14
+ * Provider add-on version.
15
+ *
16
+ * @since 1.0.0
17
+ * @var sting
18
+ */
19
+ private $version;
20
+
21
+ /**
22
+ * Provider name.
23
+ *
24
+ * @since 1.0.0
25
+ * @var sting
26
+ */
27
+ public $name;
28
+
29
+ /**
30
+ * Provider name in slug format.
31
+ *
32
+ * @since 1.0.0
33
+ * @var sting
34
+ */
35
+ public $slug;
36
+
37
+ /**
38
+ * Load priority.
39
+ *
40
+ * @since 1.0.0
41
+ * @var int
42
+ */
43
+ public $priority = 10;
44
+
45
+ /**
46
+ * Holds the API connections.
47
+ *
48
+ * @since 1.0.0
49
+ * @var mixed
50
+ */
51
+ public $api = false;
52
+
53
+ /**
54
+ * Service icon.
55
+ *
56
+ * @since 1.0.0
57
+ * @var string
58
+ */
59
+ public $icon;
60
+
61
+ /**
62
+ * Service icon.
63
+ *
64
+ * @since 1.2.3
65
+ * @var string
66
+ */
67
+ public $type;
68
+
69
+ /**
70
+ * Form data.
71
+ *
72
+ * @since 1.2.3
73
+ * @var array
74
+ */
75
+ public $form_data;
76
+
77
+ /**
78
+ * Primary class constructor.
79
+ *
80
+ * @since 1.0.0
81
+ */
82
+ public function __construct() {
83
+
84
+ $this->type = __( 'Connection', 'wpforms' );
85
+
86
+ $this->init();
87
+
88
+ // Add to list of available providers
89
+ add_filter( 'wpforms_providers_available', array( $this, 'register_provider' ), $this->priority, 1 );
90
+
91
+ // Process builder AJAX requests
92
+ add_action( "wp_ajax_wpforms_provider_ajax_{$this->slug}", array( $this, 'process_ajax' ) );
93
+
94
+ // Process entry
95
+ add_action( 'wpforms_process_complete', array( $this, 'process_entry' ), 5, 4 );
96
+
97
+ // Fetch and store the current form data when in the builder
98
+ add_action( 'wpforms_builder_init', array( $this, 'builder_form_data' ) );
99
+
100
+ // Output builder sidebar
101
+ add_action( 'wpforms_providers_panel_sidebar', array( $this, 'builder_sidebar' ), $this->priority );
102
+
103
+ // Output builder content
104
+ add_action( 'wpforms_providers_panel_content', array( $this, 'builder_output' ), $this->priority );
105
+
106
+ // Remove provider from Settings Integrations tab
107
+ add_action( "wp_ajax_wpforms_settings_provider_disconnect", array( $this, 'integrations_tab_disconnect' ) );
108
+
109
+ // Add new provider from Settings Integrations tab
110
+ add_action( "wp_ajax_wpforms_settings_provider_add", array( $this, 'integrations_tab_add' ) );
111
+
112
+ // Add providers sections to the Settings Integrations tab
113
+ add_action( 'wpforms_settings_providers', array( $this, 'integrations_tab_options' ), $this->priority, 2 );
114
+ }
115
+
116
+ /**
117
+ * All systems go. Used by subclasses.
118
+ *
119
+ * @since 1.0.0
120
+ */
121
+ public function init() {
122
+ }
123
+
124
+ /**
125
+ * Add to list of registered providers.
126
+ *
127
+ * @since 1.0.0
128
+ * @param array $providers
129
+ * @return array
130
+ */
131
+ function register_provider( $providers = array() ) {
132
+
133
+ $providers[$this->slug] = $this->name;
134
+ return $providers;
135
+ }
136
+
137
+ /**
138
+ * Process the Builder AJAX requests.
139
+ *
140
+ * @since 1.0.0
141
+ */
142
+ public function process_ajax() {
143
+
144
+ // Run a security check
145
+ check_ajax_referer( 'wpforms-builder', 'nonce' );
146
+
147
+ // Check for permissions
148
+ if ( !current_user_can( apply_filters( 'wpforms_manage_cap', 'manage_options' ) ) ) {
149
+ wp_send_json_error( array( 'error' => __( 'You do not have permission', 'wpforms' ) ) );
150
+ }
151
+
152
+ //--------------------------------------------------------------------//
153
+ // Create new connection
154
+ //--------------------------------------------------------------------//
155
+
156
+ if ( $_POST['task'] == 'new_connection' ) {
157
+
158
+ $connection = $this->output_connection( '', array( 'connection_name' => $_POST['name'] ), $_POST['id'] );
159
+ wp_send_json_success( array( 'html' => $connection ) );
160
+ }
161
+
162
+ //--------------------------------------------------------------------//
163
+ // Create new Provider account
164
+ //--------------------------------------------------------------------//
165
+
166
+ if ( $_POST['task'] == 'new_account' ) {
167
+
168
+ $auth = $this->api_auth( wp_parse_args( $_POST['data'], array() ), $_POST['id'] );
169
+
170
+ if ( is_wp_error( $auth ) ) {
171
+
172
+ wp_send_json_error( array( 'error' => $auth->get_error_message() ) );
173
+
174
+ } else {
175
+
176
+ $accounts = $this->output_accounts( $_POST['connection_id'], array( 'account_id' => $auth ) );
177
+ wp_send_json_success( array( 'html' => $accounts ) );
178
+ }
179
+ }
180
+
181
+ //--------------------------------------------------------------------//
182
+ // Select/Toggle Provider accounts
183
+ //--------------------------------------------------------------------//
184
+
185
+ if ( $_POST['task'] == 'select_account' ) {
186
+
187
+ $lists = $this->output_lists( $_POST['connection_id'], array( 'account_id' => $_POST['account_id'] ) );
188
+
189
+ if ( is_wp_error( $lists ) ) {
190
+
191
+ wp_send_json_error( array( 'error' => $lists->get_error_message() ) );
192
+
193
+ } else {
194
+
195
+ wp_send_json_success( array( 'html' => $lists ) );
196
+ }
197
+ }
198
+
199
+ //--------------------------------------------------------------------//
200
+ // Select/Toggle Provider account lists
201
+ //--------------------------------------------------------------------//
202
+
203
+ if ( $_POST['task'] == 'select_list' ) {
204
+
205
+ $fields = $this->output_fields( $_POST['connection_id'], array( 'account_id' => $_POST['account_id'], 'list_id' => $_POST['list_id'] ), $_POST['id'] );
206
+
207
+ if ( is_wp_error( $fields ) ) {
208
+
209
+ wp_send_json_error( array( 'error' => $fields->get_error_message() ) );
210
+
211
+ } else {
212
+
213
+ $groups = $this->output_groups( $_POST['connection_id'], array( 'account_id' => $_POST['account_id'], 'list_id' => $_POST['list_id'] ) );
214
+ $conditionals = $this->output_conditionals( $_POST['connection_id'], array( 'account_id' => $_POST['account_id'], 'list_id' => $_POST['list_id'] ), array( 'id' => absint( $_POST['form_id'] ) ) );
215
+ $options = $this->output_options( $_POST['connection_id'], array( 'account_id' => $_POST['account_id'], 'list_id' => $_POST['list_id'] ) );
216
+
217
+ wp_send_json_success( array( 'html' => $groups . $fields . $conditionals . $options ) );
218
+ }
219
+ }
220
+
221
+ die();
222
+ }
223
+
224
+ /**
225
+ * Process and submit entry to provider.
226
+ *
227
+ * @since 1.0.0
228
+ * @param array $fields
229
+ * @param array $entry
230
+ * @param array $form_data
231
+ * @param int $entry_id
232
+ */
233
+ public function process_entry( $fields, $entry, $form_data, $entry_id ) {
234
+ }
235
+
236
+ /**
237
+ * Process conditional fields.
238
+ *
239
+ * @since 1.0.0
240
+ * @param array $fields
241
+ * @param array $entry
242
+ * @param array $form_data
243
+ * @param array $connection
244
+ */
245
+ public function process_conditionals( $fields, $entry, $form_data, $connection ) {
246
+
247
+ if ( empty( $connection['conditional_logic'] ) || empty( $connection['conditionals'] ) ) {
248
+ return true;
249
+ }
250
+
251
+ $pass = false;
252
+
253
+ foreach ( $connection['conditionals'] as $group_id => $group ) {
254
+
255
+ $pass_group = true;
256
+
257
+ if ( !empty( $group ) ) {
258
+
259
+ foreach( $group as $rule_id => $rule ) {
260
+
261
+ if ( in_array( $fields[$rule['field']]['type'], array( 'text', 'textarea' ) ) ) {
262
+
263
+ if ( $rule['operator'] == "==" ) {
264
+
265
+ $pass_rule = ( $fields[$rule['field']]['value'] === $rule['value'] );
266
+
267
+ } elseif( $rule['operator'] == "!=" ) {
268
+
269
+ $pass_rule = ( $fields[$rule['field']]['value'] !== $rule['value'] );
270
+
271
+ }
272
+
273
+ } elseif ( in_array( $fields[$rule['field']]['type'], array( 'checkbox' ) ) ) {
274
+
275
+ $provided_id = false;
276
+
277
+ if ( !empty( $fields[$rule['field']]['value'] ) ) {
278
+
279
+ $provided_id = array();
280
+ $values = explode( "\n", $fields[$rule['field']]['value'] );
281
+
282
+ foreach( $form_data['fields'][$rule['field']]['choices'] as $key => $choice ) {
283
+
284
+ foreach( $values as $value ) {
285
+
286
+ if ( in_array( $value, $choice ) ) {
287
+ $provided_id[] = $key;
288
+ }
289
+ }
290
+ }
291
+ }
292
+
293
+ if ( $rule['operator'] == "==" ) {
294
+
295
+ $pass_rule = in_array( (int) $rule['value'], (array) $provided_id );
296
+
297
+ } elseif( $rule['operator'] == "!=" ) {
298
+
299
+ $pass_rule = ! in_array( (int) $rule['value'], (array) $provided_id );
300
+ }
301
+
302
+ } else {
303
+
304
+ $provided_id = false;
305
+
306
+ if ( !empty( $fields[$rule['field']]['value'] ) ) {
307
+
308
+ foreach( $form_data['fields'][$rule['field']]['choices'] as $key => $choice ) {
309
+
310
+ if ( in_array( $fields[$rule['field']]['value'], $choice ) ) {
311
+
312
+ $provided_id = (int) $key;
313
+ }
314
+ }
315
+ }
316
+
317
+ if ( $rule['operator'] == "==" ) {
318
+
319
+ $pass_rule = ( $provided_id === (int) $rule['value'] );
320
+
321
+ } elseif( $rule['operator'] == "!=" ) {
322
+
323
+ $pass_rule = ( $provided_id !== (int) $rule['value'] );
324
+
325
+ }
326
+ }
327
+
328
+ if ( !$pass_rule ) {
329
+ $pass_group = false;
330
+ break;
331
+ }
332
+ }
333
+ }
334
+
335
+ if ( $pass_group ) {
336
+ $pass = true;
337
+ }
338
+ }
339
+
340
+ return $pass;
341
+ }
342
+
343
+ /**
344
+ * Retrieve all available forms in a field.
345
+ *
346
+ * Not all fields should be available for merge tags so we compare against a
347
+ * white-list. Also some fields, such as Name, should have additional
348
+ * variations.
349
+ *
350
+ * @since 1.0.0
351
+ * @param mixed $form_id
352
+ * @return mixed boolean or array
353
+ */
354
+ public function get_form_fields( $form = false, $whitelist = array() ) {
355
+
356
+ // Accept form (post) object or form ID
357
+ if ( is_object( $form ) ) {
358
+ $form = wpforms_decode( $form->post_content );
359
+ } elseif ( is_numeric( $form ) ) {
360
+ $form = wpforms()->form->get( $form, array( 'content_only' => true ) );
361
+ }
362
+
363
+ if ( !is_array( $form ) || empty( $form['fields'] ) )
364
+ return false;
365
+
366
+ // White list of field types to allow
367
+ $allowed_form_fields = array(
368
+ 'text',
369
+ 'textarea',
370
+ 'select',
371
+ 'radio',
372
+ 'checkbox',
373
+ 'email',
374
+ 'address',
375
+ 'url',
376
+ 'name',
377
+ 'hidden',
378
+ 'date-time',
379
+ 'phone',
380
+ 'number'
381
+ );
382
+ $allowed_form_fields = apply_filters( 'wpforms_providers_fields', $allowed_form_fields );
383
+
384
+ $whitelist = !empty( $whitelist ) ? $whitelist : $allowed_form_fields;
385
+
386
+ $form_fields = $form['fields'];
387
+
388
+ foreach( $form_fields as $id => $form_field ) {
389
+ if ( !in_array( $form_field['type'], $whitelist ) ) {
390
+ unset( $form_fields[$id] );
391
+ }
392
+ }
393
+
394
+ return $form_fields;
395
+ }
396
+
397
+ /**
398
+ * Get form fields ready for select list options.
399
+ *
400
+ * In this function we also do the logic to limit certain fields to certain
401
+ * provider field types.
402
+ *
403
+ * @since 1.0.0
404
+ * @param array $form_fields
405
+ * @param string $form_field_type
406
+ */
407
+ public function get_form_field_select( $form_fields = array(), $form_field_type = '' ) {
408
+
409
+ if ( empty( $form_fields ) || empty( $form_field_type ) )
410
+ return array();
411
+
412
+ $formatted = array();
413
+
414
+ // Include only specific field types
415
+ foreach ( $form_fields as $id => $form_field ) {
416
+
417
+ // Email
418
+ if ( 'email' == $form_field_type && !in_array( $form_field['type'], array( 'text', 'email' ) ) ) {
419
+ unset( $form_fields[$id] );
420
+ }
421
+
422
+ // Address
423
+ if ( 'address' == $form_field_type && !in_array( $form_field['type'], array( 'address' ) ) ) {
424
+ unset( $form_fields[$id] );
425
+ }
426
+ }
427
+
428
+ // Format
429
+ foreach ( $form_fields as $id => $form_field ) {
430
+
431
+ // Complex Name field
432
+ if ( $form_field['type'] == 'name' ) {
433
+
434
+ // Full Name
435
+ $formatted[] = array(
436
+ 'id' => $form_field['id'],
437
+ 'key' => 'value',
438
+ 'type' => $form_field['type'],
439
+ 'subtype' => '',
440
+ 'provider_type' => $form_field_type,
441
+ 'label' => $form_field['label'] . sprintf( ' (%s)', __( 'Full', 'wpforms' ) ),
442
+ );
443
+
444
+ // First Name
445
+ if ( strpos( $form_field['format'], 'first' ) !== false ) {
446
+ $formatted[] = array(
447
+ 'id' => $form_field['id'],
448
+ 'key' => 'first',
449
+ 'type' => $form_field['type'],
450
+ 'subtype' => 'first',
451
+ 'provider_type' => $form_field_type,
452
+ 'label' => $form_field['label'] . sprintf( ' (%s)', __( 'First', 'wpforms' ) ),
453
+ );
454
+ }
455
+
456
+ // Middle Name
457
+ if ( strpos( $form_field['format'], 'middle' ) !== false ) {
458
+ $formatted[] = array(
459
+ 'id' => $form_field['id'],
460
+ 'key' => 'middle',
461
+ 'type' => $form_field['type'],
462
+ 'subtype' => 'middle',
463
+ 'provider_type' => $form_field_type,
464
+ 'label' => $form_field['label'] . sprintf( ' (%s)', __( 'Middle', 'wpforms' ) ),
465
+ );
466
+ }
467
+
468
+ // Middle Name
469
+ if ( strpos( $form_field['format'], 'last' ) !== false ) {
470
+ $formatted[] = array(
471
+ 'id' => $form_field['id'],
472
+ 'key' => 'last',
473
+ 'type' => $form_field['type'],
474
+ 'subtype' => 'last',
475
+ 'provider_type' => $form_field_type,
476
+ 'label' => $form_field['label'] . sprintf( ' (%s)', __( 'Last', 'wpforms' ) ),
477
+ );
478
+ }
479
+
480
+ // All other fields
481
+ } else {
482
+
483
+ $formatted[] = array(
484
+ 'id' => $form_field['id'],
485
+ 'key' => 'value',
486
+ 'type' => $form_field['type'],
487
+ 'subtype' => '',
488
+ 'provider_type' => $form_field_type,
489
+ 'label' => $form_field['label'],
490
+ );
491
+ }
492
+ }
493
+
494
+ return $formatted;
495
+ }
496
+
497
+ //************************************************************************//
498
+ //
499
+ // API methods - these methods interact directly with the provider API.
500
+ //
501
+ //************************************************************************//
502
+
503
+ /**
504
+ * Authenticate with the provider API.
505
+ *
506
+ * @param array $data
507
+ * @param string $form_id
508
+ * @return mixed id or error object
509
+ */
510
+ public function api_auth( $data = array(), $form_id = '' ) {
511
+ }
512
+
513
+ /**
514
+ * Establish connection object to provider API.
515
+ *
516
+ * @since 1.0.0
517
+ * @param string $account_id
518
+ * @return mixed array or error object
519
+ */
520
+ public function api_connect( $account_id ) {
521
+ }
522
+
523
+ /**
524
+ * Retrieve provider account lists.
525
+ *
526
+ * @since 1.0.0
527
+ * @param string $connection_id
528
+ * @param string $account_id
529
+ * @return mixed array or error object
530
+ */
531
+ public function api_lists( $connection_id = '', $account_id = '' ) {
532
+ }
533
+
534
+ /**
535
+ * Retrieve provider account list groups.
536
+ *
537
+ * @since 1.0.0
538
+ * @param string $connection_id
539
+ * @param string $account_id
540
+ * @return mixed array or error object
541
+ */
542
+ public function api_groups( $connection_id = '', $account_id = '', $list_id = '' ) {
543
+ }
544
+
545
+ /**
546
+ * Retrieve provider account list fields.
547
+ *
548
+ * @since 1.0.0
549
+ * @param string $connection_id
550
+ * @param string $account_id
551
+ * @return mixed array or error object
552
+ */
553
+ public function api_fields( $connection_id = '', $account_id = '', $list_id = '' ) {
554
+ }
555
+
556
+
557
+ //************************************************************************//
558
+ //
559
+ // Output methods - these methods generally return HTML for the builder.
560
+ //
561
+ //************************************************************************//
562
+
563
+ /**
564
+ * Connection HTML.
565
+ *
566
+ * This method compiles all the HTML necessary for a connection to a provider.
567
+ *
568
+ * @since 1.0.0
569
+ * @param string $connection_id
570
+ * @param array $connection
571
+ * @param mixed $form form id or form data
572
+ * @return string
573
+ */
574
+ public function output_connection( $connection_id = '', $connection = array(), $form = '' ) {
575
+
576
+ if ( empty( $connection_id ) ) {
577
+ $connection_id = 'connection_' . uniqid();
578
+ }
579
+
580
+ if ( empty( $connection ) || empty( $form ) )
581
+ return;
582
+
583
+ $output = sprintf( '<div class="wpforms-provider-connection" data-provider="%s" data-connection_id="%s">', $this->slug, $connection_id );
584
+
585
+ $output .= $this->output_connection_header( $connection_id, $connection );
586
+
587
+ $output .= $this->output_auth();
588
+
589
+ $output .= $this->output_accounts( $connection_id, $connection );
590
+
591
+ $lists = $this->output_lists( $connection_id, $connection );
592
+ $output .= !is_wp_error( $lists ) ? $lists : '';
593
+
594
+ $output .= $this->output_groups( $connection_id, $connection );
595
+
596
+ $fields = $this->output_fields( $connection_id, $connection, $form );
597
+ $output .= !is_wp_error( $fields ) ? $fields : '';
598
+
599
+ $output .= $this->output_conditionals( $connection_id, $connection, $form );
600
+
601
+ $output .= $this->output_options( $connection_id, $connection );
602
+
603
+ $output .= '</div>';
604
+
605
+ return $output;
606
+ }
607
+
608
+ /**
609
+ * Connection header HTML.
610
+ *
611
+ * @since 1.0.0
612
+ * @param string $connection_id
613
+ * @param array $connection
614
+ * @return string
615
+ */
616
+ public function output_connection_header( $connection_id = '', $connection = array() ) {
617
+
618
+ if ( empty( $connection_id ) || empty( $connection ) )
619
+ return;
620
+
621
+ $output = '<div class="wpforms-provider-connection-header">';
622
+
623
+ $output .= sprintf( '<span>%s</span>', sanitize_text_field( $connection['connection_name'] ) );
624
+
625
+ $output .= '<button class="wpforms-provider-connection-delete"><i class="fa fa-times-circle"></i></button>';
626
+
627
+ $output .= sprintf( '<input type="hidden" name="providers[%s][%s][connection_name]" value="%s">', $this->slug, $connection_id, esc_attr( $connection['connection_name'] ) );
628
+
629
+ $output .= '</div>';
630
+
631
+ return $output;
632
+ }
633
+
634
+ /**
635
+ * Provider account authorize fields HTML.
636
+ *
637
+ * @since 1.0.0
638
+ * @return string
639
+ */
640
+ public function output_auth() {
641
+ }
642
+
643
+ /**
644
+ * Provider account select HTML.
645
+ *
646
+ * @since 1.0.0
647
+ * @param string $connection_id
648
+ * @param array $connection
649
+ * @return string
650
+ */
651
+ public function output_accounts( $connection_id = '', $connection = array() ) {
652
+
653
+ if ( empty( $connection_id ) || empty( $connection ) )
654
+ return;
655
+
656
+ $providers = get_option( 'wpforms_providers' );
657
+
658
+ if ( empty( $providers[$this->slug] ) )
659
+ return;
660
+
661
+ $output = '<div class="wpforms-provider-accounts wpforms-connection-block">';
662
+
663
+ $output .= sprintf( '<h4>%s</h4>', __( 'Select Account', 'wpforms' ) );
664
+
665
+ $output .= sprintf( '<select name="providers[%s][%s][account_id]">', $this->slug, $connection_id );
666
+ foreach ( $providers[$this->slug] as $key => $provider_details ) {
667
+ $selected = !empty( $connection['account_id'] ) ? $connection['account_id'] : '';
668
+ $output .= sprintf(
669
+ '<option value="%s" %s>%s</option>',
670
+ $key,
671
+ selected( $selected, $key, false ),
672
+ esc_html( $provider_details['label'] )
673
+ );
674
+ }
675
+ $output .= sprintf( '<option value="">%s</a>', __( 'Add New Account', 'wpforms' ) );
676
+ $output .= '</select>';
677
+
678
+ $output .= '</div>';
679
+
680
+ return $output;
681
+ }
682
+
683
+ /**
684
+ * Provider account lists HTML.
685
+ *
686
+ * @since 1.0.0
687
+ * @param string $connection_id
688
+ * @param array $connection
689
+ * @return string
690
+ */
691
+ public function output_lists( $connection_id ='', $connection = array() ) {
692
+
693
+ if ( empty( $connection_id ) || empty( $connection['account_id'] ) )
694
+ return;
695
+
696
+ $lists = $this->api_lists( $connection_id, $connection['account_id'] );
697
+ $selected = !empty( $connection['list_id'] ) ? $connection['list_id'] : '';
698
+
699
+ if ( is_wp_error( $lists ) ) {
700
+ return $lists;
701
+ }
702
+
703
+ $output = '<div class="wpforms-provider-lists wpforms-connection-block">';
704
+
705
+ $output .= sprintf( '<h4>%s</h4>', __( 'Select List', 'wpforms' ) );
706
+
707
+ $output .= sprintf( '<select name="providers[%s][%s][list_id]">', $this->slug, $connection_id );
708
+
709
+ foreach ( $lists as $list ) {
710
+ $output .= sprintf(
711
+ '<option value="%s" %s>%s</option>',
712
+ esc_attr( $list['id'] ),
713
+ selected( $selected, $list['id'], false ),
714
+ esc_attr( $list['name'] )
715
+ );
716
+ }
717
+
718
+ $output .= '</select>';
719
+
720
+ $output .='</div>';
721
+
722
+ return $output;
723
+ }
724
+
725
+ /**
726
+ * Provider account list groups HTML.
727
+ *
728
+ * @since 1.0.0
729
+ * @param string $connection_id
730
+ * @param array $connection
731
+ * @return string
732
+ */
733
+ public function output_groups( $connection_id = '', $connection = array() ) {
734
+
735
+ if ( empty( $connection_id ) || empty( $connection['account_id'] ) || empty( $connection['list_id'] ) )
736
+ return;
737
+
738
+ $groupsets = $this->api_groups( $connection_id, $connection['account_id'], $connection['list_id'] );
739
+
740
+ if ( is_wp_error( $groupsets ) )
741
+ return;
742
+
743
+ $output = '<div class="wpforms-provider-groups wpforms-connection-block">';
744
+
745
+ $output .= sprintf( '<h4>%s</h4>', __( 'Select Groups', 'wpforms' ) );
746
+
747
+ $output .= sprintf( '<p>%s</p>', __( 'We also noticed that you have some segments in your list. You can select specific list segments below if needed. This is optional.', 'wpforms' ) );
748
+
749
+ $output .= '<div class="wpforms-provider-groups-list">';
750
+
751
+ foreach( $groupsets as $groupset ) {
752
+
753
+ $output .= sprintf( '<p>%s</p>', esc_html( $groupset['name'] ) );
754
+
755
+ foreach( $groupset['groups'] as $group ) {
756
+
757
+ $selected = !empty( $connection['groups'] ) && !empty( $connection['groups'][$groupset['id']] ) ? in_array( $group['name'], $connection['groups'][$groupset['id']] ) : false;
758
+
759
+ $output .= sprintf(
760
+ '<span><input id="group_%s" type="checkbox" value="%s" name="providers[%s][%s][groups][%s][%s]" %s><label for="group_%s">%s</label></span>',
761
+ esc_attr( $group['id'] ),
762
+ esc_attr( $group['name'] ),
763
+ $this->slug,
764
+ $connection_id,
765
+ $groupset['id'],
766
+ $group['id'],
767
+ checked( $selected, true, false ),
768
+ esc_attr( $group['id'] ),
769
+ esc_attr( $group['name'] )
770
+ );
771
+ }
772
+ }
773
+
774
+ $output .= '</div>';
775
+
776
+ $output .= '</div>';
777
+
778
+ return $output;
779
+ }
780
+
781
+ /**
782
+ * Provider account list fields HTML.
783
+ *
784
+ * @since 1.0.0
785
+ * @param string $connection_id
786
+ * @param array $connection
787
+ * @param mixed $form
788
+ * @return string
789
+ */
790
+ public function output_fields( $connection_id = '', $connection = array(), $form = '' ) {
791
+
792
+ if ( empty( $connection_id ) || empty( $connection['account_id'] ) || empty( $connection['list_id'] ) || empty( $form ) )
793
+ return;
794
+
795
+ $provider_fields = $this->api_fields( $connection_id, $connection['account_id'], $connection['list_id'] );
796
+ $form_fields = $this->get_form_fields( $form );
797
+
798
+ if ( is_wp_error( $provider_fields ) )
799
+ return $provider_fields;
800
+
801
+ $output = '<div class="wpforms-provider-fields wpforms-connection-block">';
802
+
803
+ $output .= sprintf( '<h4>%s</h4>', __( 'List Fields', 'wpforms' ) );
804
+
805
+ // Table with all the fields
806
+ $output .= '<table>';
807
+
808
+ $output .= sprintf( '<thead><tr><th>%s</th><th>%s</th></thead>', __( 'List Fields', 'wpforms'), __( 'Available Form Fields', 'wpforms' ) );
809
+
810
+ $output .= '<tbody>';
811
+
812
+ foreach( $provider_fields as $provider_field ) :
813
+
814
+ $output .= '<tr>';
815
+
816
+ $output .= '<td>';
817
+
818
+ $output .= esc_html( $provider_field['name'] );
819
+ if ( !empty( $provider_field['req']) && $provider_field['req'] == '1' ) {
820
+ $output .= '<span class="required">*</span>';
821
+ }
822
+
823
+ $output .= '<td>';
824
+
825
+ $output .= sprintf( '<select name="providers[%s][%s][fields][%s]">', $this->slug, $connection_id, esc_attr( $provider_field['tag'] ) );
826
+
827
+ $output .= '<option value=""></option>';
828
+
829
+ $options = $this->get_form_field_select( $form_fields, $provider_field['field_type'] );
830
+
831
+ foreach( $options as $option ) {
832
+ $value = sprintf( '%d.%s.%s', $option['id'], $option['key'], $option['provider_type'] );
833
+ $selected = !empty( $connection['fields'][$provider_field['tag']] ) ? selected( $connection['fields'][$provider_field['tag']], $value, false ) : '';
834
+ $output .= sprintf( '<option value="%s" %s>%s</option>', esc_attr( $value ), $selected, esc_html( $option['label'] ) );
835
+ }
836
+
837
+ $output .= '</select>';
838
+
839
+ $output .= '</td>';
840
+
841
+ $output .= '</tr>';
842
+
843
+ endforeach;
844
+
845
+ $output .= '</tbody>';
846
+
847
+ $output .= '</table>';
848
+
849
+ $output .= '</div>';
850
+
851
+ return $output;
852
+ }
853
+
854
+ /**
855
+ * Provider connection conditional options HTML
856
+ *
857
+ * @since 1.0.0
858
+ * @return [type]
859
+ */
860
+ public function output_conditionals( $connection_id = '', $connection = array(), $form = '' ) {
861
+
862
+ if ( empty( $connection['account_id'] ) )
863
+ return;
864
+
865
+ $form_fields = wpforms_get_form_fields( $form['id'], array( 'text', 'textarea', 'select', 'radio', 'checkbox', 'number' ) );
866
+
867
+ $output = '<div class="wpforms-provider-conditionals wpforms-connection-block">';
868
+
869
+ $output .= sprintf( '<h4>%s</h4>', __( 'Conditional Logic', 'wpforms' ) );
870
+
871
+ $output .= sprintf(
872
+ '<p><input id="%s_conditional_logic" class="toggle" type="checkbox" value="1" name="providers[%s][%s][conditional_logic]" %s><label for="%s_conditional_logic">%s</label></p>',
873
+ $connection_id,
874
+ $this->slug,
875
+ $connection_id,
876
+ checked( !empty( $connection['conditional_logic'] ) , true , false ),
877
+ $connection_id,
878
+ __( 'Enable conditional logic', 'wpforms' )
879
+ );
880
+
881
+ $style = empty( $connection['conditional_logic'] ) ? 'display:none' : '';
882
+
883
+ $output .= sprintf( '<div class="wpforms-provider-conditionals-groups" style="%s">', $style );
884
+
885
+ $output .= '<h4>' . __( 'Process this form if', 'wpforms' ) . '</h4>';
886
+
887
+ if ( empty( $connection['conditionals'] ) ){
888
+ $connection['conditionals'][0][0] = array();
889
+ }
890
+
891
+ foreach ( $connection['conditionals'] as $group_id => $group ) :
892
+
893
+ $output .= '<div class="wpforms-provider-conditionals-group">';
894
+
895
+ $output .='<table><tbody>';
896
+
897
+ foreach ( $group as $rule_id => $rule ) :
898
+
899
+ $output .= '<tr class="wpforms-provider-conditionals-group-row">';
900
+
901
+ // Fields
902
+ $output .= '<td class="field">';
903
+
904
+ $output .= sprintf(
905
+ '<select name="providers[%s][%s][conditionals][%d][%d][field]" data-provider="%s" data-connectionid="%s" data-groupid="%d" data-ruleid="%d" class="wpforms-provider-conditionals-field">',
906
+ $this->slug,
907
+ $connection_id,
908
+ $group_id,
909
+ $rule_id,
910
+ $this->slug,
911
+ $connection_id,
912
+ $group_id,
913
+ $rule_id
914
+ );
915
+
916
+ $output .= '<option value="">' . __( '-- Select field --', 'wpforms' ) . '</option>';
917
+
918
+ foreach( $form_fields as $form_field ) {
919
+ $selected = !empty( $rule['field'] ) ? $rule['field'] : false;
920
+ $selected = selected( $selected, $form_field['id'], false );
921
+ $output .= sprintf( '<option value="%s" %s>%s</option>', absint( $form_field['id'] ), $selected, esc_html( $form_field['label'] ) );
922
+ }
923
+
924
+ $output .= '</select>';
925
+
926
+ $output .= '</td>';
927
+
928
+ // Operator
929
+ $output .= '<td class="operator">';
930
+
931
+ $output .= sprintf( '<select name="providers[%s][%s][conditionals][%s][%s][operator]" class="wpforms-provider-conditionals-operator">', $this->slug, $connection_id, $group_id, $rule_id );
932
+ $operator = !empty( $rule['operator'] ) ? $rule['operator'] : false;
933
+ $output .= sprintf( '<option value="==" %s>%s</option>', selected( $operator, '==', false ), __( 'is', 'wpforms' ) );
934
+ $output .= sprintf( '<option value="!=" %s>%s</option>', selected( $operator, '!=', false ), __( 'is not', 'wpforms' ) );
935
+ $output .= '</select>';
936
+
937
+ $output .= '</td>';
938
+
939
+ // Values
940
+ $output .= '<td class="value">';
941
+
942
+ if ( !empty( $rule['field'] ) ) {
943
+
944
+ if ( in_array( $form_fields[$rule['field']]['type'], array( 'text', 'textarea') ) ) {
945
+
946
+ $output .= sprintf( '<input type="text" name="providers[%s][%s][conditionals][%s][%s][value]" value="%s" class="wpforms-provider-conditionals-value">', $this->slug, $connection_id, $group_id, $rule_id, esc_attr($rule['value'] ) );
947
+
948
+ } else {
949
+ $output .= sprintf( '<select name="providers[%s][%s][conditionals][%s][%s][value]" class="wpforms-provider-conditionals-value">', $this->slug, $connection_id, $group_id, $rule_id );
950
+ $output .= '<option value="">' . __( '-- Select Choice --', 'wpforms' ) . '</option>';
951
+ foreach( $form_fields[$rule['field']]['choices'] as $option_id => $option ) {
952
+ $value = !empty( $rule['value'] ) ? $rule['value'] : '';
953
+ $selected = selected( $option_id, $rule['value'], false );
954
+ $output .= sprintf( '<option value="%s" %s>%s</option>', $option_id, $selected, esc_html( $option['label'] ) );
955
+ }
956
+ $output .= '</select>';
957
+ }
958
+
959
+ } else {
960
+ $output .= '<select></select>';
961
+ }
962
+
963
+ $output .= '</td>';
964
+
965
+ // Actions
966
+ $output .= '<td class="actions">';
967
+
968
+ $output .= sprintf( '<button class="wpforms-provider-conditionals-rule-add">%s</button>', __( 'AND', 'wpforms') );
969
+ $output .= '<button class="wpforms-provider-conditionals-rule-delete"><i class="fa fa-minus-circle"></i></button>';
970
+
971
+ $output .= '</td>';
972
+
973
+ $output .= '</tr>';
974
+
975
+ endforeach;
976
+
977
+ $output .= '</tbody></table>';
978
+
979
+ $output .= '<h5>or</h5>';
980
+
981
+ $output .= '</div>';
982
+
983
+ endforeach;
984
+
985
+ $output .= '<button class="wpforms-provider-conditionals-groups-add">' . __( 'Add rule group', 'wpforms' ) . '</button>';
986
+
987
+ $output .= '</div>';
988
+
989
+ $output .= '</div>';
990
+
991
+ return $output;
992
+ }
993
+
994
+
995
+ /**
996
+ * Provider account list options HTML.
997
+ *
998
+ * @since 1.0.0
999
+ * @param string $connection_id
1000
+ * @param array $connection
1001
+ * @param mixed $form
1002
+ * @return string
1003
+ */
1004
+ public function output_options( $connection_id = '', $connection = array() ) {
1005
+ }
1006
+
1007
+ //************************************************************************//
1008
+ //
1009
+ // Builder methods - these methods _build_ the Builder.
1010
+ //
1011
+ //************************************************************************//
1012
+
1013
+ /**
1014
+ * Fetch and store the current form data when in the builder.
1015
+ *
1016
+ * @since 1.2.3
1017
+ */
1018
+ public function builder_form_data() {
1019
+
1020
+ if ( !empty( $_GET['form_id'] ) ) {
1021
+ $this->form_data = wpforms()->form->get( absint( $_GET['form_id'] ), array( 'content_only' => true ) );
1022
+ }
1023
+ }
1024
+
1025
+ /**
1026
+ * Display content inside the panel content area.
1027
+ *
1028
+ * @since 1.0.0
1029
+ */
1030
+ public function builder_content() {
1031
+
1032
+ $form_data = $this->form_data;
1033
+ $providers = get_option( 'wpforms_providers' );
1034
+
1035
+ if ( !empty( $form_data['providers'][$this->slug] ) && !empty( $providers[$this->slug] ) ) {
1036
+
1037
+ foreach( $form_data['providers'][$this->slug] as $connection_id => $connection ) {
1038
+
1039
+ foreach( $providers[$this->slug] as $account_id => $connections ) {
1040
+
1041
+ if ( !empty( $connection['account_id'] ) && $connection['account_id'] == $account_id ) {
1042
+
1043
+ echo $this->output_connection( $connection_id, $connection, $form_data );
1044
+ }
1045
+ }
1046
+ }
1047
+ }
1048
+ }
1049
+
1050
+ /**
1051
+ * Display content inside the panel sidebar area.
1052
+ *
1053
+ * @since 1.0.0
1054
+ */
1055
+ public function builder_sidebar() {
1056
+
1057
+ $form_data = $this->form_data;
1058
+ $configured = !empty( $form_data['providers'][$this->slug] ) ? 'configured' : '';
1059
+ $configured = apply_filters( 'wpforms_providers_' . $this->slug . '_configured', $configured );
1060
+
1061
+ echo '<a href="#" class="wpforms-panel-sidebar-section icon ' . $configured . ' wpforms-panel-sidebar-section-' . esc_attr( $this->slug ) . '" data-section="' . esc_attr( $this->slug ) . '">';
1062
+
1063
+ echo '<img src="' . esc_url( $this->icon ) . '">';
1064
+
1065
+ echo esc_html( $this->name );
1066
+
1067
+ echo '<i class="fa fa-angle-right wpforms-toggle-arrow"></i>';
1068
+
1069
+ if ( !empty( $configured ) ) {
1070
+ echo '<i class="fa fa-check-circle-o"></i>';
1071
+ }
1072
+
1073
+ echo '</a>';
1074
+ }
1075
+
1076
+ /**
1077
+ * Wraps the builder content with the required markup.
1078
+ *
1079
+ * @since 1.0.0
1080
+ */
1081
+ public function builder_output() {
1082
+ ?>
1083
+ <div class="wpforms-panel-content-section wpforms-panel-content-section-<?php echo $this->slug; ?>" id="<?php echo $this->slug; ?>-provider">
1084
+
1085
+ <?php $this->builder_output_before(); ?>
1086
+
1087
+ <div class="wpforms-panel-content-section-title">
1088
+
1089
+ <?php echo $this->name; ?>
1090
+
1091
+ <button class="wpforms-provider-connections-add" data-form_id="<?php echo absint( $_GET['form_id'] ); ?>" data-provider="<?php echo $this->slug; ?>" data-type="<?php echo esc_attr( strtolower( $this->type ) ); ?>"><?php _e( 'Add New', 'wpforms' ); ?> <?php echo esc_html( $this->type ); ?></button>
1092
+
1093
+ </div>
1094
+
1095
+ <div class="wpforms-provider-connections-wrap wpforms-clear">
1096
+
1097
+ <div class="wpforms-provider-connections">
1098
+
1099
+ <?php $this->builder_content(); ?>
1100
+
1101
+ </div>
1102
+
1103
+ </div>
1104
+
1105
+ <?php $this->builder_output_after(); ?>
1106
+
1107
+ </div>
1108
+ <?php
1109
+ }
1110
+
1111
+ /**
1112
+ * Optionally output content before the main builder output.
1113
+ *
1114
+ * @since 1.3.6
1115
+ */
1116
+ public function builder_output_before() {
1117
+ }
1118
+
1119
+ /**
1120
+ * Optionally output content after the main builder output.
1121
+ *
1122
+ * @since 1.3.6
1123
+ */
1124
+ public function builder_output_after() {
1125
+ }
1126
+
1127
+ //************************************************************************//
1128
+ //
1129
+ // Integrations tab methods - these methods relate to the settings page.
1130
+ //
1131
+ //************************************************************************//
1132
+
1133
+ /**
1134
+ * Form fields to add a new provider account.
1135
+ *
1136
+ * @since 1.0.0
1137
+ */
1138
+ public function integrations_tab_new_form() {
1139
+
1140
+ }
1141
+
1142
+ /**
1143
+ * AJAX to disconnect a provider from the settings integrations tab.
1144
+ *
1145
+ * @since 1.0.0
1146
+ */
1147
+ public function integrations_tab_disconnect() {
1148
+
1149
+ // Run a security check
1150
+ check_ajax_referer( 'wpforms-settings', 'nonce' );
1151
+
1152
+ // Check for permissions
1153
+ if ( !current_user_can( apply_filters( 'wpforms_manage_cap', 'manage_options' ) ) ) {
1154
+ wp_send_json_error( array( 'error' => __( 'You do not have permission', 'wpforms' ) ) );
1155
+ }
1156
+
1157
+ if ( empty( $_POST['provider'] ) || empty( $_POST['key'] ) ) {
1158
+ wp_send_json_error( array( 'error' => __( 'Missing data', 'wpforms' ) ) );
1159
+ }
1160
+
1161
+ $providers = get_option( 'wpforms_providers', false );
1162
+
1163
+ if ( !empty( $providers[$_POST['provider']][$_POST['key']] ) ) {
1164
+
1165
+ unset( $providers[$_POST['provider']][$_POST['key']] );
1166
+ update_option( 'wpforms_providers', $providers );
1167
+ wp_send_json_success();
1168
+
1169
+ } else {
1170
+ wp_send_json_error( array( 'error' => __( 'Connection missing', 'wpforms' ) ) );
1171
+ }
1172
+ }
1173
+
1174
+ /**
1175
+ * AJAX to add a provider from the settings integrations tab.
1176
+ *
1177
+ * @since 1.0.0
1178
+ */
1179
+ public function integrations_tab_add() {
1180
+
1181
+ if ( $_POST['provider'] != $this->slug )
1182
+ return;
1183
+
1184
+ // Run a security check
1185
+ check_ajax_referer( 'wpforms-settings', 'nonce' );
1186
+
1187
+ // Check for permissions
1188
+ if ( !current_user_can( apply_filters( 'wpforms_manage_cap', 'manage_options' ) ) ) {
1189
+ wp_send_json_error( array( 'error' => __( 'You do not have permission', 'wpforms' ) ) );
1190
+ }
1191
+
1192
+ if ( empty( $_POST['data'] ) ) {
1193
+ wp_send_json_error( array( 'error' => __( 'Missing data', 'wpforms' ) ) );
1194
+ }
1195
+
1196
+ $data = wp_parse_args( $_POST['data'], array() );
1197
+ $auth = $this->api_auth( $data, '' );
1198
+
1199
+ if ( is_wp_error( $auth ) ) {
1200
+
1201
+ wp_send_json_error( array( 'error' => 'Could not connect to the provider.' ) );
1202
+
1203
+ } else {
1204
+
1205
+ $account = '<li>';
1206
+ $account .= '<span class="label">' . sanitize_text_field( $data['label'] ) . '</span>';
1207
+ $account .= '<span class="date">' . __( 'Connected on: ', 'wpforms' ) . date( get_option( 'date_format', time() ) ) . '</span>';
1208
+ $account .= '<a href="#" data-provider="' . $this->slug . '" data-key="' . esc_attr( $auth ) . '">' . __( 'Disconnect ', 'wpforms' ) . '</a>';
1209
+ $account .= '</li>';
1210
+
1211
+ wp_send_json_success( array( 'html' => $account ) );
1212
+ }
1213
+ }
1214
+
1215
+
1216
+ /**
1217
+ * Add provider to the Settings Integrations tab
1218
+ *
1219
+ * @since 1.0.0
1220
+ * @param array $active
1221
+ * @param array $settings
1222
+ */
1223
+ public function integrations_tab_options( $active, $settings ) {
1224
+
1225
+ $slug = esc_html( $this->slug );
1226
+ $name = esc_html( $this->name );
1227
+ $connected = !empty( $active[$this->slug] );
1228
+ $accounts = !empty( $settings[$this->slug] ) ? $settings[$this->slug] : '';
1229
+ $class = $connected && $accounts ? 'connected' : '';
1230
+ $arrow = 'right';
1231
+
1232
+ // This lets us highlight a specific service by a special link
1233
+ if ( !empty( $_GET['wpforms-integration'] ) ) {
1234
+ if ( $this->slug == $_GET['wpforms-integration'] ) {
1235
+ $class .= ' focus-in';
1236
+ $arrow = 'down';
1237
+ } else {
1238
+ $class .= ' focus-out';
1239
+ }
1240
+ }
1241
+ ?>
1242
+
1243
+ <div id="wpforms-integration-<?php echo $slug; ?>" class="wpforms-settings-provider wpforms-clear <?php echo $slug; ?> <?php echo $class; ?>">
1244
+
1245
+ <div class="wpforms-settings-provider-header wpforms-clear" data-provider="<?php echo $slug; ?>">
1246
+
1247
+ <div class="wpforms-settings-provider-logo">
1248
+ <i title="Show Accounts" class="fa fa-chevron-<?php echo $arrow; ?>"></i>
1249
+ <img src="<?php echo $this->icon; ?>">
1250
+ </div>
1251
+
1252
+ <div class="wpforms-settings-provider-info">
1253
+ <h3><?php echo $name; ?></h3>
1254
+ <p><?php printf( __( 'Integrate %s with WPForms', 'wpforms' ), $name ); ?></p>
1255
+ <span class="connected-indicator green"><i class="fa fa-check-circle-o"></i> <?php _e( 'Connected', 'wpforms' ); ?></span>
1256
+ </div>
1257
+
1258
+ </div>
1259
+
1260
+ <div class="wpforms-settings-provider-accounts" id="provider-<?php echo $slug; ?>">
1261
+
1262
+ <div class="wpforms-settings-provider-accounts-list">
1263
+ <ul>
1264
+ <?php
1265
+ if ( !empty( $accounts ) ) {
1266
+ foreach ( $accounts as $key => $account ) {
1267
+ echo '<li>';
1268
+ echo '<span class="label">' . esc_html( $account['label'] ) . '</span>';
1269
+ echo '<span class="date">' . __( 'Connected on: ', 'wpforms' ) . date( get_option( 'date_format', $account['date'] ) ) . '</span>';
1270
+ echo '<a href="#" data-provider="' . $slug . '" data-key="' . $key . '">' . __( 'Disconnect ', 'wpforms' ) . '</a>';
1271
+ echo '</li>';
1272
+ }
1273
+ }
1274
+ ?>
1275
+ </ul>
1276
+ </div>
1277
+
1278
+ <p class="wpforms-settings-provider-accounts-toggle">
1279
+ <a class="button button-secondary" href="#" data-provider="<?php echo $slug; ?>"><i class="fa fa-plus"></i> <?php _e( 'Add New Account', 'wpforms' ); ?></a>
1280
+ </p>
1281
+
1282
+ <div class="wpforms-settings-provider-accounts-connect">
1283
+
1284
+ <form>
1285
+ <p><?php _e( 'Please fill out all of the fields below to add your new provider account.', 'wpforms' ); ?></span></p>
1286
+
1287
+ <p class="wpforms-settings-provider-accounts-connect-fields">
1288
+ <?php $this->integrations_tab_new_form(); ?>
1289
+ </p>
1290
+
1291
+ <p><button type="submit" class="button button-primary wpforms-settings-provider-connect" data-provider="<?php echo $slug; ?>" title="Connect to <?php echo $name; ?>"><?php _e( 'Connect to', 'wpforms' ); ?> <?php echo $name; ?></button> <i class="fa fa-cog fa-spin"></i></p>
1292
+ </form>
1293
+ </div>
1294
+
1295
+ </div>
1296
+
1297
+ </div>
1298
+ <?php
1299
+ }
1300
+
1301
+ /**
1302
+ * Error wrapper for WP_Error.
1303
+ *
1304
+ * @since 1.0.0
1305
+ * @param string $id
1306
+ * @param string $message
1307
+ * @return object
1308
+ */
1309
+ public function error( $message = '', $parent = '0' ) {
1310
+
1311
+ return new WP_Error( $this->slug . '-error', $message );
1312
+ }
1313
+ }
includes/providers/class-constant-contact.php ADDED
@@ -0,0 +1,852 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Constant Contact integration.
4
+ *
5
+ * @package WPForms
6
+ * @author WPForms
7
+ * @since 1.3.6
8
+ * @license GPL-2.0+
9
+ * @copyright Copyright (c) 2017, WPForms LLC
10
+ */
11
+ class WPForms_Constant_Contact extends WPForms_Provider {
12
+
13
+ /**
14
+ * Provider access token.
15
+ *
16
+ * @since 1.3.6
17
+ * @var string
18
+ */
19
+ public $access_token;
20
+
21
+ /**
22
+ * Provider API key.
23
+ *
24
+ * @since 1.3.6
25
+ * @var string
26
+ */
27
+ public $api_key = 'c58xq3r27udz59h9rrq7qnvf';
28
+
29
+ /**
30
+ * Sign up link.
31
+ *
32
+ * @since 1.3.6
33
+ * @var string
34
+ */
35
+ public $sign_up = 'https://constant-contact.evyy.net/c/11535/341874/3411?sharedid=wpforms';
36
+
37
+ /**
38
+ * Initialize.
39
+ *
40
+ * @since 1.3.6
41
+ */
42
+ public function init() {
43
+
44
+ $this->version = '1.3.6';
45
+ $this->name = 'Constant Contact';
46
+ $this->slug = 'constant-contact';
47
+ $this->priority = 14;
48
+ $this->icon = WPFORMS_PLUGIN_URL . 'assets/images/icon-provider-constant-contact.png';
49
+
50
+ if ( is_admin() ) {
51
+ // Admin notice requesting connecting
52
+ add_action( 'admin_notices', array( $this, 'connect_request' ) );
53
+ add_action( 'wp_ajax_wpforms_constant_contact_dismiss', array( $this, 'connect_dismiss' ) );
54
+ add_action( 'wpforms_admin_page', array( $this, 'learn_more_page' ) );
55
+
56
+ // Provide option to override sign up link
57
+ $sign_up = get_option( 'wpforms_constant_contact_signup', false );
58
+ if ( $sign_up ) {
59
+ $this->sign_up = esc_html( $sign_up );
60
+ }
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Process and submit entry to provider.
66
+ *
67
+ * @since 1.3.6
68
+ * @param array $fields
69
+ * @param array $entry
70
+ * @param array $form_data
71
+ */
72
+ public function process_entry( $fields, $entry, $form_data, $entry_id = 0 ) {
73
+
74
+ // Only run if this form has a connections for this provider
75
+ if ( empty( $form_data['providers'][$this->slug] ) )
76
+ return;
77
+
78
+ $providers = get_option( 'wpforms_providers' );
79
+ $results = array();
80
+
81
+ // Fire for each connection ------------------------------------------//
82
+
83
+ foreach ( $form_data['providers'][$this->slug] as $connection ) :
84
+
85
+ // Before proceeding make sure required fields are configured
86
+ if ( empty( $connection['fields']['email'] ) ) {
87
+ continue;
88
+ }
89
+
90
+ // Setup basic data
91
+ $full_name = '';
92
+ $list_id = $connection['list_id'];
93
+ $account_id = $connection['account_id'];
94
+ $email_data = explode( '.', $connection['fields']['email'] );
95
+ $email_id = $email_data[0];
96
+ $email = $fields[$email_id]['value'];
97
+ $data = array();
98
+
99
+ $this->api_connect( $account_id );
100
+
101
+ // Email is required and Access token are required
102
+ if ( empty( $email ) || empty( $this->access_token ) ) {
103
+ continue;
104
+ }
105
+
106
+ // Check for conditionals
107
+ $pass = $this->process_conditionals( $fields, $entry, $form_data, $connection );
108
+ if ( !$pass ) {
109
+ wpforms_log(
110
+ __( 'Constant Contact Subscription stopped by conditional logic', 'wpforms' ),
111
+ $fields,
112
+ array(
113
+ 'type' => array( 'provider', 'conditional_logic' ),
114
+ 'parent' => $entry_id,
115
+ 'form_id' => $form_data['id'],
116
+ )
117
+ );
118
+ continue;
119
+ }
120
+
121
+ // Check to see if the lead already exists in Constant Contact.
122
+ $response = wp_remote_get( 'https://api.constantcontact.com/v2/contacts?api_key=' . $this->api_key . '&access_token=' . $this->access_token . '&email=' . $email, array( 'sslverify' => false ) );
123
+ $contact = json_decode( wp_remote_retrieve_body( $response ), true );
124
+
125
+ // Return early if there was a problem.
126
+ if ( isset( $contact['error_key'] ) ) {
127
+ wpforms_log(
128
+ __( 'Constant Contact API Error', 'wpforms' ),
129
+ $contact->get_error_message(),
130
+ array(
131
+ 'type' => array( 'provider', 'error' ),
132
+ 'parent' => $entry_id,
133
+ 'form_id' => $form_data['id'],
134
+ )
135
+ );
136
+ continue;
137
+ }
138
+
139
+ // Setup Merge Vars ---------------------------------------------//
140
+ $merge_vars = array();
141
+
142
+ foreach( $connection['fields'] as $name => $merge_var ) {
143
+
144
+ // Don't include Email or Full name fields
145
+ if ( 'email' == $name ) {
146
+ continue;
147
+ }
148
+
149
+ // Check if merge var is mapped
150
+ if ( empty( $merge_var ) ) {
151
+ continue;
152
+ }
153
+
154
+ $merge_var = explode( '.', $merge_var );
155
+ $id = $merge_var[0];
156
+ $key = !empty( $merge_var[1] ) ? $merge_var[1] : 'value';
157
+ $type = !empty( $merge_var[2] ) ? $merge_var[2] : 'text';
158
+
159
+ // Check if mapped form field has a value
160
+ if ( empty( $fields[$id][$key] ) ) {
161
+ continue;
162
+ }
163
+
164
+ $value = $fields[$id][$key];
165
+
166
+ // Constant Contact doesn't native URL field so it has to be
167
+ // stored in a custom field.
168
+ if ( 'url' == $name ) {
169
+ $merge_vars['custom_fields'] = array(
170
+ array(
171
+ 'name' => 'custom_field_1',
172
+ 'value' => $value,
173
+ )
174
+ );
175
+ continue;
176
+ }
177
+
178
+ // Constant Contact stores name in two fields, so we have to
179
+ // separate it.
180
+ if ( 'full_name' == $name ) {
181
+ $names = explode( ' ', $value );
182
+ if ( !empty( $names[0] ) ) {
183
+ $merge_vars['first_name'] = $names[0];
184
+ }
185
+ if ( !empty( $names[1] ) ) {
186
+ $merge_vars['last_name'] = $names[1];
187
+ }
188
+ continue;
189
+ }
190
+
191
+ // Constant Contact stores address in multiple fields, so we
192
+ // have to separate it.
193
+ if ( 'address' == $name ) {
194
+
195
+ // Only support Address fields
196
+ if ( 'address' != $fields[$id]['type'] ) {
197
+ continue;
198
+ }
199
+
200
+ // Postal code may be in extended US format
201
+ $postal = array( 'code' => '', 'subcode' => '' );
202
+ if ( !empty( $fields[$id]['postal'] ) ) {
203
+ $p = explode( '-', $fields[$id]['postal'] );
204
+ $postal['code'] = !empty( $p[0] ) ? $p[0] : '';
205
+ $postal['subcode'] = !empty( $p[1] ) ? $p[1] : '';
206
+ }
207
+
208
+ $merge_vars['addresses'] = array(
209
+ array(
210
+ 'address_type' => 'BUSINESS',
211
+ 'city' => !empty( $fields[$id]['city'] ) ? $fields[$id]['city'] : '',
212
+ 'country_code' => !empty( $fields[$id]['country'] ) ? $fields[$id]['country'] : '',
213
+ 'line1' => !empty( $fields[$id]['address1'] ) ? $fields[$id]['address1'] : '',
214
+ 'line2' => !empty( $fields[$id]['address2'] ) ? $fields[$id]['address2'] : '',
215
+ 'postal_code' => $postal['code'],
216
+ 'state' => !empty( $fields[$id]['state'] ) ? $fields[$id]['state'] : '',
217
+ 'sub_postal_code' => $postal['subcode'],
218
+ ),
219
+ );
220
+ continue;
221
+ }
222
+
223
+ $merge_vars[$name] = $value;
224
+ }
225
+
226
+ // Process in API ------------------------------------------------//
227
+
228
+ // If we have a previous contact, only update the list association.
229
+ if ( ! empty( $contact['results'] ) ) {
230
+
231
+ $data = $contact['results'][0];
232
+
233
+ // Check if they are already assigned to lists.
234
+ if ( ! empty( $data['lists'] ) ) {
235
+
236
+ foreach ( $data['lists'] as $list ) {
237
+
238
+ // If they are already assigned to this list, return early.
239
+ if ( isset( $list['id'] ) && $list_id == $list['id'] ) {
240
+ return true;
241
+ }
242
+ }
243
+
244
+ // Otherwise, add them to the list.
245
+ $data['lists'][ count( $data['lists'] ) ] = array(
246
+ 'id' => $list_id,
247
+ 'status' => 'ACTIVE',
248
+ );
249
+
250
+ } else {
251
+
252
+ // Add the contact to the list.
253
+ $data['lists'][0] = array(
254
+ 'id' => $list_id,
255
+ 'status' => 'ACTIVE',
256
+ );
257
+ }
258
+
259
+ // Combine merge vars into data before sending
260
+ $data = array_merge( $data, $merge_vars );
261
+
262
+ // Args to use
263
+ $args = array(
264
+ 'body' => json_encode( $data ),
265
+ 'method' => 'PUT',
266
+ 'sslverify' => false,
267
+ 'headers' => array(
268
+ 'Content-Type' => 'application/json',
269
+ ),
270
+ );
271
+
272
+ $update = wp_remote_request( 'https://api.constantcontact.com/v2/contacts/' . $data['id'] . '?api_key=' . $this->api_key . '&access_token=' . $this->access_token . '&action_by=ACTION_BY_VISITOR', $args );
273
+ $res = json_decode( wp_remote_retrieve_body( $update ), true );
274
+
275
+ } else {
276
+ // Add a new contact.
277
+ $data = array(
278
+ 'email_addresses' => array( array( 'email_address' => $email ) ),
279
+ 'lists' => array( array( 'id' => $list_id ) ),
280
+ );
281
+
282
+ // Combine merge vars into data before sending
283
+ $data = array_merge( $data, $merge_vars );
284
+
285
+ // Args to use
286
+ $args = array(
287
+ 'body' => json_encode( $data ),
288
+ 'sslverify' => false,
289
+ 'headers' => array(
290
+ 'Content-Type' => 'application/json',
291
+ ),
292
+ );
293
+
294
+ $add = wp_remote_post( 'https://api.constantcontact.com/v2/contacts?api_key=' . $this->api_key . '&access_token=' . $this->access_token . '&action_by=ACTION_BY_VISITOR', $args );
295
+ $res = json_decode( wp_remote_retrieve_body( $add ), true );
296
+ }
297
+
298
+ // Check for errors
299
+ if ( isset( $res['error_key'] ) ) {
300
+ wpforms_log(
301
+ __( 'Constant Contact API Error', 'wpforms' ),
302
+ $res->get_error_message(),
303
+ array(
304
+ 'type' => array( 'provider', 'error' ),
305
+ 'parent' => $entry_id,
306
+ 'form_id' => $form_data['id'],
307
+ )
308
+ );
309
+ }
310
+
311
+ endforeach;
312
+ }
313
+
314
+ //************************************************************************//
315
+ //
316
+ // API methods - these methods interact directly with the provider API.
317
+ //
318
+ //************************************************************************//
319
+
320
+ /**
321
+ * Authenticate with the API.
322
+ *
323
+ * @since 1.3.6
324
+ * @param array $data
325
+ * @param string $form_id
326
+ * @return mixed id or error object
327
+ */
328
+ public function api_auth( $data = array(), $form_id = '' ) {
329
+
330
+ $id = uniqid();
331
+ $providers = get_option( 'wpforms_providers', array() );
332
+ $providers[$this->slug][$id] = array(
333
+ 'access_token' => sanitize_text_field( $data['authcode'] ),
334
+ 'label' => sanitize_text_field( $data['label'] ),
335
+ 'date' => time(),
336
+ );
337
+ update_option( 'wpforms_providers', $providers );
338
+
339
+ return $id;
340
+ }
341
+
342
+ /**
343
+ * Establish connection object to API.
344
+ *
345
+ * @since 1.3.6 [<description>]
346
+ * @param string $account_id
347
+ * @return mixed array or error object
348
+ */
349
+ public function api_connect( $account_id ) {
350
+
351
+ if ( !empty( $this->api[$account_id] ) ) {
352
+ return $this->api[$account_id];
353
+ } else {
354
+ $providers = get_option( 'wpforms_providers' );
355
+ if ( !empty( $providers[$this->slug][$account_id] ) ) {
356
+ $this->api[$account_id] = true;
357
+ $this->access_token = $providers[$this->slug][$account_id]['access_token'];
358
+ } else {
359
+ return $this->error( 'API error' );
360
+ }
361
+ }
362
+ }
363
+
364
+ /**
365
+ * Retrieve provider account lists.
366
+ *
367
+ * @since 1.3.6
368
+ * @param string $connection_id
369
+ * @param string $account_id
370
+ * @return mixed array or error object
371
+ */
372
+ public function api_lists( $connection_id = '', $account_id = '' ) {
373
+
374
+ $this->api_connect( $account_id );
375
+
376
+ $request = wp_remote_get( 'https://api.constantcontact.com/v2/lists?api_key=' . $this->api_key . '&access_token=' . $this->access_token, array( 'sslverify' => false ) );
377
+ $lists = json_decode( wp_remote_retrieve_body( $request ), true );
378
+ $return = array();
379
+
380
+ if ( empty( $lists ) ) {
381
+ wpforms_log(
382
+ __( 'Constant Contact API error', 'wpforms' ),
383
+ '',
384
+ array(
385
+ 'type' => array( 'provider', 'error' ),
386
+ )
387
+ );
388
+ return $this->error( 'API list error: Constant API error' );
389
+ }
390
+
391
+ return $lists;
392
+ }
393
+
394
+ /**
395
+ * Retrieve provider account list fields.
396
+ *
397
+ * @since 1.3.6
398
+ * @param string $connection_id
399
+ * @param string $account_id
400
+ * @return mixed array or error object
401
+ */
402
+ public function api_fields( $connection_id = '', $account_id = '', $list_id = '' ) {
403
+
404
+ $provider_fields = array(
405
+ array(
406
+ 'name' => 'Email',
407
+ 'field_type' => 'email',
408
+ 'req' => '1',
409
+ 'tag' => 'email',
410
+ ),
411
+ array(
412
+ 'name' => 'Full Name',
413
+ 'field_type' => 'name',
414
+ 'tag' => 'full_name',
415
+ ),
416
+ array(
417
+ 'name' => 'First Name',
418
+ 'field_type' => 'first',
419
+ 'tag' => 'first_name',
420
+ ),
421
+ array(
422
+ 'name' => 'Last Name',
423
+ 'field_type' => 'last',
424
+ 'tag' => 'last_name',
425
+ ),
426
+ array(
427
+ 'name' => 'Phone',
428
+ 'field_type' => 'text',
429
+ 'tag' => 'work_phone',
430
+ ),
431
+ array(
432
+ 'name' => 'Website',
433
+ 'field_type' => 'text',
434
+ 'tag' => 'url',
435
+ ),
436
+ array(
437
+ 'name' => 'Address',
438
+ 'field_type' => 'address',
439
+ 'tag' => 'address',
440
+ ),
441
+ array(
442
+ 'name' => 'Job Title',
443
+ 'field_type' => 'text',
444
+ 'tag' => 'job_title',
445
+ ),
446
+ array(
447
+ 'name' => 'Company',
448
+ 'field_type' => 'text',
449
+ 'tag' => 'company_name',
450
+ ),
451
+ );
452
+
453
+ return $provider_fields;
454
+ }
455
+
456
+
457
+ //************************************************************************//
458
+ //
459
+ // Output methods - these methods generally return HTML for the builder.
460
+ //
461
+ //************************************************************************//
462
+
463
+ /**
464
+ * Provider account authorize fields HTML.
465
+ *
466
+ * @since 1.3.6
467
+ * @return string
468
+ */
469
+ public function output_auth() {
470
+
471
+ $providers = get_option( 'wpforms_providers' );
472
+ $class = !empty( $providers[$this->slug] ) ? 'hidden' : '';
473
+
474
+ $output = '<div class="wpforms-provider-account-add ' . $class . ' wpforms-connection-block">';
475
+
476
+ $output .= sprintf( '<h4>%s</h4>', __( 'Add New Account', 'wpforms' ) );
477
+
478
+ $output .= '<p>';
479
+ $output .= __( 'Please fill out all of the fields below to register your new Constant Contact account.' , 'wpforms' );
480
+ $output .= '<br><a href="https://wpforms.com/docs/how-to-connect-constant-contact-with-wpforms/" target="_blank" rel="noopener noreferrer">';
481
+ $output .= __( 'Click here for documentation on connecting WPForms with Constant Contact.', 'wpforms' );
482
+ $output .= '</a>';
483
+ $output .= '</p>';
484
+
485
+ $output .= '<p class="wpforms-alert wpforms-alert-warning">';
486
+ $output .= __( 'Because Constant Contact requires external authentication, you will need to register WPForms with Constant Contact before you can proceed.', 'wpforms' );
487
+ $output .= '</p>';
488
+
489
+ $output .= '<p class=""><strong><a onclick="window.open(this.href,\'\',\'resizable=yes,location=no,width=750,height=500,status\'); return false" href="https://oauth2.constantcontact.com/oauth2/oauth/siteowner/authorize?response_type=code&client_id=c58xq3r27udz59h9rrq7qnvf&redirect_uri=https://wpforms.com/oauth/constant-contact/" class="btn">';
490
+ $output .= __( 'Click here to register with Constant Contact', 'wpforms' );
491
+ $output .= '</a></strong></p>';
492
+
493
+ $output .= sprintf( '<input type="text" data-name="authcode" placeholder="%s %s" class="wpforms-required">', $this->name, __( 'Authorization Code', 'wpforms' ) );
494
+
495
+ $output .= sprintf( '<input type="text" data-name="label" placeholder="%s %s" class="wpforms-required">', $this->name, __( 'Account Nickname', 'wpforms' ) );
496
+
497
+ $output .= sprintf( '<button data-provider="%s">%s</button>', $this->slug, __( 'Connect', 'wpforms' ) );
498
+
499
+ $output .= '</div>';
500
+
501
+ return $output;
502
+ }
503
+
504
+ /**
505
+ * Provider account list groups HTML.
506
+ *
507
+ * @since 1.3.6
508
+ * @param string $connection_id
509
+ * @param array $connection
510
+ * @return string
511
+ */
512
+ public function output_groups( $connection_id = '', $connection = array() ) {
513
+ // No groups or segments for this provider
514
+ return;
515
+ }
516
+
517
+ /**
518
+ * Output content after the main builder output.
519
+ *
520
+ * @since 1.3.6
521
+ */
522
+ public function builder_output_after() {
523
+
524
+ // Only display if Constant Contact account has not been setup
525
+ $providers = get_option( 'wpforms_providers', array() );
526
+
527
+ if ( !empty( $providers[$this->slug] ) ) {
528
+ return;
529
+ }
530
+ ?>
531
+ <div class="wpforms-alert wpforms-alert-info">
532
+ <p><?php _e( 'Get the most out of <strong>WPForms</strong> &mdash; use it with an active Constant Contact account.', 'wpforms' ); ?></p>
533
+ <p>
534
+ <a href="<?php echo $this->sign_up; ?>" style="margin-right: 10px;" class="button-primary" target="_blank" rel="noopener noreferrer"><?php _e( 'Try Constant Contact for Free', 'wpforms' ); ?></a>
535
+ <?php printf( __( 'Learn More about the <a href="%s" target="_blank" rel="noopener noreferrer">power of email marketing</a>', 'wpforms' ), admin_url( 'admin.php?page=wpforms-page&wpforms-page=constant-contact' ) ); ?>
536
+ </p>
537
+ </div>
538
+ <?php
539
+ }
540
+
541
+ //************************************************************************//
542
+ //
543
+ // Integrations tab methods - these methods relate to the settings page.
544
+ //
545
+ //************************************************************************//
546
+
547
+ /**
548
+ * Form fields to add a new provider account.
549
+ *
550
+ * @since 1.3.6
551
+ */
552
+ public function integrations_tab_new_form() {
553
+
554
+ $output = '<p>';
555
+ $output .= '<a href="https://wpforms.com/docs/how-to-connect-constant-contact-with-wpforms/" target="_blank" rel="noopener noreferrer">';
556
+ $output .= __( 'Click here for documentation on connecting WPForms with Constant Contact.', 'wpforms' );
557
+ $output .= '</a>';
558
+ $output .= '</p>';
559
+
560
+ $output .= '<p class="wpforms-alert wpforms-alert-warning">';
561
+ $output .= __( 'Because Constant Contact requires external authentication, you will need to register WPForms with Constant Contact before you can proceed.', 'wpforms' );
562
+ $output .= '</p>';
563
+
564
+ $output .= '<p class=""><strong><a onclick="window.open(this.href,\'\',\'resizable=yes,location=no,width=800,height=600,status\'); return false" href="https://oauth2.constantcontact.com/oauth2/oauth/siteowner/authorize?response_type=code&client_id=c58xq3r27udz59h9rrq7qnvf&redirect_uri=https://wpforms.com/oauth/constant-contact/" class="btn">';
565
+ $output .= __( 'Click here to register with Constant Contact', 'wpforms' );
566
+ $output .= '</a></strong></p>';
567
+
568
+ $output .= sprintf( '<input type="text" name="authcode" placeholder="%s %s" class="wpforms-required">', $this->name, __( 'Authorization Code', 'wpforms' ) );
569
+
570
+ $output .= sprintf( '<input type="text" name="label" placeholder="%s %s" class="wpforms-required">', $this->name, __( 'Account Nickname', 'wpforms' ) );
571
+
572
+ echo $output;
573
+ }
574
+
575
+ //************************************************************************//
576
+ //
577
+ // Other functionality.
578
+ //
579
+ //************************************************************************//
580
+
581
+ /**
582
+ * Add admin notices to connect to Constant Contact.
583
+ *
584
+ * @since 1.3.6
585
+ */
586
+ public function connect_request() {
587
+
588
+ // Only consider showing the review request to admin users
589
+ if ( ! is_super_admin() ) {
590
+ return;
591
+ }
592
+
593
+ // Don't display on WPForms admin content pages
594
+ if ( !empty( $_GET['wpforms-page'] ) ) {
595
+ return;
596
+ }
597
+
598
+ // Don't display if user is about to connect via Settings page
599
+ if ( !empty( $_GET['wpforms-integration'] ) && $this->slug == $_GET['wpforms-integration'] ) {
600
+ return;
601
+ }
602
+
603
+ // Only display the notice is the Constant Contact option is set and
604
+ // there are previous Constant Contact connections created
605
+ $cc_notice = get_option( 'wpforms_constant_contact', false );
606
+ $providers = get_option( 'wpforms_providers', array() );
607
+
608
+ if ( ! $cc_notice || !empty( $providers[$this->slug] ) ) {
609
+ return;
610
+ }
611
+
612
+ // Output the notice message.
613
+ $connect = admin_url( 'admin.php?page=wpforms-settings&wpforms-integration=constant-contact#!wpforms-tab-providers' );
614
+ $learn_more = admin_url( 'admin.php?page=wpforms-page&wpforms-page=constant-contact ');
615
+ ?>
616
+ <div class="notice notice-info is-dismissible wpforms-constant-contact-notice">
617
+ <p><?php _e( 'Get the most out of the <strong>WPForms</strong> plugin &mdash; use it with an active Constant Contact account.', 'wpforms' ); ?></p>
618
+ <p>
619
+ <a href="<?php echo $this->sign_up; ?>" class="button-primary" target="_blank" rel="noopener noreferrer"><?php _e( 'Try Constant Contact for Free', 'wpforms' ); ?></a>
620
+ <a href="<?php echo $connect; ?>" class="button-secondary"><?php _e( 'Connect your existing account', 'wpforms' ); ?></a>
621
+ <?php printf( __( 'Learn More about the <a href="%s">power of email marketing</a>', 'wpforms' ), $learn_more ); ?>
622
+ </p>
623
+ </div>
624
+ <style type="text/css">
625
+ .wpforms-constant-contact-notice {
626
+ border-left-color: #1a5285;
627
+ }
628
+ .wpforms-constant-contact-notice p:first-of-type {
629
+ margin: 16px 0 8px;
630
+ }
631
+ .wpforms-constant-contact-notice p:last-of-type {
632
+ margin: 8px 0 16px;
633
+ }
634
+ .wpforms-constant-contact-notice .button-primary,
635
+ .wpforms-constant-contact-notice .button-secondary {
636
+ display: inline-block;
637
+ margin: 0 10px 0 0;
638
+ }
639
+ </style>
640
+ <script type="text/javascript">
641
+ jQuery(function($){
642
+ $(document).on('click', '.wpforms-constant-contact-notice button', function( event ) {
643
+ event.preventDefault();
644
+ $.post( ajaxurl, { action: 'wpforms_constant_contact_dismiss' } );
645
+ $('.wpforms-constant-contact-notice').remove();
646
+ });
647
+ });
648
+ </script>
649
+ <?php
650
+ }
651
+
652
+ /**
653
+ * Dismiss the Constant Contact admin notice.
654
+ *
655
+ * @since 1.3.6
656
+ */
657
+ public function connect_dismiss() {
658
+
659
+ delete_option( 'wpforms_constant_contact' );
660
+ wp_send_json_success();
661
+ }
662
+
663
+ /**
664
+ * Constant Contact "Learn More" admin page.
665
+ *
666
+ * @since 1.3.6
667
+ */
668
+ public function learn_more_page() {
669
+
670
+ if ( empty( $_GET['page'] ) || empty( $_GET['wpforms-page'] ) || 'wpforms-page' != $_GET['page'] || 'constant-contact' != $_GET['wpforms-page'] ) {
671
+ return;
672
+ }
673
+ $more = 'http://www.wpbeginner.com/beginners-guide/why-you-should-start-building-your-email-list-right-away';
674
+ ?>
675
+ <div class="wrap about-wrap">
676
+ <h1><?php _e( 'Grow Your Website with WPForms + Email Marketing', 'wpforms' ); ?></h1>
677
+ <p><?php _e( 'Wondering if email marketing is really worth your time?', 'wpforms' ); ?></p>
678
+ <p><?php _e( 'Email is hands-down the most effective way to nurture leads and turn them into customers, with a return on investment (ROI) of <strong>$44 back for every $1 spent</strong> according to Direct Marketing Association.', 'wpforms' ); ?></p>
679
+ <p><?php _e( 'Here are 3 big reasons why every smart business in the world has an email list:', 'wpforms' ); ?></p>
680
+ <a href="<?php echo $this->sign_up; ?>" target="_blank" rel="noopener noreferrer"><img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/cc-about-logo.png" class="logo"></a>
681
+ <ol class="reasons">
682
+ <li><?php _e( '<strong>Email is still #1</strong> - At least 91% of consumers check their email on a daily basis. You get direct access to your subscribers, without having to play by social media&#39;s rules and algorithms.', 'wpforms' ); ?></li>
683
+ <li><?php _e( '<strong>You own your email list</strong> - Unlike with social media, your list is your property and no one can revoke your access to it.', 'wpforms' ); ?></li>
684
+ <li><?php _e( '<strong>Email converts</strong> - People who buy products marketed through email spend 138% more than those who don&#39;t receive email offers.', 'wpforms' ); ?></li>
685
+ </ol>
686
+ <p><?php _e( 'That&#39;s why it&#39;s crucial to start collecting email addresses and building your list as soon as possible.', 'wpforms' ); ?></p>
687
+ <p><?php printf( __( 'For more details, see this guide on <a href="%s" target="_blank" rel="noopener noreferrer">why building your email list is so important.', 'wpforms' ), $more ); ?></a></p>
688
+ <hr />
689
+ <h2><?php _e( 'You&#39;ve Already Started - Here&#39;s the Next Step (It&#39;s Easy)', 'wpforms' ); ?></h2>
690
+ <p><?php _e( 'Here are the 3 things you need to build an email list:', 'wpforms' ); ?></p>
691
+ <ol>
692
+ <li><?php _e( 'A Website or Blog', 'wpforms' ); ?> <span class="dashicons dashicons-yes"></span></li>
693
+ <li><?php _e( 'High-Converting Form Builder', 'wpforms' ); ?> <span class="dashicons dashicons-yes"></span></li>
694
+ <li><strong><?php _e( 'The Best Email Marketing Service', 'wpforms' ); ?></strong></li>
695
+ </ol>
696
+ <p><?php _e( 'With a powerful email marketing service like Constant Contact, you can instantly send out mass notifications and beautifully designed newsletters to engage your subscribers.', 'wpforms' ); ?></p>
697
+ <p><a href="<?php echo $this->sign_up; ?>" class="button" target="_blank" rel="noopener noreferrer"><?php _e( 'Get Started with Constant Contact for Free', 'wpforms' ); ?></a></p>
698
+ <p><?php _e( 'WPForms plugin makes it fast and easy to capture all kinds of visitor information right from your WordPress site - even if you don&#39;t have a Constant Contact account.', 'wpforms' ); ?></p>
699
+ <p><?php _e( 'But when you combine WPForms with Constant Contact, you can nurture your contacts and engage with them even after they leave your website. When you use Constant Contact + WPForms together, you can:', 'wpforms' ); ?></p>
700
+ <ul>
701
+ <li><?php _e( 'Seamlessly add new contacts to your email list', 'wpforms' ); ?></li>
702
+ <li><?php _e( 'Create and send professional email newsletters', 'wpforms' ); ?></li>
703
+ <li><?php _e( 'Get expert marketing and support', 'wpforms' ); ?></li>
704
+ </ul>
705
+ <p><a href="<?php echo $this->sign_up; ?>" target="_blank" rel="noopener noreferrer"><strong><?php _e( 'Try Constant Contact Today', 'wpforms' ); ?></strong></a></p>
706
+ <hr />
707
+ <h2><?php _e( 'WPForms Makes List Building Easy', 'wpforms' ); ?></h2>
708
+ <p><?php _e( 'When creating WPForms, our goal was to make a WordPress forms plugin that&#39;s both EASY and POWERFUL.', 'wpforms' ); ?></p>
709
+ <p><?php _e( 'We made the form creation process extremely intuitive, so you can create a form to start capturing emails within 5 minutes or less.', 'wpforms' ); ?></p>
710
+ <p><?php _e( 'Here&#39;s how it works.', 'wpforms' ); ?></p>
711
+ <div class="steps">
712
+ <div class="step1 step">
713
+ <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/cc-about-step1.png">
714
+ <p><?php _e( '1. Select from our pre-built templates, or create a form from scratch.', 'wpforms' ); ?></p>
715
+ </div>
716
+ <div class="step2 step">
717
+ <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/cc-about-step2.png">
718
+ <p><?php _e( '2. Drag and drop any field you want onto your signup form.', 'wpforms' ); ?></p>
719
+ </div>
720
+ <div class="step3 step">
721
+ <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/cc-about-step3.png">
722
+ <p><?php _e( '3. Connect your Constant Contact email list.', 'wpforms' ); ?></p>
723
+ </div>
724
+ <div class="step4 step">
725
+ <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/cc-about-step4.png">
726
+ <p><?php _e( '4. Add your new form to any post, page, or sidebar.', 'wpforms' ); ?></p>
727
+ </div>
728
+ </div>
729
+ <p><?php _e( 'It doesn&#39;t matter what kind of business you run, what kind of website you have, or what industry you are in - you need to start building your email list today.', 'wpforms' ); ?></p>
730
+ <p><?php _e( 'With Constant Contact + WPForms, growing your list is easy.', 'wpforms' ); ?></p>
731
+ </div>
732
+ <style type="text/css">
733
+ .notice {
734
+ display: none;
735
+ }
736
+ .about-wrap{
737
+ padding: 15px;
738
+ max-width: 970px;
739
+ }
740
+ .about-wrap h1 {
741
+ color: #1a5285;
742
+ font-size: 30px;
743
+ margin: 0 0 15px 0;
744
+ }
745
+ .about-wrap h2 {
746
+ color: #1a5285;
747
+ font-size: 26px;
748
+ margin: 0 0 15px 0;
749
+ text-align: left;
750
+ }
751
+ .about-wrap p {
752
+ font-size: 16px;
753
+ font-weight: 300;
754
+ color: #333;
755
+ margin: 1.2em 0;
756
+ }
757
+ .about-wrap ul,
758
+ .about-wrap ol {
759
+ margin: 1.6em 2.5em 2em;
760
+ line-height: 1.5;
761
+ font-size: 16px;
762
+ font-weight: 300;
763
+ }
764
+ .about-wrap ul {
765
+ list-style: disc;
766
+ }
767
+ .about-wrap li {
768
+ margin-bottom: 0.8em;
769
+ }
770
+ .about-wrap hr {
771
+ margin: 2.2em 0;
772
+ }
773
+ .about-wrap .logo {
774
+ float: right;
775
+ margin-top: 0.8em;
776
+ }
777
+ .about-wrap .reasons {
778
+ margin: 2.2em 0 2.2em 2em;
779
+ margin-right: 400px;
780
+ }
781
+ .about-wrap .reasons li {
782
+ margin-bottom: 1.4em;
783
+ }
784
+ .about-wrap .steps {
785
+ clear: both;
786
+ overflow: hidden;
787
+ }
788
+ .about-wrap .step {
789
+ width: 46%;
790
+ float: left;
791
+ }
792
+ .about-wrap .step {
793
+ margin-bottom: 1.4em;
794
+ }
795
+ .about-wrap .step2,
796
+ .about-wrap .step4 {
797
+ float: right;
798
+ }
799
+ .about-wrap .step3 {
800
+ clear: both;
801
+ }
802
+ .about-wrap .dashicons-yes {
803
+ color: #19BE19;
804
+ font-size: 26px;
805
+ }
806
+ .about-wrap .button {
807
+ background-color: #0078C3;
808
+ border: 1px solid #005990;
809
+ border-radius: 4px;
810
+ color: #fff;
811
+ font-size: 16px;
812
+ font-weight: 600;
813
+ height: auto;
814
+ line-height: 1;
815
+ margin-bottom: 10px;
816
+ padding: 14px 30px;
817
+ text-align: center;
818
+ }
819
+ .about-wrap .button:hover,
820
+ .about-wrap .button:focus {
821
+ background-color: #005990;
822
+ color: #fff
823
+ }
824
+ @media only screen and (max-width: 767px) {
825
+ .about-wrap {
826
+ padding: 0;
827
+ }
828
+ .about-wrap h1 {
829
+ font-size: 26px;
830
+ }
831
+ .about-wrap h2 {
832
+ font-size: 22px;
833
+ }
834
+ .about-wrap p {
835
+ font-size: 14px;
836
+ }
837
+ .about-wrap ul,
838
+ .about-wrap ol {
839
+ font-size: 14px;
840
+ }
841
+ .about-wrap .logo {
842
+ width: 120px;
843
+ }
844
+ .about-wrap .reasons {
845
+ margin-right: 150px;
846
+ }
847
+ }
848
+ </style>
849
+ <?php
850
+ }
851
+ }
852
+ new WPForms_Constant_Contact;
includes/templates/class-subscribe.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Scribe to Email list form template.
4
+ *
5
+ * @package WPForms
6
+ * @author WPForms
7
+ * @since 1.0.0
8
+ * @license GPL-2.0+
9
+ * @copyright Copyright (c) 2016, WPForms LLC
10
+ */
11
+ class WPForms_Template_Subscribe extends WPForms_Template {
12
+
13
+ /**
14
+ * Primary class constructor.
15
+ *
16
+ * @since 1.0.0
17
+ */
18
+ public function init() {
19
+
20
+ $this->name = __( 'Newsletter Signup Form', 'wpforms' );
21
+ $this->slug = 'subscribe';
22
+ $this->description = __( 'Add subscribers and grow your email list with this newsletter signup form. You can add and remove fields as needed.', 'wpforms' );
23
+ $this->includes = '';
24
+ $this->icon = '';
25
+ $this->modal = array(
26
+ 'title' => __( 'Don&#39;t Forget', 'wpforms' ),
27
+ 'message' => __( 'Click the marketing tab to configure your newsletter service provider', 'wpforms' ),
28
+ );
29
+ $this->data = array(
30
+ 'field_id' => '2',
31
+ 'fields' => array(
32
+ '0' => array(
33
+ 'id' => '0',
34
+ 'type' => 'name',
35
+ 'label' => __( 'Name', 'wpforms' ),
36
+ 'required' => '1',
37
+ 'size' => 'medium',
38
+ ),
39
+ '1' => array(
40
+ 'id' => '1',
41
+ 'type' => 'email',
42
+ 'label' => __( 'Email', 'wpforms' ),
43
+ 'required' => '1',
44
+ 'size' => 'medium',
45
+ ),
46
+ ),
47
+ 'settings' => array(
48
+ 'honeypot' => '1',
49
+ 'confirmation_message_scroll' => '1',
50
+ 'submit_text_processing' => __( 'Sending...', 'wpforms' ),
51
+ ),
52
+ 'meta' => array(
53
+ 'template' => $this->slug,
54
+ ),
55
+ );
56
+ }
57
+
58
+ /**
59
+ * Conditional to determine if the template informational modal screens
60
+ * should display.
61
+ *
62
+ * @since 1.0.0
63
+ * @param array $form_data
64
+ * @return boolean
65
+ */
66
+ function template_modal_conditional( $form_data ) {
67
+
68
+ // If we do not have provider data, then we can assume a provider
69
+ // method has not yet been configured, so we display the modal to
70
+ // remind the user they need to set it up for the form to work
71
+ // correctly.
72
+ if ( empty( $form_data['providers'] ) ) {
73
+ return true;
74
+ } else {
75
+ return false;
76
+ }
77
+ }
78
+ }
79
+ new WPForms_Template_Subscribe;
languages/wpforms.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the same license as the WPForms package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: WPForms 1.3.4\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wpforms\n"
7
- "POT-Creation-Date: 2017-02-09 18:10:00+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -48,7 +48,7 @@ msgstr ""
48
  msgid "taxonomy"
49
  msgstr ""
50
 
51
- #: includes/admin/builder/class-builder.php:268
52
  #: pro/includes/fields/class-date-time.php:229
53
  #: pro/includes/fields/class-date-time.php:231
54
  #: pro/includes/fields/class-date-time.php:452
@@ -56,7 +56,7 @@ msgstr ""
56
  msgid "DD"
57
  msgstr ""
58
 
59
- #: includes/admin/builder/class-builder.php:269
60
  #: pro/includes/fields/class-date-time.php:228
61
  #: pro/includes/fields/class-date-time.php:232
62
  #: pro/includes/fields/class-date-time.php:433
@@ -65,218 +65,218 @@ msgstr ""
65
  msgid "MM"
66
  msgstr ""
67
 
68
- #: includes/admin/builder/class-builder.php:270
69
  msgid ""
70
  "The {source} {type} contains over {limit} items ({total}). This may make the "
71
  "field difficult for your vistors to use and/or cause the form to be slow."
72
  msgstr ""
73
 
74
- #: includes/admin/builder/class-builder.php:271
75
  #: includes/admin/class-editor.php:96
76
  #: pro/includes/admin/entries/class-entries.php:994
77
  msgid "Cancel"
78
  msgstr ""
79
 
80
- #: includes/admin/builder/class-builder.php:272
81
  msgid "OK"
82
  msgstr ""
83
 
84
- #: includes/admin/builder/class-builder.php:273
85
  #: includes/admin/class-editor.php:70
86
  msgid "Close"
87
  msgstr ""
88
 
89
- #: includes/admin/builder/class-builder.php:274
90
  msgid ""
91
  "Due to form changes, conditional logic rules have been removed or updated:"
92
  msgstr ""
93
 
94
- #: includes/admin/builder/class-builder.php:275
95
  #: pro/includes/admin/entries/class-entries-table.php:176
96
  msgid "Field"
97
  msgstr ""
98
 
99
- #: includes/admin/builder/class-builder.php:276
100
  msgid "Field Locked"
101
  msgstr ""
102
 
103
- #: includes/admin/builder/class-builder.php:277
104
  msgid "This field cannot be deleted or duplicated."
105
  msgstr ""
106
 
107
- #: includes/admin/builder/class-builder.php:278
108
  msgid "Available Fields"
109
  msgstr ""
110
 
111
- #: includes/admin/builder/class-builder.php:279
112
  msgid "No fields available"
113
  msgstr ""
114
 
115
- #: includes/admin/builder/class-builder.php:280
116
  msgid "Heads up!"
117
  msgstr ""
118
 
119
- #: includes/admin/builder/class-builder.php:282
120
  msgid "No email fields"
121
  msgstr ""
122
 
123
- #: includes/admin/builder/class-builder.php:283
124
  msgid "Are you sure you want to delete this notification?"
125
  msgstr ""
126
 
127
- #: includes/admin/builder/class-builder.php:284
128
  msgid "Enter a notification name"
129
  msgstr ""
130
 
131
- #: includes/admin/builder/class-builder.php:285
132
  msgid "Eg: User Confirmation"
133
  msgstr ""
134
 
135
- #: includes/admin/builder/class-builder.php:286
136
  msgid "You must provide a notification name"
137
  msgstr ""
138
 
139
- #: includes/admin/builder/class-builder.php:287
140
  msgid ""
141
  "Form must contain one notification. To disable all notifications use the "
142
  "setting Notifications dropdown setting."
143
  msgstr ""
144
 
145
- #: includes/admin/builder/class-builder.php:288
146
  #: lite/includes/admin/class-settings.php:131
147
  #: pro/includes/admin/class-settings.php:135
148
  msgid "Saving ..."
149
  msgstr ""
150
 
151
- #: includes/admin/builder/class-builder.php:289
152
  msgid "Saved!"
153
  msgstr ""
154
 
155
- #: includes/admin/builder/class-builder.php:290
156
  msgid "Save and Exit"
157
  msgstr ""
158
 
159
- #: includes/admin/builder/class-builder.php:291
160
- #: includes/admin/builder/class-builder.php:354
161
  msgid "Loading"
162
  msgstr ""
163
 
164
- #: includes/admin/builder/class-builder.php:297
165
  msgid "Use Template"
166
  msgstr ""
167
 
168
- #: includes/admin/builder/class-builder.php:298
169
  msgid ""
170
  "Changing templates on an existing form will DELETE existing form fields. Are "
171
  "you sure you want apply the new template?"
172
  msgstr ""
173
 
174
- #: includes/admin/builder/class-builder.php:299
175
  msgid ""
176
  "You are almost done. To embed this form on your site, please paste the "
177
  "following shortcode inside a post or page."
178
  msgstr ""
179
 
180
- #: includes/admin/builder/class-builder.php:300
181
  msgid "Or you can follow the instructions in this video."
182
  msgstr ""
183
 
184
- #: includes/admin/builder/class-builder.php:301
185
- #: includes/admin/builder/class-builder.php:404
186
  msgid "Exit"
187
  msgstr ""
188
 
189
- #: includes/admin/builder/class-builder.php:303
190
  msgid "If you exit without saving, your changes will be lost."
191
  msgstr ""
192
 
193
- #: includes/admin/builder/class-builder.php:304
194
  msgid "Are you sure you want to delete this field?"
195
  msgstr ""
196
 
197
- #: includes/admin/builder/class-builder.php:305
198
  msgid "Are you sure you want to duplicate this field?"
199
  msgstr ""
200
 
201
- #: includes/admin/builder/class-builder.php:306
202
  msgid "(copy)"
203
  msgstr ""
204
 
205
- #: includes/admin/builder/class-builder.php:307
206
  msgid "Please enter a form title."
207
  msgstr ""
208
 
209
- #: includes/admin/builder/class-builder.php:308
210
  msgid "This item must contain at least one choice."
211
  msgstr ""
212
 
213
- #: includes/admin/builder/class-builder.php:309
214
  #: includes/fields/class-base.php:239 includes/fields/class-base.php:570
215
  #: lite/wpforms-lite.php:78 pro/wpforms-pro.php:263
216
  msgid "Off"
217
  msgstr ""
218
 
219
- #: includes/admin/builder/class-builder.php:310
220
  #: includes/fields/class-base.php:239 lite/wpforms-lite.php:77
221
  #: pro/wpforms-pro.php:262
222
  msgid "On"
223
  msgstr ""
224
 
225
- #: includes/admin/builder/class-builder.php:311
226
  #: includes/templates/class-suggestion.php:59
227
  msgid "Other"
228
  msgstr ""
229
 
230
- #: includes/admin/builder/class-builder.php:312 includes/class-frontend.php:492
231
  #: pro/includes/fields/class-page-break.php:144
232
  msgid "Previous"
233
  msgstr ""
234
 
235
- #: includes/admin/builder/class-builder.php:315
236
  #: includes/admin/builder/functions.php:246 includes/fields/class-base.php:471
237
  msgid "Show Smart Tags"
238
  msgstr ""
239
 
240
- #: includes/admin/builder/class-builder.php:316
241
  msgid "Hide Smart Tags"
242
  msgstr ""
243
 
244
- #: includes/admin/builder/class-builder.php:317
245
  msgid "-- Select Field --"
246
  msgstr ""
247
 
248
- #: includes/admin/builder/class-builder.php:318
249
  #: pro/includes/class-provider.php:945
250
  msgid "-- Select Choice --"
251
  msgstr ""
252
 
253
- #: includes/admin/builder/class-builder.php:377
254
  msgid "Now editing"
255
  msgstr ""
256
 
257
- #: includes/admin/builder/class-builder.php:387
258
  #: pro/includes/admin/entries/class-entries.php:512
259
  msgid "Preview Form"
260
  msgstr ""
261
 
262
- #: includes/admin/builder/class-builder.php:389
263
  #: includes/admin/overview/class-overview-table.php:159
264
  msgid "Preview"
265
  msgstr ""
266
 
267
- #: includes/admin/builder/class-builder.php:392
268
  msgid "Embed Form"
269
  msgstr ""
270
 
271
- #: includes/admin/builder/class-builder.php:394
272
  msgid "Embed"
273
  msgstr ""
274
 
275
- #: includes/admin/builder/class-builder.php:397
276
  msgid "Save Form"
277
  msgstr ""
278
 
279
- #: includes/admin/builder/class-builder.php:399
280
  #: pro/includes/admin/class-settings.php:451
281
  msgid "Save"
282
  msgstr ""
@@ -529,9 +529,9 @@ msgid ""
529
  "a>?"
530
  msgstr ""
531
 
532
- #. #-#-#-#-# wpforms.pot (WPForms 1.3.4) #-#-#-#-#
533
  #. Plugin Name of the plugin/theme
534
- #. #-#-#-#-# wpforms.pot (WPForms 1.3.4) #-#-#-#-#
535
  #. Author of the plugin/theme
536
  #: includes/admin/class-menu.php:36 includes/admin/class-menu.php:37
537
  #: includes/admin/class-menu.php:48 includes/integrations.php:34
@@ -1103,7 +1103,7 @@ msgid "No field type found"
1103
  msgstr ""
1104
 
1105
  #: includes/fields/class-base.php:798 includes/fields/class-name.php:311
1106
- #: includes/fields/class-number.php:127
1107
  #: pro/includes/fields/class-address.php:624
1108
  #: pro/includes/fields/class-date-time.php:532
1109
  #: pro/includes/fields/class-file-upload.php:356
@@ -1274,7 +1274,7 @@ msgstr ""
1274
  msgid "Numbers"
1275
  msgstr ""
1276
 
1277
- #: includes/fields/class-number.php:132
1278
  msgid "Please enter a valid number."
1279
  msgstr ""
1280
 
@@ -1672,17 +1672,17 @@ msgid ""
1672
  "To display all form fields, use the <code>{all_fields}</code> Smart Tag."
1673
  msgstr ""
1674
 
1675
- #: lite/wpforms-lite.php:440
1676
  msgid "is a PRO Feature"
1677
  msgstr ""
1678
 
1679
- #: lite/wpforms-lite.php:441
1680
  msgid ""
1681
  "We're sorry, %name% is not available on your plan.<br><br>Please upgrade to "
1682
  "the PRO plan to unlock all these awesome features."
1683
  msgstr ""
1684
 
1685
- #: lite/wpforms-lite.php:442
1686
  msgid "Upgrade to PRO"
1687
  msgstr ""
1688
 
@@ -3185,9 +3185,9 @@ msgstr ""
3185
  msgid "Please deactivate WPForms Lite before activating WPForms"
3186
  msgstr ""
3187
 
3188
- #. #-#-#-#-# wpforms.pot (WPForms 1.3.4) #-#-#-#-#
3189
  #. Plugin URI of the plugin/theme
3190
- #. #-#-#-#-# wpforms.pot (WPForms 1.3.4) #-#-#-#-#
3191
  #. Author URI of the plugin/theme
3192
  msgid "https://wpforms.com"
3193
  msgstr ""
2
  # This file is distributed under the same license as the WPForms package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: WPForms 1.3.5\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wpforms\n"
7
+ "POT-Creation-Date: 2017-02-22 22:15:23+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
48
  msgid "taxonomy"
49
  msgstr ""
50
 
51
+ #: includes/admin/builder/class-builder.php:271
52
  #: pro/includes/fields/class-date-time.php:229
53
  #: pro/includes/fields/class-date-time.php:231
54
  #: pro/includes/fields/class-date-time.php:452
56
  msgid "DD"
57
  msgstr ""
58
 
59
+ #: includes/admin/builder/class-builder.php:272
60
  #: pro/includes/fields/class-date-time.php:228
61
  #: pro/includes/fields/class-date-time.php:232
62
  #: pro/includes/fields/class-date-time.php:433
65
  msgid "MM"
66
  msgstr ""
67
 
68
+ #: includes/admin/builder/class-builder.php:273
69
  msgid ""
70
  "The {source} {type} contains over {limit} items ({total}). This may make the "
71
  "field difficult for your vistors to use and/or cause the form to be slow."
72
  msgstr ""
73
 
74
+ #: includes/admin/builder/class-builder.php:274
75
  #: includes/admin/class-editor.php:96
76
  #: pro/includes/admin/entries/class-entries.php:994
77
  msgid "Cancel"
78
  msgstr ""
79
 
80
+ #: includes/admin/builder/class-builder.php:275
81
  msgid "OK"
82
  msgstr ""
83
 
84
+ #: includes/admin/builder/class-builder.php:276
85
  #: includes/admin/class-editor.php:70
86
  msgid "Close"
87
  msgstr ""
88
 
89
+ #: includes/admin/builder/class-builder.php:277
90
  msgid ""
91
  "Due to form changes, conditional logic rules have been removed or updated:"
92
  msgstr ""
93
 
94
+ #: includes/admin/builder/class-builder.php:278
95
  #: pro/includes/admin/entries/class-entries-table.php:176
96
  msgid "Field"
97
  msgstr ""
98
 
99
+ #: includes/admin/builder/class-builder.php:279
100
  msgid "Field Locked"
101
  msgstr ""
102
 
103
+ #: includes/admin/builder/class-builder.php:280
104
  msgid "This field cannot be deleted or duplicated."
105
  msgstr ""
106
 
107
+ #: includes/admin/builder/class-builder.php:281
108
  msgid "Available Fields"
109
  msgstr ""
110
 
111
+ #: includes/admin/builder/class-builder.php:282
112
  msgid "No fields available"
113
  msgstr ""
114
 
115
+ #: includes/admin/builder/class-builder.php:283
116
  msgid "Heads up!"
117
  msgstr ""
118
 
119
+ #: includes/admin/builder/class-builder.php:285
120
  msgid "No email fields"
121
  msgstr ""
122
 
123
+ #: includes/admin/builder/class-builder.php:286
124
  msgid "Are you sure you want to delete this notification?"
125
  msgstr ""
126
 
127
+ #: includes/admin/builder/class-builder.php:287
128
  msgid "Enter a notification name"
129
  msgstr ""
130
 
131
+ #: includes/admin/builder/class-builder.php:288
132
  msgid "Eg: User Confirmation"
133
  msgstr ""
134
 
135
+ #: includes/admin/builder/class-builder.php:289
136
  msgid "You must provide a notification name"
137
  msgstr ""
138
 
139
+ #: includes/admin/builder/class-builder.php:290
140
  msgid ""
141
  "Form must contain one notification. To disable all notifications use the "
142
  "setting Notifications dropdown setting."
143
  msgstr ""
144
 
145
+ #: includes/admin/builder/class-builder.php:291
146
  #: lite/includes/admin/class-settings.php:131
147
  #: pro/includes/admin/class-settings.php:135
148
  msgid "Saving ..."
149
  msgstr ""
150
 
151
+ #: includes/admin/builder/class-builder.php:292
152
  msgid "Saved!"
153
  msgstr ""
154
 
155
+ #: includes/admin/builder/class-builder.php:293
156
  msgid "Save and Exit"
157
  msgstr ""
158
 
159
+ #: includes/admin/builder/class-builder.php:294
160
+ #: includes/admin/builder/class-builder.php:357
161
  msgid "Loading"
162
  msgstr ""
163
 
164
+ #: includes/admin/builder/class-builder.php:300
165
  msgid "Use Template"
166
  msgstr ""
167
 
168
+ #: includes/admin/builder/class-builder.php:301
169
  msgid ""
170
  "Changing templates on an existing form will DELETE existing form fields. Are "
171
  "you sure you want apply the new template?"
172
  msgstr ""
173
 
174
+ #: includes/admin/builder/class-builder.php:302
175
  msgid ""
176
  "You are almost done. To embed this form on your site, please paste the "
177
  "following shortcode inside a post or page."
178
  msgstr ""
179
 
180
+ #: includes/admin/builder/class-builder.php:303
181
  msgid "Or you can follow the instructions in this video."
182
  msgstr ""
183
 
184
+ #: includes/admin/builder/class-builder.php:304
185
+ #: includes/admin/builder/class-builder.php:407
186
  msgid "Exit"
187
  msgstr ""
188
 
189
+ #: includes/admin/builder/class-builder.php:306
190
  msgid "If you exit without saving, your changes will be lost."
191
  msgstr ""
192
 
193
+ #: includes/admin/builder/class-builder.php:307
194
  msgid "Are you sure you want to delete this field?"
195
  msgstr ""
196
 
197
+ #: includes/admin/builder/class-builder.php:308
198
  msgid "Are you sure you want to duplicate this field?"
199
  msgstr ""
200
 
201
+ #: includes/admin/builder/class-builder.php:309
202
  msgid "(copy)"
203
  msgstr ""
204
 
205
+ #: includes/admin/builder/class-builder.php:310
206
  msgid "Please enter a form title."
207
  msgstr ""
208
 
209
+ #: includes/admin/builder/class-builder.php:311
210
  msgid "This item must contain at least one choice."
211
  msgstr ""
212
 
213
+ #: includes/admin/builder/class-builder.php:312
214
  #: includes/fields/class-base.php:239 includes/fields/class-base.php:570
215
  #: lite/wpforms-lite.php:78 pro/wpforms-pro.php:263
216
  msgid "Off"
217
  msgstr ""
218
 
219
+ #: includes/admin/builder/class-builder.php:313
220
  #: includes/fields/class-base.php:239 lite/wpforms-lite.php:77
221
  #: pro/wpforms-pro.php:262
222
  msgid "On"
223
  msgstr ""
224
 
225
+ #: includes/admin/builder/class-builder.php:314
226
  #: includes/templates/class-suggestion.php:59
227
  msgid "Other"
228
  msgstr ""
229
 
230
+ #: includes/admin/builder/class-builder.php:315 includes/class-frontend.php:492
231
  #: pro/includes/fields/class-page-break.php:144
232
  msgid "Previous"
233
  msgstr ""
234
 
235
+ #: includes/admin/builder/class-builder.php:318
236
  #: includes/admin/builder/functions.php:246 includes/fields/class-base.php:471
237
  msgid "Show Smart Tags"
238
  msgstr ""
239
 
240
+ #: includes/admin/builder/class-builder.php:319
241
  msgid "Hide Smart Tags"
242
  msgstr ""
243
 
244
+ #: includes/admin/builder/class-builder.php:320
245
  msgid "-- Select Field --"
246
  msgstr ""
247
 
248
+ #: includes/admin/builder/class-builder.php:321
249
  #: pro/includes/class-provider.php:945
250
  msgid "-- Select Choice --"
251
  msgstr ""
252
 
253
+ #: includes/admin/builder/class-builder.php:380
254
  msgid "Now editing"
255
  msgstr ""
256
 
257
+ #: includes/admin/builder/class-builder.php:390
258
  #: pro/includes/admin/entries/class-entries.php:512
259
  msgid "Preview Form"
260
  msgstr ""
261
 
262
+ #: includes/admin/builder/class-builder.php:392
263
  #: includes/admin/overview/class-overview-table.php:159
264
  msgid "Preview"
265
  msgstr ""
266
 
267
+ #: includes/admin/builder/class-builder.php:395
268
  msgid "Embed Form"
269
  msgstr ""
270
 
271
+ #: includes/admin/builder/class-builder.php:397
272
  msgid "Embed"
273
  msgstr ""
274
 
275
+ #: includes/admin/builder/class-builder.php:400
276
  msgid "Save Form"
277
  msgstr ""
278
 
279
+ #: includes/admin/builder/class-builder.php:402
280
  #: pro/includes/admin/class-settings.php:451
281
  msgid "Save"
282
  msgstr ""
529
  "a>?"
530
  msgstr ""
531
 
532
+ #. #-#-#-#-# wpforms.pot (WPForms 1.3.5) #-#-#-#-#
533
  #. Plugin Name of the plugin/theme
534
+ #. #-#-#-#-# wpforms.pot (WPForms 1.3.5) #-#-#-#-#
535
  #. Author of the plugin/theme
536
  #: includes/admin/class-menu.php:36 includes/admin/class-menu.php:37
537
  #: includes/admin/class-menu.php:48 includes/integrations.php:34
1103
  msgstr ""
1104
 
1105
  #: includes/fields/class-base.php:798 includes/fields/class-name.php:311
1106
+ #: includes/fields/class-number.php:132
1107
  #: pro/includes/fields/class-address.php:624
1108
  #: pro/includes/fields/class-date-time.php:532
1109
  #: pro/includes/fields/class-file-upload.php:356
1274
  msgid "Numbers"
1275
  msgstr ""
1276
 
1277
+ #: includes/fields/class-number.php:137
1278
  msgid "Please enter a valid number."
1279
  msgstr ""
1280
 
1672
  "To display all form fields, use the <code>{all_fields}</code> Smart Tag."
1673
  msgstr ""
1674
 
1675
+ #: lite/wpforms-lite.php:446
1676
  msgid "is a PRO Feature"
1677
  msgstr ""
1678
 
1679
+ #: lite/wpforms-lite.php:447
1680
  msgid ""
1681
  "We're sorry, %name% is not available on your plan.<br><br>Please upgrade to "
1682
  "the PRO plan to unlock all these awesome features."
1683
  msgstr ""
1684
 
1685
+ #: lite/wpforms-lite.php:448
1686
  msgid "Upgrade to PRO"
1687
  msgstr ""
1688
 
3185
  msgid "Please deactivate WPForms Lite before activating WPForms"
3186
  msgstr ""
3187
 
3188
+ #. #-#-#-#-# wpforms.pot (WPForms 1.3.5) #-#-#-#-#
3189
  #. Plugin URI of the plugin/theme
3190
+ #. #-#-#-#-# wpforms.pot (WPForms 1.3.5) #-#-#-#-#
3191
  #. Author URI of the plugin/theme
3192
  msgid "https://wpforms.com"
3193
  msgstr ""
lite/includes/admin/class-settings.php CHANGED
@@ -66,6 +66,7 @@ class WPForms_Settings {
66
  $this->options = get_option( 'wpforms_settings', array() );
67
 
68
  add_action( 'wpforms_tab_settings_general', array( $this, 'settings_page_tab_general' ) );
 
69
  add_action( 'wpforms_tab_settings_system', array( $this, 'settings_page_tab_system' ) );
70
  add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) );
71
  add_action( 'wpforms_admin_page', array( $this, 'output' ) );
@@ -150,6 +151,7 @@ class WPForms_Settings {
150
  // Define our base tabs
151
  $tabs = array(
152
  'general' => __( 'General', 'wpforms' ),
 
153
  'system' => __( 'System Information', 'wpforms' ),
154
  );
155
 
@@ -321,6 +323,31 @@ class WPForms_Settings {
321
  <?php
322
  }
323
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
  /**
325
  * Build the output for System Info (system) tab on the settings page.
326
  *
66
  $this->options = get_option( 'wpforms_settings', array() );
67
 
68
  add_action( 'wpforms_tab_settings_general', array( $this, 'settings_page_tab_general' ) );
69
+ add_action( 'wpforms_tab_settings_providers', array( $this, 'settings_page_tab_providers' ) );
70
  add_action( 'wpforms_tab_settings_system', array( $this, 'settings_page_tab_system' ) );
71
  add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) );
72
  add_action( 'wpforms_admin_page', array( $this, 'output' ) );
151
  // Define our base tabs
152
  $tabs = array(
153
  'general' => __( 'General', 'wpforms' ),
154
+ 'providers' => __( 'Integrations', 'wpforms' ),
155
  'system' => __( 'System Information', 'wpforms' ),
156
  );
157
 
323
  <?php
324
  }
325
 
326
+ /**
327
+ * Build the output for Integrations (providers) tab on the settings page and check for save.
328
+ *
329
+ * @since 1.0.0
330
+ */
331
+ public function settings_page_tab_providers() {
332
+
333
+ $providers = get_option( 'wpforms_providers', false );
334
+ $active = apply_filters( 'wpforms_providers_available', array() );
335
+
336
+ // If no provider addons are activated display a message and bail
337
+ if ( empty( $active ) ) {
338
+ echo '<div class="notice notice-info below-h2"><p>' . sprintf( __( 'You do not have any marketing add-ons activated. You can head over to the <a href="%s">Add-Ons page</a> to install and activate the add-on for your provider.', 'wpforms' ), admin_url( 'admin.php?page=wpforms-addons' ) ) . '</p></div>';
339
+ return;
340
+ }
341
+ ?>
342
+
343
+ <div id="wpforms-settings-providers">
344
+
345
+ <?php do_action( 'wpforms_settings_providers', $active, $providers ); ?>
346
+
347
+ </div>
348
+ <?php
349
+ }
350
+
351
  /**
352
  * Build the output for System Info (system) tab on the settings page.
353
  *
lite/wpforms-lite.php CHANGED
@@ -265,11 +265,6 @@ class WPForms_Lite {
265
  'name' => 'Billing / Order Form',
266
  'slug' => 'order',
267
  'description' => 'Collect payments for product and service orders with this ready-made form template. You can add and remove fields as needed.',
268
- ),
269
- array(
270
- 'name' => 'Newsletter Sign Up Form',
271
- 'slug' => 'subscribe',
272
- 'description' => 'Add subscribers and grow your email list with this newsletter signup form. You can add and remove fields as needed.',
273
  )
274
  );
275
  ?>
@@ -415,9 +410,6 @@ class WPForms_Lite {
415
  public function form_panels() {
416
 
417
  ?>
418
- <button class="wpforms-panel-providers-button upgrade-modal" data-panel="providers">
419
- <i class="fa fa-bullhorn"></i><span>Marketing</span>
420
- </button>
421
  <button class="wpforms-panel-payments-button upgrade-modal" data-panel="payments">
422
  <i class="fa fa-usd"></i><span>Payments</span>
423
  </button>
265
  'name' => 'Billing / Order Form',
266
  'slug' => 'order',
267
  'description' => 'Collect payments for product and service orders with this ready-made form template. You can add and remove fields as needed.',
 
 
 
 
 
268
  )
269
  );
270
  ?>
410
  public function form_panels() {
411
 
412
  ?>
 
 
 
413
  <button class="wpforms-panel-payments-button upgrade-modal" data-panel="payments">
414
  <i class="fa fa-usd"></i><span>Payments</span>
415
  </button>
readme.txt CHANGED
@@ -2,7 +2,7 @@
2
  Contributors: wpforms, jaredatch, smub
3
  Tags: contact form, contact form plugin, contact button, contact me, custom form, custom contact form, form builder, form manager, form, forms builder, forms creator, captcha, recaptcha, Akismet, email form, web form, feedback form, payment form, survey form, donation form, email submit form, message form, mailchimp, mailchimp form, aweber, aweber form, paypal, paypal form, stripe, stripe form, getresponse, getresponse form, email subscription, contact form widget, user registration form, wordpress registration, wordpress login form
4
  Requires at least: 4.5
5
- Tested up to: 4.7.2
6
  Stable tag: trunk
7
  License: GNU General Public License v2.0 or later
8
 
@@ -163,10 +163,17 @@ Syed Balkhi
163
 
164
  == Changelog ==
165
 
 
 
 
 
 
 
 
166
  = 1.3.5 =
167
  - Fixed: Some browers allowing unexpected characters inside number input fields
168
  - Fixed: Issue with Dropdown field placeholder text
169
- - Fixed: Select few plugins loading conflicting scripts in form builder
170
 
171
  = 1.3.4 =
172
  - Added: reCAPTCHA improvements; reCAPTCHA now required if turned on
@@ -179,7 +186,6 @@ Syed Balkhi
179
  - Fixed: Possible errors if web host had `set_time_limit()` disabled
180
 
181
  = 1.3.2 =
182
- - Added: WP.org review request
183
  - Added: New form class, `.inline-fields`, to apply single line form layout
184
  - Changed: All Smart Tags now available for Email Subject field in form notifications
185
  - Fixed: Email addresses reporting as invalid of the domain contained capitalization
2
  Contributors: wpforms, jaredatch, smub
3
  Tags: contact form, contact form plugin, contact button, contact me, custom form, custom contact form, form builder, form manager, form, forms builder, forms creator, captcha, recaptcha, Akismet, email form, web form, feedback form, payment form, survey form, donation form, email submit form, message form, mailchimp, mailchimp form, aweber, aweber form, paypal, paypal form, stripe, stripe form, getresponse, getresponse form, email subscription, contact form widget, user registration form, wordpress registration, wordpress login form
4
  Requires at least: 4.5
5
+ Tested up to: 4.7.3
6
  Stable tag: trunk
7
  License: GNU General Public License v2.0 or later
8
 
163
 
164
  == Changelog ==
165
 
166
+ = 1.3.6 =
167
+ - Added: Constant Contact integration
168
+ - Changed: Don't strip tags from plain text emails
169
+ - Fixed: Form builder javascript conflict with Clef plugin
170
+ - Fixed: Form builder logo URL double slash
171
+ - Fixed: Form builder embed code field not being selectable
172
+
173
  = 1.3.5 =
174
  - Fixed: Some browers allowing unexpected characters inside number input fields
175
  - Fixed: Issue with Dropdown field placeholder text
176
+ - Fixed: Other plugins loading conflicting scripts in form builder
177
 
178
  = 1.3.4 =
179
  - Added: reCAPTCHA improvements; reCAPTCHA now required if turned on
186
  - Fixed: Possible errors if web host had `set_time_limit()` disabled
187
 
188
  = 1.3.2 =
 
189
  - Added: New form class, `.inline-fields`, to apply single line form layout
190
  - Changed: All Smart Tags now available for Email Subject field in form notifications
191
  - Fixed: Email addresses reporting as invalid of the domain contained capitalization
wpforms.php CHANGED
@@ -5,7 +5,7 @@
5
  * Description: Beginner friendly WordPress contact form plugin. Use our Drag & Drop form builder to create your WordPress forms.
6
  * Author: WPForms
7
  * Author URI: https://wpforms.com
8
- * Version: 1.3.5
9
  * Text Domain: wpforms
10
  * Domain Path: languages
11
  *
@@ -81,7 +81,7 @@ final class WPForms {
81
  * @since 1.0.0
82
  * @var sting
83
  */
84
- public $version = '1.3.5';
85
 
86
  /**
87
  * The form data handler instance.
@@ -199,6 +199,7 @@ final class WPForms {
199
  require_once WPFORMS_PLUGIN_DIR . 'includes/class-fields.php';
200
  require_once WPFORMS_PLUGIN_DIR . 'includes/class-frontend.php';
201
  require_once WPFORMS_PLUGIN_DIR . 'includes/class-templates.php';
 
202
  require_once WPFORMS_PLUGIN_DIR . 'includes/class-process.php';
203
  require_once WPFORMS_PLUGIN_DIR . 'includes/class-smart-tags.php';
204
  require_once WPFORMS_PLUGIN_DIR . 'includes/class-logging.php';
5
  * Description: Beginner friendly WordPress contact form plugin. Use our Drag & Drop form builder to create your WordPress forms.
6
  * Author: WPForms
7
  * Author URI: https://wpforms.com
8
+ * Version: 1.3.6
9
  * Text Domain: wpforms
10
  * Domain Path: languages
11
  *
81
  * @since 1.0.0
82
  * @var sting
83
  */
84
+ public $version = '1.3.6';
85
 
86
  /**
87
  * The form data handler instance.
199
  require_once WPFORMS_PLUGIN_DIR . 'includes/class-fields.php';
200
  require_once WPFORMS_PLUGIN_DIR . 'includes/class-frontend.php';
201
  require_once WPFORMS_PLUGIN_DIR . 'includes/class-templates.php';
202
+ require_once WPFORMS_PLUGIN_DIR . 'includes/class-providers.php';
203
  require_once WPFORMS_PLUGIN_DIR . 'includes/class-process.php';
204
  require_once WPFORMS_PLUGIN_DIR . 'includes/class-smart-tags.php';
205
  require_once WPFORMS_PLUGIN_DIR . 'includes/class-logging.php';