Creative Mail – Easier WordPress & WooCommerce Email Marketing - Version 1.6.1

Version Description

Download this release

Release Info

Developer constantcontact
Plugin Icon 128x128 Creative Mail – Easier WordPress & WooCommerce Email Marketing
Version 1.6.1
Comparing to
See all releases

Code changes from version 1.6.0 to 1.6.1

Files changed (141) hide show
  1. CHANGELOG.md +3 -0
  2. README.md +2 -1
  3. assets/css/admin.css +764 -764
  4. assets/css/deactivation.css +16 -16
  5. assets/css/feedback_notice.css +39 -39
  6. assets/js/block/subscribe.asset.php +1 -1
  7. assets/js/block/subscribe.js +1 -1
  8. assets/js/deactivation.js +39 -39
  9. assets/js/feedback_notice.js +13 -13
  10. assets/js/footer_rating.js +3 -3
  11. composer.json +7 -7
  12. composer.lock +31 -84
  13. creative-mail-plugin.php +84 -59
  14. readme.txt +2 -1
  15. src/Clients/CreativeMailClient.php +141 -100
  16. src/Constants/EnvironmentNames.php +5 -5
  17. src/CreativeMail.php +219 -116
  18. src/Exceptions/CreativeMailException.php +9 -6
  19. src/Helpers/EncryptionHelper.php +72 -76
  20. src/Helpers/EnvironmentHelper.php +53 -56
  21. src/Helpers/GuidHelper.php +20 -9
  22. src/Helpers/OptionsHelper.php +382 -395
  23. src/Helpers/SsoHelper.php +63 -54
  24. src/Integrations/Integration.php +161 -114
  25. src/Managers/AdminManager.php +668 -553
  26. src/Managers/ApiManager.php +784 -770
  27. src/Managers/CheckoutManager.php +1023 -966
  28. src/Managers/DatabaseManager.php +279 -278
  29. src/Managers/EmailManager.php +795 -826
  30. src/Managers/FormManager.php +90 -96
  31. src/Managers/InstanceManager.php +40 -38
  32. src/Managers/IntegrationManager.php +178 -185
  33. src/Managers/RaygunManager.php +83 -88
  34. src/Models/ApiSchema.php +26 -26
  35. src/Models/Campaign.php +32 -32
  36. src/Models/CartData.php +50 -44
  37. src/Models/Checkout.php +32 -32
  38. src/Models/CheckoutSave.php +32 -32
  39. src/Models/Coupon.php +55 -0
  40. src/Models/CustomerNewAccount.php +32 -32
  41. src/Models/CustomerNote.php +20 -20
  42. src/Models/CustomerResetPassword.php +26 -26
  43. src/Models/EmailNotification.php +14 -14
  44. src/Models/HashSchema.php +26 -26
  45. src/Models/OptionsSchema.php +14 -14
  46. src/Models/Order.php +36 -32
  47. src/Models/OrderBilling.php +120 -104
  48. src/Models/OrderBillingPaymentDetails.php +40 -0
  49. src/Models/OrderBillingShipping.php +96 -0
  50. src/Models/OrderLineItem.php +180 -0
  51. src/Models/RequestItem.php +116 -116
  52. src/Models/Response.php +8 -8
  53. src/Models/TriggerExecution.php +14 -14
  54. src/Models/User.php +38 -38
  55. src/Modules/Api/Models/ApiRequestItem.php +64 -24
  56. src/Modules/Api/Processes/ApiBackgroundProcess.php +62 -60
  57. src/Modules/Blog/Models/BlogAttachment.php +23 -23
  58. src/Modules/Blog/Models/BlogInformation.php +30 -31
  59. src/Modules/Blog/Models/BlogPost.php +33 -34
  60. src/Modules/Contacts/Exceptions/InvalidContactSyncBackgroundRequestException.php +5 -6
  61. src/Modules/Contacts/Exceptions/InvalidHandlerContactSyncRequestException.php +5 -6
  62. src/Modules/Contacts/Handlers/BaseContactFormPluginHandler.php +54 -60
  63. src/Modules/Contacts/Handlers/BlueHostBuilderPluginHandler.php +100 -106
  64. src/Modules/Contacts/Handlers/CalderaPluginHandler.php +174 -180
  65. src/Modules/Contacts/Handlers/ContactFormSevenPluginHandler.php +209 -216
  66. src/Modules/Contacts/Handlers/CreativeMailPluginHandler.php +72 -79
  67. src/Modules/Contacts/Handlers/ElementorPluginHandler.php +93 -99
  68. src/Modules/Contacts/Handlers/FormidablePluginHandler.php +166 -171
  69. src/Modules/Contacts/Handlers/GravityFormsPluginHandler.php +256 -229
  70. src/Modules/Contacts/Handlers/JetpackPluginHandler.php +241 -208
  71. src/Modules/Contacts/Handlers/NewsLetterContactFormPluginHandler.php +128 -115
  72. src/Modules/Contacts/Handlers/NinjaFormsPluginHandler.php +256 -225
  73. src/Modules/Contacts/Handlers/WooCommercePluginHandler.php +243 -188
  74. src/Modules/Contacts/Handlers/WpFormsPluginHandler.php +205 -161
  75. src/Modules/Contacts/Managers/ContactsSyncManager.php +25 -18
  76. src/Modules/Contacts/Models/ContactAddressModel.php +209 -94
  77. src/Modules/Contacts/Models/ContactFormSevenSubmission.php +4 -4
  78. src/Modules/Contacts/Models/ContactModel.php +169 -201
  79. src/Modules/Contacts/Models/FormidableContactForm.php +11 -0
  80. src/Modules/Contacts/Models/OptActionBy.php +4 -6
  81. src/Modules/Contacts/Processors/ContactsSyncBackgroundProcessor.php +61 -62
  82. src/Modules/Contacts/Services/ContactsSyncService.php +264 -266
  83. src/Modules/DashboardWidgetModule.php +97 -104
  84. src/Modules/FeedbackNoticeModule.php +77 -78
  85. src/Modules/WooCommerce/Emails/AbandonedCartEmail.php +18 -20
  86. src/Modules/WooCommerce/Models/WCInformationModel.php +16 -16
  87. src/Modules/WooCommerce/Models/WCProductModel.php +39 -40
  88. src/Modules/WooCommerce/Models/WCStoreInformation.php +28 -29
  89. src/blocks/LoadBlock.php +30 -18
  90. src/blocks/subscribe/deprecated/deprecated_save.js +9 -7
  91. src/blocks/subscribe/edit.js +446 -446
  92. src/blocks/subscribe/index.js +4 -1
  93. src/blocks/subscribe/save.js +6 -6
  94. src/views/activated-integrations.php +236 -220
  95. src/views/admin-dashboard-widget/campaigns.php +34 -24
  96. src/views/admin-dashboard-widget/divider.php +5 -0
  97. src/views/admin-dashboard-widget/exception.php +16 -9
  98. src/views/admin-dashboard-widget/most-recent-campaigns.php +91 -89
  99. src/views/admin-dashboard-widget/no-campaign.php +13 -10
  100. src/views/admin-dashboard-widget/no-ce-account.php +13 -12
  101. src/views/admin-dashboard-widget/no-woocommerce.php +19 -12
  102. src/views/admin-dashboard-widget/woocommerce.php +34 -26
  103. src/views/admin-feedback-notice/after-week-notice.php +23 -0
  104. src/views/admin-feedback-notice/few-contacts.php +15 -9
  105. src/views/admin-feedback-notice/many-contacts.php +22 -17
  106. src/views/admin-feedback-notice/sync-disabled.php +19 -15
  107. src/views/admin-get-started-banner.php +37 -31
  108. src/views/available-integrations.php +69 -75
  109. src/views/contact-sync.php +20 -18
  110. src/views/creative-mail-form-banner.php +67 -62
  111. src/views/dashboard-open-creative-mail.php +59 -44
  112. src/views/dashboard.php +69 -65
  113. src/views/onboarding-content.php +43 -39
  114. src/views/onboarding.php +38 -36
  115. src/views/password-protected-notice.php +10 -5
  116. src/views/pending-setup.php +18 -14
  117. src/views/settings-internal.php +69 -41
  118. src/views/settings.php +123 -99
  119. src/views/unlink.php +20 -5
  120. vendor/autoload.php +1 -1
  121. vendor/bin/phpstan +8 -0
  122. vendor/bin/phpstan.phar +0 -0
  123. vendor/composer/autoload_classmap.php +5 -1
  124. vendor/composer/autoload_real.php +7 -7
  125. vendor/composer/autoload_static.php +10 -6
  126. vendor/composer/installed.json +44 -97
  127. vendor/mindscape/raygun4php/.travis.yml +4 -1
  128. vendor/mindscape/raygun4php/sample-apps/.gitignore +2 -0
  129. vendor/mindscape/raygun4php/sample-apps/async-example/README.md +6 -0
  130. vendor/mindscape/raygun4php/sample-apps/async-example/composer.json +6 -0
  131. vendor/mindscape/raygun4php/sample-apps/async-example/config-sample.php +2 -0
  132. vendor/mindscape/raygun4php/sample-apps/async-example/index.php +46 -0
  133. vendor/mindscape/raygun4php/sample-apps/async-example/partials/head.php +15 -0
  134. vendor/mindscape/raygun4php/sample-apps/async-example/raygunSetup.php +37 -0
  135. vendor/mindscape/raygun4php/sample-apps/async-example/viewData.php +76 -0
  136. vendor/mindscape/raygun4php/src/Raygun4php/RaygunClient.php +2 -2
  137. vendor/phpstan/phpstan/README.md +4 -5
  138. vendor/phpstan/phpstan/bootstrap.php +1 -1
  139. vendor/phpstan/phpstan/composer.json +1 -0
  140. vendor/phpstan/phpstan/phpstan.phar +0 -0
  141. vendor/phpstan/phpstan/phpstan.phar.asc +13 -13
CHANGELOG.md CHANGED
@@ -1,6 +1,9 @@
1
  Changelog
2
  =========
3
 
 
 
 
4
  #### 1.6.0 - October 12th, 2022
5
  - Security update
6
  - Bug fixes
1
  Changelog
2
  =========
3
 
4
+ #### 1.6.1 - October 28th, 2022
5
+ - Security update
6
+
7
  #### 1.6.0 - October 12th, 2022
8
  - Security update
9
  - Bug fixes
README.md CHANGED
@@ -3,7 +3,7 @@ Contributors: Constant Contact
3
  Tags: email, marketing, newsletter, subscribe, contact form, constant contact, crm, automations, ecommerce, promotion, offers, retargeting
4
  Requires at least: 4.9
5
  Tested up to: 6.0.2
6
- Stable tag: 1.6.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
  Requires PHP: 7.2
@@ -93,6 +93,7 @@ Creative Mail by Constant Contact [Privacy Notice](https://www.endurance.com/pri
93
  6. Enhance your brand with LogoBuilder
94
 
95
  == Changelog ==
 
96
  * 1.6.0 - Security update, Bug fixes and Support to sync Address Fields for Contact Form 7
97
  * 1.5.4 - Migration to WordPress version 6.0.2 and Checkout mail templates update
98
  * 1.5.3 - README update
3
  Tags: email, marketing, newsletter, subscribe, contact form, constant contact, crm, automations, ecommerce, promotion, offers, retargeting
4
  Requires at least: 4.9
5
  Tested up to: 6.0.2
6
+ Stable tag: 1.6.1
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
  Requires PHP: 7.2
93
  6. Enhance your brand with LogoBuilder
94
 
95
  == Changelog ==
96
+ * 1.6.1 - Security update
97
  * 1.6.0 - Security update, Bug fixes and Support to sync Address Fields for Contact Form 7
98
  * 1.5.4 - Migration to WordPress version 6.0.2 and Checkout mail templates update
99
  * 1.5.3 - README update
assets/css/admin.css CHANGED
@@ -1,1309 +1,1309 @@
1
  .ce4wp-admin-wrapper {
2
- margin-right: 20px;
3
- margin-top: 20px;
4
- font-size: 14px;
5
- font-family: 'Poppins', sans-serif;
6
  }
7
  @media (max-width:460px) {
8
- .ce4wp-admin-wrapper {
9
- margin-right: 10px;
10
- }
11
  }
12
 
13
  .ce4wp-card {
14
- background-attachment:scroll;
15
- background-clip:border-box;
16
- background-color:rgb(255, 255, 255);
17
- background-image:none;
18
- background-origin:padding-box;
19
- background-position-x:0%;
20
- background-position-y:0%;
21
- background-size:auto;
22
- border-radius: 4px;
23
- box-shadow:rgba(0, 0, 0, 0.06) 0px 0px 0px 1px, rgba(0, 0, 0, 0.05) 0px 2px 4px 0px, rgba(0, 0, 0, 0.08) 0px 2px 1px 0px;
24
- box-sizing:border-box;
25
- color:rgba(0, 0, 0, 0.9);
26
- display:block;
27
- font-size:15px;
28
- letter-spacing:normal;
29
- margin-bottom:24px;
30
- min-height:150px;
31
- min-width:200px;
32
- overflow: hidden;
33
- position:relative;
34
- transition-delay:0s;
35
- transition-duration:0.3s;
36
- transition-property:box-shadow;
37
- transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);
38
- -webkit-font-smoothing:antialiased;
39
- padding: 15px;
40
  }
41
 
42
  @media (max-width: 450px){
43
- .ce4wp-card{
44
- padding: 0;
45
- }
46
  }
47
 
48
  .ce4wp-card ul {
49
- padding-left: 10px;
50
  }
51
  .ce4wp-card ul li {
52
- font-size: 14px;
53
- font-weight: 400;
54
  }
55
 
56
  .ce4wp-card .ce4wp-kvp {
57
- margin-top: 10px;
58
  }
59
 
60
  .ce4wp-card .ce4wp-kvp h6 {
61
- margin: 0;
62
  }
63
 
64
  .ce4wp-button-base-root {
65
- color: inherit;
66
- border: 0;
67
- cursor: pointer;
68
- margin: 0;
69
- display: inline-flex;
70
- outline: 0;
71
- padding: 0;
72
- position: relative;
73
- align-items: center;
74
- user-select: none;
75
- border-radius: 0;
76
- vertical-align: middle;
77
- -moz-appearance: none;
78
- justify-content: center;
79
- text-decoration: none;
80
- background-color: transparent;
81
- -webkit-appearance: none;
82
- -webkit-tap-highlight-color: transparent;
83
  }
84
  #skeleton .ce4wp-button-base-root {
85
- cursor: default;
86
  }
87
  .ce4wp-button-root {
88
- color: rgba(0, 0, 0, 0.9);
89
- height: 40px;
90
- padding: 6px 16px;
91
- shadows: none;
92
- font-size: 14px;
93
- min-width: auto;
94
- box-shadow: none;
95
- box-sizing: border-box;
96
- transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
97
- box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
98
- border 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
99
- font-weight: 500;
100
- line-height: inherit;
101
- border-radius: 4px;
102
- text-transform: none;
103
  }
104
 
105
  .ce4wp-button-contained {
106
- color: rgba(0, 0, 0, 0.87);
107
- box-shadow: none;
108
- text-transform: none;
109
- background-color: #e0e0e0;
110
  }
111
  .ce4wp-button-contained-orange {
112
- color: #784100;
113
- border: 1px solid #FFB800;
114
- font-size: 14px;
115
- font-weight: 700;
116
- background-color: #FFB800;
117
  }
118
 
119
  .ce4wp-button-contained-primary {
120
- color: #ffffff;
121
- border: 1px solid #7A4CA8;
122
- font-size: 14px;
123
- font-weight: 700;
124
- background-color: #7A4CA8;
125
  }
126
 
127
  .ce4wp-button-contained-primary:hover {
128
- box-shadow: none;
129
- background-color: #663399;
130
- color: rgba(255, 255, 255, 0.7);
131
  }
132
  .ce4wp-button-label {
133
- width: 100%;
134
- display: inherit;
135
- align-items: inherit;
136
- justify-content: inherit;
137
  }
138
  .ce4wp-button-endIcon {
139
- display: inherit;
140
- margin-left: 8px;
141
- margin-right: -4px;
142
  }
143
 
144
  .ce4wp-button-outlined {
145
- border: 1px solid rgba(0, 0, 0, 0.23);
146
- padding: 5px 15px;
147
  }
148
  .ce4wp-button-outlined-primary {
149
- color: #7A4CA8;
150
- border: 1px solid #7A4CA8;
151
  }
152
  .ce4wp-button-outlined-primary:hover {
153
- border: 1px solid #7A4CA8;
154
- background-color: rgba(122, 76, 168, 0.04);
155
- color: #7A4CA8;
156
  }
157
 
158
  .ce4wp-button-text-primary {
159
- align-items: center;
160
- background-color: rgba(0, 0, 0, 0);
161
- border-radius: 4px;
162
- border-style: none;
163
- border-width: 0;
164
- box-shadow: none;
165
- box-sizing: border-box;
166
- color: rgb(122,76,168);
167
- cursor: pointer;
168
- display: inline-flex;
169
- font-size: 14px;
170
- font-style: normal;
171
- font-weight: 700;
172
- height: 40px;
173
- justify-content: center;
174
- line-height: 20px;
175
- margin: 0px;
176
- min-width: 0px;
177
- padding: 6px 8px;
178
- position: relative;
179
- text-align: center;
180
- transition-delay: 0s, 0s, 0s;
181
- transition-duration: 0.25s, 0.25s, 0.25s;
182
- transition-property: background-color, box-shadow, border;
183
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1), cubic-bezier(0.4, 0, 0.2, 1), cubic-bezier(0.4, 0, 0.2, 1);
184
- user-select: none;
185
- vertical-align: middle;
186
- white-space: nowrap;
187
  }
188
 
189
  .ce4wp-button-text-primary:hover {
190
- background-color: rgba(122,76,168, 0.04);
191
  }
192
 
193
  .ce4wp-button-text-primary.destructive {
194
- color: #D42424;
195
  }
196
 
197
  .ce4wp-button-text-primary.destructive:hover {
198
- background-color: rgba(212, 36, 36, 0.1);
199
  }
200
 
201
  .ce4wp-right {
202
- float: right;
203
  }
204
 
205
  .ce4wp-left {
206
- float: left;
207
  }
208
 
209
  .ce4wp-inline-block {
210
- display: inline-block;
211
  }
212
 
213
  .ce4wp-checkbox {
214
- z-index: 0;
215
- position: relative;
216
- display: inline-block;
217
- color: rgba(var(--pure-material-onsurface-rgb, 0, 0, 0), 0.87);
218
- font-size: 14px;
219
- line-height: 1.5;
220
  }
221
 
222
  /* Input */
223
  .ce4wp-checkbox > input {
224
- appearance: none;
225
- -moz-appearance: none;
226
- -webkit-appearance: none;
227
- z-index: -1;
228
- position: absolute;
229
- left: -10px;
230
- top: -8px;
231
- display: block;
232
- margin: 0;
233
- border-radius: 50%;
234
- width: 40px;
235
- height: 40px;
236
- background-color: rgba(var(--pure-material-onsurface-rgb, 0, 0, 0), 0.6);
237
- box-shadow: none;
238
- outline: none;
239
- opacity: 0;
240
- transform: scale(1);
241
- pointer-events: none;
242
- transition: opacity 0.3s, transform 0.2s;
243
  }
244
 
245
  /* Span */
246
  .ce4wp-checkbox > span {
247
- display: inline-block;
248
- width: 100%;
249
- cursor: pointer;
250
  }
251
 
252
  /* Box */
253
  .ce4wp-checkbox > span::before {
254
- content: "";
255
- display: inline-block;
256
- box-sizing: border-box;
257
- margin: 3px 11px 3px 1px;
258
- border: solid 2px; /* Safari */
259
- border-color: rgba(var(--pure-material-onsurface-rgb, 0, 0, 0), 0.6);
260
- border-radius: 2px;
261
- width: 18px;
262
- height: 18px;
263
- vertical-align: top;
264
- transition: border-color 0.2s, background-color 0.2s;
265
  }
266
 
267
  /* Checkmark */
268
  .ce4wp-checkbox > span::after {
269
- content: "";
270
- display: block;
271
- position: absolute;
272
- top: 3px;
273
- left: 1px;
274
- width: 10px;
275
- height: 5px;
276
- border: solid 2px transparent;
277
- border-right: none;
278
- border-top: none;
279
- transform: translate(3px, 4px) rotate(-45deg);
280
  }
281
 
282
  /* Checked, Indeterminate */
283
  .ce4wp-checkbox > input:checked,
284
  .ce4wp-checkbox > input:indeterminate {
285
- background-color: rgb(var(--pure-material-primary-rgb, 122, 76, 168));
286
  }
287
 
288
  .ce4wp-checkbox > input:checked + span::before,
289
  .ce4wp-checkbox > input:indeterminate + span::before {
290
- border-color: rgb(var(--pure-material-primary-rgb, 122, 76, 168));
291
- background-color: rgb(var(--pure-material-primary-rgb, 122, 76, 168));
292
  }
293
 
294
  .ce4wp-checkbox > input:checked + span::after,
295
  .ce4wp-checkbox > input:indeterminate + span::after {
296
- border-color: rgb(var(--pure-material-onprimary-rgb, 255, 255, 255));
297
  }
298
 
299
  .ce4wp-checkbox > input:indeterminate + span::after {
300
- border-left: none;
301
- transform: translate(4px, 3px);
302
  }
303
 
304
  /* Hover, Focus */
305
  .ce4wp-checkbox:hover > input {
306
- opacity: 0.04;
307
  }
308
 
309
  .ce4wp-checkbox > input:focus {
310
- opacity: 0.12;
311
  }
312
 
313
  .ce4wp-checkbox:hover > input:focus {
314
- opacity: 0.16;
315
  }
316
 
317
  /* Active */
318
  .ce4wp-checkbox > input:active {
319
- opacity: 1;
320
- transform: scale(0);
321
- transition: transform 0s, opacity 0s;
322
  }
323
 
324
  .ce4wp-checkbox > input:active + span::before {
325
- border-color: rgb(var(--pure-material-primary-rgb, 122, 76, 168));
326
  }
327
 
328
  .ce4wp-checkbox > input:checked:active + span::before {
329
- border-color: transparent;
330
- background-color: rgba(var(--pure-material-onsurface-rgb, 0, 0, 0), 0.6);
331
  }
332
 
333
  /* Disabled */
334
  .ce4wp-checkbox > input:disabled {
335
- opacity: 0;
336
  }
337
 
338
  .ce4wp-checkbox > input:disabled + span {
339
- color: rgba(var(--pure-material-onsurface-rgb, 0, 0, 0), 0.38);
340
- cursor: initial;
341
  }
342
 
343
  .ce4wp-checkbox > input:disabled + span::before {
344
- border-color: currentColor;
345
  }
346
 
347
  .ce4wp-checkbox > input:checked:disabled + span::before,
348
  .ce4wp-checkbox > input:indeterminate:disabled + span::before {
349
- border-color: transparent;
350
- background-color: currentColor;
351
  }
352
 
353
  .ce4wp-redirector {
354
- margin: 0 auto;
355
- position: relative;
356
- padding-top: 40px;
357
  }
358
  @media (min-width: 600px) {
359
- .ce4wp-redirector {
360
- max-width: 890px;
361
- padding-top: 72px;
362
- }
363
  }
364
 
365
  .ce4wp-mt-2,
366
  .ce4wp-my-2 {
367
- margin-top: .5rem !important;
368
  }
369
  .ce4wp-mb-2,
370
  .ce4wp-my-2 {
371
- margin-bottom: .5rem !important;
372
  }
373
 
374
  .ce4wp-mt-3,
375
  .ce4wp-my-3 {
376
- margin-top: 1rem !important;
377
  }
378
  .ce4wp-mb-3,
379
  .ce4wp-my-3 {
380
- margin-bottom: 1rem !important;
381
  }
382
 
383
  .ce4wp-mb-4,
384
  .ce4wp-my-4 {
385
- margin-bottom: 1.5rem !important;
386
  }
387
 
388
  .ce4wp-mt-4,
389
  .ce4wp-my-4 {
390
- margin-top: 1.5rem !important;
391
  }
392
 
393
  .ce4wp-pt-2,
394
  .ce4wp-py-2 {
395
- padding-top: .5rem !important;
396
  }
397
  .ce4wp-pb-2,
398
  .ce4wp-py-2 {
399
- padding-bottom: .5rem !important;
400
  }
401
 
402
  .ce4wp-pt-3,
403
  .ce4wp-py-3 {
404
- padding-top: 1rem !important;
405
  }
406
  .ce4wp-pb-3,
407
  .ce4wp-py-3 {
408
- padding-bottom: 1rem !important;
409
  }
410
 
411
  .ce4wp-pt-4,
412
  .ce4wp-py-4 {
413
- padding-top: 1.5rem !important;
414
  }
415
  .ce4wp-pb-4,
416
  .ce4wp-py-4 {
417
- padding-bottom: 1.5rem !important;
418
  }
419
 
420
  .ce4wp-pr-0,
421
  .ce4wp-px-0 {
422
- padding-right: 0rem !important;
423
  }
424
  .ce4wp-pl-0,
425
  .ce4wp-px-0 {
426
- padding-left: 0rem !important;
427
  }
428
 
429
  .ce4wp-pr-3,
430
  .ce4wp-px-3 {
431
- padding-right: 1rem !important;
432
  }
433
  .ce4wp-pl-3,
434
  .ce4wp-px-3 {
435
- padding-left: 1rem !important;
436
  }
437
  .ce4wp-pr-4,
438
  .ce4wp-px-4 {
439
- padding-right: 1.5rem !important;
440
  }
441
  .ce4wp-pl-4,
442
  .ce4wp-px-4 {
443
- padding-left: 1.5rem !important;
444
  }
445
 
446
  .ce4wp-pb-1,
447
  .ce4wp-py-1 {
448
- padding-bottom: 0.25rem !important;
449
  }
450
  .ce4wp-pt-1,
451
  .ce4wp-py-1 {
452
- padding-top: 0.25rem !important;
453
  }
454
  .ce4wp-m-0 {
455
- margin: 0 !important;
456
  }
457
 
458
  .ce4wp-p-3 {
459
- padding: 1rem !important;
460
  }
461
 
462
  .ce4wp-typography-root {
463
- margin: 0;
464
  }
465
 
466
  .ce4wp-typography-gutter-bottom {
467
- margin-bottom: 12px;
468
  }
469
 
470
  .ce4wp-typography-subtitle1 {
471
- color: rgba(0, 0, 0, 0.6);
472
- font-size: 16px;
473
- font-weight: 400;
474
- line-height: 24px;
475
  }
476
 
477
  .ce4wp-typography-root {
478
- margin: 0;
479
  }
480
 
481
  .ce4wp-typography-h1 {
482
- font-size: 36px;
483
- font-weight: 500;
484
- line-height: 40px;
485
  }
486
 
487
  .ce4wp-typography-h2 {
488
- font-size: 28px;
489
- font-weight: 500;
490
- line-height: 32px;
491
  }
492
 
493
  .ce4wp-typography-h4 {
494
- font-size: 16px;
495
- font-weight: 500;
496
- line-height: 20px;
497
  }
498
 
499
  .ce4wp-typography-h5 {
500
- font-size: 14px;
501
- font-weight: 400;
502
- line-height: 20px;
503
  }
504
 
505
  .ce4wp-typography-h6 {
506
- font-size: 18px;
507
- font-weight: 400;
508
- line-height: 24px;
509
- color: rgba(0, 0, 0, 0.6);
510
  }
511
 
512
  .ce4wp-typography-h6-darker {
513
- font-size: 18px;
514
- font-weight: 400;
515
- line-height: 24px;
516
- color: rgba(0, 0, 0, 0.9);
517
  }
518
 
519
  @media (max-width: 460px) {
520
- .ce4wp-typography-h1 {
521
- font-size: 28px;
522
- }
523
 
524
- .ce4wp-typography-h2 {
525
- font-size: 20px;
526
- }
527
- .ce4wp-typography-h4 {
528
- font-size: 12px;
529
- }
530
  }
531
 
532
  @media (max-width: 330px) {
533
- .ce4wp-typography-h1 {
534
- font-size: 24px;
535
- }
536
  }
537
 
538
  .ce4wp-typography-body {
539
- font-size: 16px;
540
  }
541
 
542
  .ce4wp_bold_link {
543
- font-weight: bold;
544
- text-decoration: underline;
545
  }
546
 
547
  .ce4wp-plugin-support-title {
548
- font-size: 18px;
549
- font-weight: bold;
550
- line-height: 20px;
551
- color: rgba(0, 0, 0, 0.9);
552
  }
553
 
554
  .ce4wp-list-root {
555
- margin: 0;
556
- padding-left: 0 !important;
557
- padding-right: 0 !important;
558
- position: relative;
559
- list-style: none;
560
  }
561
 
562
  .ce4wp-list-padding {
563
- padding-top: 8px;
564
- padding-bottom: 8px;
565
  }
566
 
567
  .ce4wp-list-item-gutters {
568
- padding-left: 8px;
569
- padding-right: 8px;
570
  }
571
  .ce4wp-list-item-root {
572
- width: 100%;
573
- display: flex;
574
- position: relative;
575
- box-sizing: border-box;
576
- min-height: 40px;
577
- text-align: left;
578
- align-items: center;
579
- padding-top: 8px;
580
- padding-bottom: 8px;
581
- justify-content: flex-start;
582
- text-decoration: none;
583
  }
584
  .ce4wp-list-item-text-root {
585
- flex: 1 1 auto;
586
- padding: 0;
587
- min-width: 0;
588
- margin-top: 4px;
589
- text-align: left;
590
- margin-bottom: 4px;
591
  }
592
 
593
  .ce4wp-svg-icon-root {
594
- fill: currentColor;
595
- width: 1em;
596
- height: 1em;
597
- display: inline-block;
598
- font-size: 1.5rem;
599
- transition: fill 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
600
- flex-shrink: 0;
601
- user-select: none;
602
  }
603
  .ce4wp-svg-icon-color {
604
- color: rgb(122,76,168);
605
  }
606
  .ce4wp-list-item-icon-root {
607
- align-self: start;
608
  }
609
 
610
  .ce4wp-flex-column {
611
- flex-direction: column !important;
612
  }
613
  .ce4wp-d-flex {
614
- display: flex !important;
615
  }
616
 
617
  .status-creativemail {
618
- font-size: 1.4em;
619
- display: block;
620
- text-indent: -9999px;
621
- position: relative;
622
- height: 1em;
623
- width: 1em;
624
  }
625
 
626
  .status-creativemail::before {
627
- background-image: url("../images/icon-small.png");
628
- background-size: contain;
629
- background-position-y: 50%;
630
- background-repeat: no-repeat;
631
- font-weight: 400;
632
- font-variant: normal;
633
- text-transform: none;
634
- line-height: 1;
635
- margin: 0;
636
- text-indent: 0;
637
- position: absolute;
638
- top: 0;
639
- left: 0;
640
- width: 100%;
641
- height: 100%;
642
- text-align: center;
643
- content: " ";
644
- color: transparent;
645
  }
646
 
647
  .ce4wp-card table.form-table input[type=text] {
648
- width: 100%;
649
- margin: 0;
650
- padding: 6px;
651
- box-sizing: border-box;
652
- vertical-align: top;
653
- }
654
 
655
  .ce4wp-swoosh-container {
656
- margin: 0 auto;
657
- position: relative;
658
  }
659
 
660
  .ce4wp-swoosh-header {
661
- align-items: center;
662
- display: flex;
663
- position: relative;
664
  }
665
 
666
  .ce4wp-swoosh-header::after {
667
- top: 0px;
668
- left: 0px;
669
- right: 0px;
670
- height: 350px;
671
- content: "";
672
- position: absolute;
673
- background-size: cover;
674
- background-color: transparent;
675
- background-image: url("../images/swoosh.svg");
676
- background-repeat: no-repeat;
677
- background-position: 100% 100%;
678
- bottom: auto !important;
679
  }
680
 
681
  .ce4wp-backdrop {
682
- padding: 0 20px;
683
  }
684
  @media (max-width:460px) {
685
- .ce4wp-backdrop {
686
- padding: 0 8px;
687
- }
688
  }
689
 
690
  .ce4wp-backdrop-container {
691
- margin: 0 auto;
692
- position: relative;
693
- padding-top: 40px;
694
  }
695
  @media (min-width:600px) {
696
- .ce4wp-backdrop-container {
697
- max-width: 890px;
698
- }
699
  }
700
  .ce4wp-backdrop-header {
701
- margin-bottom: 20px;
702
  }
703
 
704
  .ce4wp-logo-poppins {
705
- background-image: url("../images/logo.svg");
706
- background-size: contain;
707
- background-position-y: 50%;
708
- width: 272px;
709
- height: 72px;
710
- background-repeat: no-repeat;
711
  }
712
 
713
  .ce4wp-airplane {
714
- position: absolute;
715
- right: 48px;
716
- top: 40px;
717
- z-index: 10;
718
  }
719
  @media (max-width:450px) {
720
- .ce4wp-airplane {
721
- right: -20px;
722
- top: 65px;
723
- width: 32%;
724
- }
725
  }
726
  @media (max-width:330px) {
727
- .ce4wp-logo-poppins {
728
- width: 250px;
729
- }
730
  }
731
 
732
  p.ce4wp-subtitle {
733
- color: rgba(0,0,0,0.6);
734
- font-size: 24px;
735
- line-height: 28px;
736
- font-weight: 400;
737
  }
738
 
739
  .ce4wp-body2 {
740
- color: rgba(38, 46, 57, 0.7);
741
- font-size: 14px;
742
- font-weight: 400;
743
- line-height: 20px;
744
  }
745
 
746
  @media (max-width:450px) {
747
- .ce4wp-body2 {
748
- font-size: 12px;
749
- }
750
  }
751
 
752
  .ce4wp-Svgicon-root {
753
- fill: currentColor;
754
- width: 1em;
755
- height: 1em;
756
- display: inline-block;
757
- font-size: 1.5rem;
758
- transition: fill 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
759
- flex-shrink: 0;
760
- user-select: none;
761
  }
762
 
763
  .ce4wp-grid {
764
- width: 100%;
765
- display: flex;
766
- flex-wrap: wrap;
767
- box-sizing: border-box;
768
- width: calc(100% + 16px);
769
- margin: -8px;
770
  }
771
  @media (max-width:450px) {
772
- .ce4wp-grid {
773
- margin: 0;
774
- }
775
  }
776
 
777
  .ce4wp-grid-item {
778
- margin: 0;
779
- box-sizing: border-box;
780
- flex-grow: 0;
781
- max-width: 33.333333%;
782
- flex-basis: 33.333333%;
783
- padding: 8px;
784
  }
785
 
786
  .ce4wp-grid-xs-2 {
787
- flex-grow: 0;
788
- max-width: 16.666667%;
789
- flex-basis: 16.666667%;
790
  }
791
 
792
  .ce4wp-grid-xs-8 {
793
- flex-grow: 0;
794
- max-width: 66.666667%;
795
- flex-basis: 66.666667%;
796
  }
797
 
798
  .ce4wp-grid-xs-10 {
799
- flex-grow: 0;
800
- max-width: 83.333333%;
801
- flex-basis: 83.333333%;
802
  }
803
 
804
  @media (max-width:800px) {
805
- .ce4wp-grid-item {
806
- max-width: none;
807
- flex-basis: 100%;
808
- }
809
  }
810
 
811
  .ce4wp-grid-item-card {
812
- box-sizing: inherit;
813
- margin-bottom: 1.5rem !important;
814
- color: rgba(0, 0, 0, 0.9);
815
- transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, background-color 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
816
- border-radius: 4px;
817
- overflow: hidden;
818
- position: relative;
819
- min-width: 200px;
820
- background: #fff;
821
- box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
822
  }
823
  @media (min-width:800px) {
824
- .ce4wp-grid-item-card {
825
- min-height: 150px;
826
- }
827
  }
828
  @media (max-width:800px) {
829
- .ce4wp-grid-item-card {
830
- display: flex;
831
- }
832
  }
833
 
834
  @media (max-width:450px) {
835
- .ce4wp-grid-item-card {
836
- margin: 0 !important;
837
- }
838
  }
839
 
840
  .ce4wp-grid-item-card:hover {
841
- cursor: pointer;
842
- box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.1);
843
- background-color: rgba(0, 0, 0, 0.03);
844
  }
845
  #skeleton .ce4wp-grid-item-card:hover {
846
- cursor: default;
847
- background-color: initial;
848
- box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
849
  }
850
  .ce4wp-grid-item-card-media {
851
- display: block;
852
- background-size: 80% 80%;
853
- background-repeat: no-repeat;
854
- background-position: center;
855
- height: 0px;
856
- padding-top: 56.25%;
857
- background-color: #E7E2F6;
858
  }
859
 
860
  @media (max-width:800px) {
861
- .ce4wp-grid-item-card-media {
862
- height: auto;
863
- padding-left: 30%;
864
- padding-top: initial;
865
- }
866
  }
867
 
868
  .ce4wp-grid-item-card-content-root {
869
- padding: 16px;
870
- padding-bottom: 24px;
871
- width: 100%;
872
- box-sizing: border-box;
873
  }
874
 
875
  @media (max-width: 450px){
876
- .ce4wp-grid-item-card-content-root {
877
- padding: 5px;
878
- padding-bottom: 5px;
879
- }
880
  }
881
 
882
  .skeleton-pulse {
883
- animation: skeleton-keyframes-pulse 1.5s ease-in-out 0.5s infinite;
884
  }
885
  @keyframes skeleton-keyframes-pulse {
886
- 0% {
887
- opacity: 1;
888
- }
889
- 50% {
890
- opacity: 0.4;
891
- }
892
- 100% {
893
- opacity: 1;
894
- }
895
  }
896
 
897
  .ce4wp-subapps-skeleton {
898
- height: 24px;
899
- width: 200px;
900
- background-color: #F5F5F5;
901
  }
902
 
903
  .ce4wp-grid-item-card-media-skeleton {
904
- background-color: #E4E4E4;
905
  }
906
 
907
  .ce4wp-grid-item-card-content-skeleton-title {
908
- height: 20px;
909
- width: 100%;
910
- background-color: #F5F5F5;
911
  }
912
 
913
  .ce4wp-grid-item-card-content-skeleton-description {
914
- height: 36px;
915
- width: 100%;
916
- background-color: #F5F5F5;
917
- margin-top: 4px;
918
  }
919
 
920
  .ce4wp-dialog-root {
921
- position: fixed;
922
- z-index: 1300;
923
- right: 0px;
924
- bottom: 0px;
925
- top: 0px;
926
- left: 0px;
927
  }
928
  .ce4wp-dialog-root * {
929
- box-sizing: border-box;
930
  }
931
  .ce4wp-backdrop-root {
932
- top: 0;
933
- left: 0;
934
- right: 0;
935
- bottom: 0;
936
- display: flex;
937
- z-index: -1;
938
- position: fixed;
939
- background: rgba(49, 57, 68, .7);
940
- align-items: center;
941
- justify-content: center;
942
- background-color: rgba(0, 0, 0, 0.5);
943
- -webkit-tap-highlight-color: transparent;
944
- transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
945
  }
946
 
947
  .ce4wp-dialog-container {
948
- height: 100%;
949
- outline: 0;
950
- transform: none;
951
- transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
952
- transform 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
953
- display: flex;
954
- align-items: center;
955
- justify-content: center;
956
  }
957
 
958
  .ce4wp-dialog-wrapper {
959
- height: auto;
960
- max-height: calc(100% - 64px);
961
- width: calc(100% - 64px);
962
- max-width: 600px;
963
- overflow: hidden;
964
- transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
965
- transform: translate3d(0, 0, 0);
966
- box-shadow: 0px 11px 15px -7px rgba(0,0,0,0.2), 0px 24px 38px 3px rgba(0,0,0,0.14), 0px 9px 46px 8px rgba(0,0,0,0.12);
967
- display: flex;
968
- flex-direction: column;
969
- margin: 32px;
970
- position: relative;
971
- overflow-y: auto;
972
- border-radius: 4px;
973
- color: rgba(0,0,0,0.9);
974
- background-color: #fff;
975
  }
976
 
977
  .ce4wp-dialog-header {
978
- width: 100%;
979
- padding: 12px;
980
- min-height: 64px;
981
- position: fixed;
982
- top: 0px;
983
- left: 0px;
984
- z-index: 10;
985
- display: flex;
986
- align-items: flex-start;
987
- vertical-align: middle;
988
- justify-content: space-between;
989
- border-bottom: 1px solid rgba(0, 0, 0, 0.1);
990
- background: rgb(246, 246, 246);
991
  }
992
 
993
  .ce4wp-show-me-how-modal .ce4wp-dialog-header {
994
- height: 180px;
995
  }
996
 
997
  .ce4wp-show-me-how-modal .ce4wp-dialog-header-close{
998
- align-self: initial;
999
- vertical-align: initial;
1000
  }
1001
 
1002
  .ce4wp-dialog-header-title {
1003
- display: flex;
1004
- align-self: center;
1005
- align-items: center;
1006
- vertical-align: middle;
1007
- justify-content: flex-start;
1008
  }
1009
 
1010
  .ce4wp-dialog-header-close,
1011
  .ce4wp-dialog-footer-close {
1012
- display: flex;
1013
- align-self: center;
1014
- align-items: center;
1015
- vertical-align: middle;
1016
- justify-content: flex-end;
1017
- margin-left: auto;
1018
  }
1019
 
1020
  .ce4wp-dialog-header-title-wrapper {
1021
- display: flex;
1022
- align-items: center;
1023
- vertical-align: middle;
1024
- justify-content: flex-start;
1025
  }
1026
 
1027
  .ce4wp-dialog-header-title-wrapper > :last-of-type {
1028
- margin-right: 0px !important;
1029
  }
1030
 
1031
  .ce4wp-dialog-header-title-wrapper > :first-of-type {
1032
- margin-left: 0px !important;
1033
  }
1034
 
1035
  .ce4wp-dialog-header-title-wrapper > * {
1036
- display: inline-block;
1037
- vertical-align: top;
1038
- margin: 0px 0px 0px 8px !important;
1039
  }
1040
 
1041
  .ce4wp-dialog-header-title-wrapper-content {
1042
- padding-left: 12px;
1043
- overflow: hidden;
1044
- text-overflow: ellipsis;
1045
- display: -webkit-box;
1046
- -webkit-box-orient: vertical;
1047
- -webkit-line-clamp: 3;
1048
- line-height: 24px;
1049
- max-height: 72px;
1050
  }
1051
 
1052
  .ce4wp-dialog-header-close-wrapper,
1053
  .ce4wp-dialog-footer-close-wrapper {
1054
- display: flex;
1055
- align-items: center;
1056
- vertical-align: middle;
1057
- justify-content: center;
1058
  }
1059
  .ce4wp-dialog-header-close-wrapper {
1060
- width: 40px;
1061
- height: 40px;
1062
- cursor: pointer;
1063
  }
1064
 
1065
  .ce4wp-dialog-header-close-wrapper:hover {
1066
- background-color: rgba(0, 0, 0, 0.04);
1067
  }
1068
  .ce4wp-dialog-header-close-wrapper {
1069
- flex: 0 0 auto;
1070
- color: rgba(0, 0, 0, 0.54);
1071
- padding: 8px;
1072
- overflow: visible;
1073
- font-size: 1.5rem;
1074
- text-align: center;
1075
- transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
1076
- border-radius: 4px;
1077
  }
1078
 
1079
  .ce4wp-dialog-content {
1080
- flex: 1 1 auto;
1081
- overflow-y: auto;
1082
- position: relative;
1083
- height: auto;
1084
- margin-top: 64px;
1085
- padding: 24px;
1086
  }
1087
 
1088
  .ce4wp-show-me-how-modal .ce4wp-dialog-content {
1089
- margin-top: 180px;
1090
  }
1091
 
1092
  .ce4wp-consent {
1093
- background-color: rgba(122, 92, 189, 0.1);
1094
- border: 1px solid rgb(209, 179, 238);
1095
- border-radius: 2px;
1096
- padding: 16px;
1097
- margin-bottom: 12px;
1098
  }
1099
 
1100
  .ce4wp-dialog-footer {
1101
- display: flex;
1102
- flex: 0 0 auto;
1103
- align-items: center;
1104
- justify-content: space-between;
1105
- z-index: 1;
1106
- padding: 8px;
1107
- background: rgb(255, 255, 255);
1108
- border-top: 1px solid rgba(0, 0, 0, 0.1);
1109
  }
1110
  #ce4wp_admin_dashboard_widget .floater {
1111
- float:right;
1112
  }
1113
  .ce4wp_dashboard_icon {
1114
- background-image: url(../images/admin-dashboard-widget/logo.svg);
1115
- height: 1.1em;
1116
- width: 130px;
1117
- background-size: cover;
1118
- background-repeat: no-repeat;
1119
- float: right;
1120
- margin-left: 5px;
1121
  }
1122
 
1123
  .ce4wp-settings-card{
1124
- padding: 8px 16px;
1125
- cursor: pointer;
1126
- border: 1px solid rgba(0,0,0,0.1);
1127
- margin: 1px;
1128
- border-radius: 4px;
1129
  }
1130
 
1131
  .ce4wp-selected{
1132
- border: 2px solid #A78AE8;
1133
- margin: 0;
1134
  }
1135
 
1136
  .ce4wp-settings-card:hover {
1137
- background-color: rgba(122,92,189,0.1);
1138
  }
1139
  .ce4wp-settings-card-image{
1140
- height: 32px;
1141
- width: 32px;
1142
- margin: 8px 0;
1143
- background-size: contain;
1144
  }
1145
 
1146
  .ce4wp-settings-card-title{
1147
- line-height: 48px;
1148
  }
1149
 
1150
  .ce4wp-settings-card-link{
1151
- visibility: hidden;
1152
- background-image: url(../images/launch-grey.svg);
1153
- fill: #6f6f6f;
1154
- height: 24px;
1155
- width: 24px;
1156
- margin-top: 12px;
1157
  }
1158
 
1159
  .ce4wp-settings-card:hover .ce4wp-settings-card-link{
1160
- visibility: visible;
1161
  }
1162
 
1163
  .ce4wp-show-on-mobile{
1164
- display: none;
1165
  }
1166
  @media (max-width: 450px) {
1167
- .ce4wp-hide-on-mobile{
1168
- display: none;
1169
- }
1170
- .ce4wp-show-on-mobile{
1171
- display: initial;
1172
- }
1173
  }
1174
 
1175
  .ce4wp-loader{
1176
- color: #0076DF;
1177
- animation: ce4wp-loader-rotate 1.4s linear infinite;
1178
- animation-duration: 1.4s;
1179
- animation-timing-function: linear;
1180
- animation-delay: 0s;
1181
- animation-iteration-count: infinite;
1182
- animation-direction: normal;
1183
- animation-fill-mode: none;
1184
- animation-play-state: running;
1185
- animation-name: ce4wp-loader-rotate;
1186
- margin: 0 auto;
1187
  }
1188
 
1189
  .ce4wp-notice {
1190
- border-left: 0;
1191
- background-repeat: no-repeat;
1192
- background-size: contain;
1193
- display: flex;
1194
- height: 175px;
1195
- position: relative;
1196
- margin-right: var(--large-gap);
1197
- margin-bottom: 20px;
1198
- max-width: 100%;
1199
  }
1200
 
1201
  .ce4wp-notice-primary {
1202
- background-color: #7A5CBD;
1203
- background-image: url(../images/woocommerce-banners/bg-blob.png);
1204
  }
1205
 
1206
  .ce4wp-notice-primary #close::before {
1207
- color:white !important;
1208
  }
1209
 
1210
  .ce4wp-notice-secondary {
1211
- background-color: #B5E5E7;
1212
- background-image: url(../images/woocommerce-banners/bg-blob.png);
1213
- padding: 0 0 0 50px;
1214
  }
1215
 
1216
  .ce4wp-notice-secondary section h1 {
1217
- color: black !important;
1218
  }
1219
 
1220
  .ce4wp-notice-secondary section p {
1221
- color: black !important;
1222
  }
1223
 
1224
  .ce4wp-notice img {
1225
- max-height: 150px;
1226
- margin-top: 25px;
1227
- margin-left: 20px;
1228
  }
1229
  .ce4wp-notice section {
1230
- margin-left: 40px;
1231
- margin-top: 2px;
1232
  }
1233
 
1234
  .ce4wp-notice section h1 {
1235
- color:white;
1236
- margin-top: 1em;
1237
  }
1238
  .ce4wp-notice section p {
1239
- color:white;
1240
- font-size: 17px;
1241
- line-height: 1;
1242
  }
1243
 
1244
  .ce4wp-notice section button {
1245
- color:black !important;
1246
- background: white !important;
1247
- border-color: white !important;
1248
  }
1249
 
1250
  .ce4wp-notice #close {
1251
- width: 16px;
1252
- height: 16px;
1253
- margin-left: 0.3em;
1254
- cursor: pointer;
1255
- position: absolute;
1256
- top: 10px;
1257
- right: 10px;
1258
  }
1259
 
1260
  .ce4wp-notice #close::before {
1261
- color: #6f6f6f;
1262
- font: 400 21px/1 dashicons;
1263
- content: '\f158';
1264
  }
1265
 
1266
 
1267
  .ce4wp-hidden {
1268
- display: none;
1269
  }
1270
 
1271
  .ce4wp-loader circle {
1272
- animation: ce4wp-loader-circular-dash 1.4s ease-in-out infinite;
1273
- animation-duration: 1.4s;
1274
- animation-timing-function: ease-in-out;
1275
- animation-delay: 0s;
1276
- animation-iteration-count: infinite;
1277
- animation-direction: normal;
1278
- animation-fill-mode: none;
1279
- animation-play-state: running;
1280
- animation-name: ce4wp-loader-circular-dash;
1281
- stroke-dasharray: 80px, 200px;
1282
- stroke-dashoffset: 0px;
1283
- stroke: currentColor;
1284
  }
1285
 
1286
  .ce4wp-banner {
1287
- background-color: #7A5CBD;
1288
- color: white;
1289
- padding: 12px;
1290
- border-radius: 4px;
1291
- margin-top: 25px;
1292
- display: flex;
1293
- flex-direction: row;
1294
  }
1295
 
1296
  .ce4wp-banner .ce4wp-content {
1297
- margin-left: 20px;
1298
  }
1299
 
1300
  .ce4wp-banner .ce4wp-content h2,.ce4wp-banner .ce4wp-content a{
1301
- color: white
1302
  }
1303
 
1304
  .ce4wp-banner .ce4wp-content a {
1305
- text-decoration: underline;
1306
- font-weight: 600;
1307
  }
1308
 
1309
  .ce4wp-banner .ce4wp-content a:hover {
@@ -1313,29 +1313,29 @@ p.ce4wp-subtitle {
1313
 
1314
 
1315
  .ce4wp-ml-6 {
1316
- margin-left: 24px;
1317
  }
1318
 
1319
  .ce4wp-show-me-how-screenshot{
1320
- max-width: 280px;
1321
  }
1322
 
1323
  @keyframes ce4wp-loader-rotate {
1324
- 0% {transform-origin: 50% 50%;}
1325
- 100% {transform: rotate(360deg)};
1326
  }
1327
 
1328
  @keyframes ce4wp-loader-circular-dash {
1329
- 0% {
1330
- stroke-dasharray: 1px, 200px;
1331
- stroke-dashoffset: 0px;
1332
- }
1333
- 50% {
1334
- stroke-dasharray: 100px, 200px;
1335
- stroke-dashoffset: -15px;
1336
- }
1337
- 100% {
1338
- stroke-dasharray: 100px, 200px;
1339
- stroke-dashoffset: -125px;
1340
- }
1341
- }
1
  .ce4wp-admin-wrapper {
2
+ margin-right: 20px;
3
+ margin-top: 20px;
4
+ font-size: 14px;
5
+ font-family: 'Poppins', sans-serif;
6
  }
7
  @media (max-width:460px) {
8
+ .ce4wp-admin-wrapper {
9
+ margin-right: 10px;
10
+ }
11
  }
12
 
13
  .ce4wp-card {
14
+ background-attachment:scroll;
15
+ background-clip:border-box;
16
+ background-color:rgb(255, 255, 255);
17
+ background-image:none;
18
+ background-origin:padding-box;
19
+ background-position-x:0%;
20
+ background-position-y:0%;
21
+ background-size:auto;
22
+ border-radius: 4px;
23
+ box-shadow:rgba(0, 0, 0, 0.06) 0px 0px 0px 1px, rgba(0, 0, 0, 0.05) 0px 2px 4px 0px, rgba(0, 0, 0, 0.08) 0px 2px 1px 0px;
24
+ box-sizing:border-box;
25
+ color:rgba(0, 0, 0, 0.9);
26
+ display:block;
27
+ font-size:15px;
28
+ letter-spacing:normal;
29
+ margin-bottom:24px;
30
+ min-height:150px;
31
+ min-width:200px;
32
+ overflow: hidden;
33
+ position:relative;
34
+ transition-delay:0s;
35
+ transition-duration:0.3s;
36
+ transition-property:box-shadow;
37
+ transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);
38
+ -webkit-font-smoothing:antialiased;
39
+ padding: 15px;
40
  }
41
 
42
  @media (max-width: 450px){
43
+ .ce4wp-card{
44
+ padding: 0;
45
+ }
46
  }
47
 
48
  .ce4wp-card ul {
49
+ padding-left: 10px;
50
  }
51
  .ce4wp-card ul li {
52
+ font-size: 14px;
53
+ font-weight: 400;
54
  }
55
 
56
  .ce4wp-card .ce4wp-kvp {
57
+ margin-top: 10px;
58
  }
59
 
60
  .ce4wp-card .ce4wp-kvp h6 {
61
+ margin: 0;
62
  }
63
 
64
  .ce4wp-button-base-root {
65
+ color: inherit;
66
+ border: 0;
67
+ cursor: pointer;
68
+ margin: 0;
69
+ display: inline-flex;
70
+ outline: 0;
71
+ padding: 0;
72
+ position: relative;
73
+ align-items: center;
74
+ user-select: none;
75
+ border-radius: 0;
76
+ vertical-align: middle;
77
+ -moz-appearance: none;
78
+ justify-content: center;
79
+ text-decoration: none;
80
+ background-color: transparent;
81
+ -webkit-appearance: none;
82
+ -webkit-tap-highlight-color: transparent;
83
  }
84
  #skeleton .ce4wp-button-base-root {
85
+ cursor: default;
86
  }
87
  .ce4wp-button-root {
88
+ color: rgba(0, 0, 0, 0.9);
89
+ height: 40px;
90
+ padding: 6px 16px;
91
+ shadows: none;
92
+ font-size: 14px;
93
+ min-width: auto;
94
+ box-shadow: none;
95
+ box-sizing: border-box;
96
+ transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
97
+ box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
98
+ border 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
99
+ font-weight: 500;
100
+ line-height: inherit;
101
+ border-radius: 4px;
102
+ text-transform: none;
103
  }
104
 
105
  .ce4wp-button-contained {
106
+ color: rgba(0, 0, 0, 0.87);
107
+ box-shadow: none;
108
+ text-transform: none;
109
+ background-color: #e0e0e0;
110
  }
111
  .ce4wp-button-contained-orange {
112
+ color: #784100;
113
+ border: 1px solid #FFB800;
114
+ font-size: 14px;
115
+ font-weight: 700;
116
+ background-color: #FFB800;
117
  }
118
 
119
  .ce4wp-button-contained-primary {
120
+ color: #ffffff;
121
+ border: 1px solid #7A4CA8;
122
+ font-size: 14px;
123
+ font-weight: 700;
124
+ background-color: #7A4CA8;
125
  }
126
 
127
  .ce4wp-button-contained-primary:hover {
128
+ box-shadow: none;
129
+ background-color: #663399;
130
+ color: rgba(255, 255, 255, 0.7);
131
  }
132
  .ce4wp-button-label {
133
+ width: 100%;
134
+ display: inherit;
135
+ align-items: inherit;
136
+ justify-content: inherit;
137
  }
138
  .ce4wp-button-endIcon {
139
+ display: inherit;
140
+ margin-left: 8px;
141
+ margin-right: -4px;
142
  }
143
 
144
  .ce4wp-button-outlined {
145
+ border: 1px solid rgba(0, 0, 0, 0.23);
146
+ padding: 5px 15px;
147
  }
148
  .ce4wp-button-outlined-primary {
149
+ color: #7A4CA8;
150
+ border: 1px solid #7A4CA8;
151
  }
152
  .ce4wp-button-outlined-primary:hover {
153
+ border: 1px solid #7A4CA8;
154
+ background-color: rgba(122, 76, 168, 0.04);
155
+ color: #7A4CA8;
156
  }
157
 
158
  .ce4wp-button-text-primary {
159
+ align-items: center;
160
+ background-color: rgba(0, 0, 0, 0);
161
+ border-radius: 4px;
162
+ border-style: none;
163
+ border-width: 0;
164
+ box-shadow: none;
165
+ box-sizing: border-box;
166
+ color: rgb(122,76,168);
167
+ cursor: pointer;
168
+ display: inline-flex;
169
+ font-size: 14px;
170
+ font-style: normal;
171
+ font-weight: 700;
172
+ height: 40px;
173
+ justify-content: center;
174
+ line-height: 20px;
175
+ margin: 0px;
176
+ min-width: 0px;
177
+ padding: 6px 8px;
178
+ position: relative;
179
+ text-align: center;
180
+ transition-delay: 0s, 0s, 0s;
181
+ transition-duration: 0.25s, 0.25s, 0.25s;
182
+ transition-property: background-color, box-shadow, border;
183
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1), cubic-bezier(0.4, 0, 0.2, 1), cubic-bezier(0.4, 0, 0.2, 1);
184
+ user-select: none;
185
+ vertical-align: middle;
186
+ white-space: nowrap;
187
  }
188
 
189
  .ce4wp-button-text-primary:hover {
190
+ background-color: rgba(122,76,168, 0.04);
191
  }
192
 
193
  .ce4wp-button-text-primary.destructive {
194
+ color: #D42424;
195
  }
196
 
197
  .ce4wp-button-text-primary.destructive:hover {
198
+ background-color: rgba(212, 36, 36, 0.1);
199
  }
200
 
201
  .ce4wp-right {
202
+ float: right;
203
  }
204
 
205
  .ce4wp-left {
206
+ float: left;
207
  }
208
 
209
  .ce4wp-inline-block {
210
+ display: inline-block;
211
  }
212
 
213
  .ce4wp-checkbox {
214
+ z-index: 0;
215
+ position: relative;
216
+ display: inline-block;
217
+ color: rgba(var(--pure-material-onsurface-rgb, 0, 0, 0), 0.87);
218
+ font-size: 14px;
219
+ line-height: 1.5;
220
  }
221
 
222
  /* Input */
223
  .ce4wp-checkbox > input {
224
+ appearance: none;
225
+ -moz-appearance: none;
226
+ -webkit-appearance: none;
227
+ z-index: -1;
228
+ position: absolute;
229
+ left: -10px;
230
+ top: -8px;
231
+ display: block;
232
+ margin: 0;
233
+ border-radius: 50%;
234
+ width: 40px;
235
+ height: 40px;
236
+ background-color: rgba(var(--pure-material-onsurface-rgb, 0, 0, 0), 0.6);
237
+ box-shadow: none;
238
+ outline: none;
239
+ opacity: 0;
240
+ transform: scale(1);
241
+ pointer-events: none;
242
+ transition: opacity 0.3s, transform 0.2s;
243
  }
244
 
245
  /* Span */
246
  .ce4wp-checkbox > span {
247
+ display: inline-block;
248
+ width: 100%;
249
+ cursor: pointer;
250
  }
251
 
252
  /* Box */
253
  .ce4wp-checkbox > span::before {
254
+ content: "";
255
+ display: inline-block;
256
+ box-sizing: border-box;
257
+ margin: 3px 11px 3px 1px;
258
+ border: solid 2px; /* Safari */
259
+ border-color: rgba(var(--pure-material-onsurface-rgb, 0, 0, 0), 0.6);
260
+ border-radius: 2px;
261
+ width: 18px;
262
+ height: 18px;
263
+ vertical-align: top;
264
+ transition: border-color 0.2s, background-color 0.2s;
265
  }
266
 
267
  /* Checkmark */
268
  .ce4wp-checkbox > span::after {
269
+ content: "";
270
+ display: block;
271
+ position: absolute;
272
+ top: 3px;
273
+ left: 1px;
274
+ width: 10px;
275
+ height: 5px;
276
+ border: solid 2px transparent;
277
+ border-right: none;
278
+ border-top: none;
279
+ transform: translate(3px, 4px) rotate(-45deg);
280
  }
281
 
282
  /* Checked, Indeterminate */
283
  .ce4wp-checkbox > input:checked,
284
  .ce4wp-checkbox > input:indeterminate {
285
+ background-color: rgb(var(--pure-material-primary-rgb, 122, 76, 168));
286
  }
287
 
288
  .ce4wp-checkbox > input:checked + span::before,
289
  .ce4wp-checkbox > input:indeterminate + span::before {
290
+ border-color: rgb(var(--pure-material-primary-rgb, 122, 76, 168));
291
+ background-color: rgb(var(--pure-material-primary-rgb, 122, 76, 168));
292
  }
293
 
294
  .ce4wp-checkbox > input:checked + span::after,
295
  .ce4wp-checkbox > input:indeterminate + span::after {
296
+ border-color: rgb(var(--pure-material-onprimary-rgb, 255, 255, 255));
297
  }
298
 
299
  .ce4wp-checkbox > input:indeterminate + span::after {
300
+ border-left: none;
301
+ transform: translate(4px, 3px);
302
  }
303
 
304
  /* Hover, Focus */
305
  .ce4wp-checkbox:hover > input {
306
+ opacity: 0.04;
307
  }
308
 
309
  .ce4wp-checkbox > input:focus {
310
+ opacity: 0.12;
311
  }
312
 
313
  .ce4wp-checkbox:hover > input:focus {
314
+ opacity: 0.16;
315
  }
316
 
317
  /* Active */
318
  .ce4wp-checkbox > input:active {
319
+ opacity: 1;
320
+ transform: scale(0);
321
+ transition: transform 0s, opacity 0s;
322
  }
323
 
324
  .ce4wp-checkbox > input:active + span::before {
325
+ border-color: rgb(var(--pure-material-primary-rgb, 122, 76, 168));
326
  }
327
 
328
  .ce4wp-checkbox > input:checked:active + span::before {
329
+ border-color: transparent;
330
+ background-color: rgba(var(--pure-material-onsurface-rgb, 0, 0, 0), 0.6);
331
  }
332
 
333
  /* Disabled */
334
  .ce4wp-checkbox > input:disabled {
335
+ opacity: 0;
336
  }
337
 
338
  .ce4wp-checkbox > input:disabled + span {
339
+ color: rgba(var(--pure-material-onsurface-rgb, 0, 0, 0), 0.38);
340
+ cursor: initial;
341
  }
342
 
343
  .ce4wp-checkbox > input:disabled + span::before {
344
+ border-color: currentColor;
345
  }
346
 
347
  .ce4wp-checkbox > input:checked:disabled + span::before,
348
  .ce4wp-checkbox > input:indeterminate:disabled + span::before {
349
+ border-color: transparent;
350
+ background-color: currentColor;
351
  }
352
 
353
  .ce4wp-redirector {
354
+ margin: 0 auto;
355
+ position: relative;
356
+ padding-top: 40px;
357
  }
358
  @media (min-width: 600px) {
359
+ .ce4wp-redirector {
360
+ max-width: 890px;
361
+ padding-top: 72px;
362
+ }
363
  }
364
 
365
  .ce4wp-mt-2,
366
  .ce4wp-my-2 {
367
+ margin-top: .5rem !important;
368
  }
369
  .ce4wp-mb-2,
370
  .ce4wp-my-2 {
371
+ margin-bottom: .5rem !important;
372
  }
373
 
374
  .ce4wp-mt-3,
375
  .ce4wp-my-3 {
376
+ margin-top: 1rem !important;
377
  }
378
  .ce4wp-mb-3,
379
  .ce4wp-my-3 {
380
+ margin-bottom: 1rem !important;
381
  }
382
 
383
  .ce4wp-mb-4,
384
  .ce4wp-my-4 {
385
+ margin-bottom: 1.5rem !important;
386
  }
387
 
388
  .ce4wp-mt-4,
389
  .ce4wp-my-4 {
390
+ margin-top: 1.5rem !important;
391
  }
392
 
393
  .ce4wp-pt-2,
394
  .ce4wp-py-2 {
395
+ padding-top: .5rem !important;
396
  }
397
  .ce4wp-pb-2,
398
  .ce4wp-py-2 {
399
+ padding-bottom: .5rem !important;
400
  }
401
 
402
  .ce4wp-pt-3,
403
  .ce4wp-py-3 {
404
+ padding-top: 1rem !important;
405
  }
406
  .ce4wp-pb-3,
407
  .ce4wp-py-3 {
408
+ padding-bottom: 1rem !important;
409
  }
410
 
411
  .ce4wp-pt-4,
412
  .ce4wp-py-4 {
413
+ padding-top: 1.5rem !important;
414
  }
415
  .ce4wp-pb-4,
416
  .ce4wp-py-4 {
417
+ padding-bottom: 1.5rem !important;
418
  }
419
 
420
  .ce4wp-pr-0,
421
  .ce4wp-px-0 {
422
+ padding-right: 0rem !important;
423
  }
424
  .ce4wp-pl-0,
425
  .ce4wp-px-0 {
426
+ padding-left: 0rem !important;
427
  }
428
 
429
  .ce4wp-pr-3,
430
  .ce4wp-px-3 {
431
+ padding-right: 1rem !important;
432
  }
433
  .ce4wp-pl-3,
434
  .ce4wp-px-3 {
435
+ padding-left: 1rem !important;
436
  }
437
  .ce4wp-pr-4,
438
  .ce4wp-px-4 {
439
+ padding-right: 1.5rem !important;
440
  }
441
  .ce4wp-pl-4,
442
  .ce4wp-px-4 {
443
+ padding-left: 1.5rem !important;
444
  }
445
 
446
  .ce4wp-pb-1,
447
  .ce4wp-py-1 {
448
+ padding-bottom: 0.25rem !important;
449
  }
450
  .ce4wp-pt-1,
451
  .ce4wp-py-1 {
452
+ padding-top: 0.25rem !important;
453
  }
454
  .ce4wp-m-0 {
455
+ margin: 0 !important;
456
  }
457
 
458
  .ce4wp-p-3 {
459
+ padding: 1rem !important;
460
  }
461
 
462
  .ce4wp-typography-root {
463
+ margin: 0;
464
  }
465
 
466
  .ce4wp-typography-gutter-bottom {
467
+ margin-bottom: 12px;
468
  }
469
 
470
  .ce4wp-typography-subtitle1 {
471
+ color: rgba(0, 0, 0, 0.6);
472
+ font-size: 16px;
473
+ font-weight: 400;
474
+ line-height: 24px;
475
  }
476
 
477
  .ce4wp-typography-root {
478
+ margin: 0;
479
  }
480
 
481
  .ce4wp-typography-h1 {
482
+ font-size: 36px;
483
+ font-weight: 500;
484
+ line-height: 40px;
485
  }
486
 
487
  .ce4wp-typography-h2 {
488
+ font-size: 28px;
489
+ font-weight: 500;
490
+ line-height: 32px;
491
  }
492
 
493
  .ce4wp-typography-h4 {
494
+ font-size: 16px;
495
+ font-weight: 500;
496
+ line-height: 20px;
497
  }
498
 
499
  .ce4wp-typography-h5 {
500
+ font-size: 14px;
501
+ font-weight: 400;
502
+ line-height: 20px;
503
  }
504
 
505
  .ce4wp-typography-h6 {
506
+ font-size: 18px;
507
+ font-weight: 400;
508
+ line-height: 24px;
509
+ color: rgba(0, 0, 0, 0.6);
510
  }
511
 
512
  .ce4wp-typography-h6-darker {
513
+ font-size: 18px;
514
+ font-weight: 400;
515
+ line-height: 24px;
516
+ color: rgba(0, 0, 0, 0.9);
517
  }
518
 
519
  @media (max-width: 460px) {
520
+ .ce4wp-typography-h1 {
521
+ font-size: 28px;
522
+ }
523
 
524
+ .ce4wp-typography-h2 {
525
+ font-size: 20px;
526
+ }
527
+ .ce4wp-typography-h4 {
528
+ font-size: 12px;
529
+ }
530
  }
531
 
532
  @media (max-width: 330px) {
533
+ .ce4wp-typography-h1 {
534
+ font-size: 24px;
535
+ }
536
  }
537
 
538
  .ce4wp-typography-body {
539
+ font-size: 16px;
540
  }
541
 
542
  .ce4wp_bold_link {
543
+ font-weight: bold;
544
+ text-decoration: underline;
545
  }
546
 
547
  .ce4wp-plugin-support-title {
548
+ font-size: 18px;
549
+ font-weight: bold;
550
+ line-height: 20px;
551
+ color: rgba(0, 0, 0, 0.9);
552
  }
553
 
554
  .ce4wp-list-root {
555
+ margin: 0;
556
+ padding-left: 0 !important;
557
+ padding-right: 0 !important;
558
+ position: relative;
559
+ list-style: none;
560
  }
561
 
562
  .ce4wp-list-padding {
563
+ padding-top: 8px;
564
+ padding-bottom: 8px;
565
  }
566
 
567
  .ce4wp-list-item-gutters {
568
+ padding-left: 8px;
569
+ padding-right: 8px;
570
  }
571
  .ce4wp-list-item-root {
572
+ width: 100%;
573
+ display: flex;
574
+ position: relative;
575
+ box-sizing: border-box;
576
+ min-height: 40px;
577
+ text-align: left;
578
+ align-items: center;
579
+ padding-top: 8px;
580
+ padding-bottom: 8px;
581
+ justify-content: flex-start;
582
+ text-decoration: none;
583
  }
584
  .ce4wp-list-item-text-root {
585
+ flex: 1 1 auto;
586
+ padding: 0;
587
+ min-width: 0;
588
+ margin-top: 4px;
589
+ text-align: left;
590
+ margin-bottom: 4px;
591
  }
592
 
593
  .ce4wp-svg-icon-root {
594
+ fill: currentColor;
595
+ width: 1em;
596
+ height: 1em;
597
+ display: inline-block;
598
+ font-size: 1.5rem;
599
+ transition: fill 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
600
+ flex-shrink: 0;
601
+ user-select: none;
602
  }
603
  .ce4wp-svg-icon-color {
604
+ color: rgb(122,76,168);
605
  }
606
  .ce4wp-list-item-icon-root {
607
+ align-self: start;
608
  }
609
 
610
  .ce4wp-flex-column {
611
+ flex-direction: column !important;
612
  }
613
  .ce4wp-d-flex {
614
+ display: flex !important;
615
  }
616
 
617
  .status-creativemail {
618
+ font-size: 1.4em;
619
+ display: block;
620
+ text-indent: -9999px;
621
+ position: relative;
622
+ height: 1em;
623
+ width: 1em;
624
  }
625
 
626
  .status-creativemail::before {
627
+ background-image: url("../images/icon-small.png");
628
+ background-size: contain;
629
+ background-position-y: 50%;
630
+ background-repeat: no-repeat;
631
+ font-weight: 400;
632
+ font-variant: normal;
633
+ text-transform: none;
634
+ line-height: 1;
635
+ margin: 0;
636
+ text-indent: 0;
637
+ position: absolute;
638
+ top: 0;
639
+ left: 0;
640
+ width: 100%;
641
+ height: 100%;
642
+ text-align: center;
643
+ content: " ";
644
+ color: transparent;
645
  }
646
 
647
  .ce4wp-card table.form-table input[type=text] {
648
+ width: 100%;
649
+ margin: 0;
650
+ padding: 6px;
651
+ box-sizing: border-box;
652
+ vertical-align: top;
653
+ }
654
 
655
  .ce4wp-swoosh-container {
656
+ margin: 0 auto;
657
+ position: relative;
658
  }
659
 
660
  .ce4wp-swoosh-header {
661
+ align-items: center;
662
+ display: flex;
663
+ position: relative;
664
  }
665
 
666
  .ce4wp-swoosh-header::after {
667
+ top: 0px;
668
+ left: 0px;
669
+ right: 0px;
670
+ height: 350px;
671
+ content: "";
672
+ position: absolute;
673
+ background-size: cover;
674
+ background-color: transparent;
675
+ background-image: url("../images/swoosh.svg");
676
+ background-repeat: no-repeat;
677
+ background-position: 100% 100%;
678
+ bottom: auto !important;
679
  }
680
 
681
  .ce4wp-backdrop {
682
+ padding: 0 20px;
683
  }
684
  @media (max-width:460px) {
685
+ .ce4wp-backdrop {
686
+ padding: 0 8px;
687
+ }
688
  }
689
 
690
  .ce4wp-backdrop-container {
691
+ margin: 0 auto;
692
+ position: relative;
693
+ padding-top: 40px;
694
  }
695
  @media (min-width:600px) {
696
+ .ce4wp-backdrop-container {
697
+ max-width: 890px;
698
+ }
699
  }
700
  .ce4wp-backdrop-header {
701
+ margin-bottom: 20px;
702
  }
703
 
704
  .ce4wp-logo-poppins {
705
+ background-image: url("../images/logo.svg");
706
+ background-size: contain;
707
+ background-position-y: 50%;
708
+ width: 272px;
709
+ height: 72px;
710
+ background-repeat: no-repeat;
711
  }
712
 
713
  .ce4wp-airplane {
714
+ position: absolute;
715
+ right: 48px;
716
+ top: 40px;
717
+ z-index: 10;
718
  }
719
  @media (max-width:450px) {
720
+ .ce4wp-airplane {
721
+ right: -20px;
722
+ top: 65px;
723
+ width: 32%;
724
+ }
725
  }
726
  @media (max-width:330px) {
727
+ .ce4wp-logo-poppins {
728
+ width: 250px;
729
+ }
730
  }
731
 
732
  p.ce4wp-subtitle {
733
+ color: rgba(0,0,0,0.6);
734
+ font-size: 24px;
735
+ line-height: 28px;
736
+ font-weight: 400;
737
  }
738
 
739
  .ce4wp-body2 {
740
+ color: rgba(38, 46, 57, 0.7);
741
+ font-size: 14px;
742
+ font-weight: 400;
743
+ line-height: 20px;
744
  }
745
 
746
  @media (max-width:450px) {
747
+ .ce4wp-body2 {
748
+ font-size: 12px;
749
+ }
750
  }
751
 
752
  .ce4wp-Svgicon-root {
753
+ fill: currentColor;
754
+ width: 1em;
755
+ height: 1em;
756
+ display: inline-block;
757
+ font-size: 1.5rem;
758
+ transition: fill 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
759
+ flex-shrink: 0;
760
+ user-select: none;
761
  }
762
 
763
  .ce4wp-grid {
764
+ width: 100%;
765
+ display: flex;
766
+ flex-wrap: wrap;
767
+ box-sizing: border-box;
768
+ width: calc(100% + 16px);
769
+ margin: -8px;
770
  }
771
  @media (max-width:450px) {
772
+ .ce4wp-grid {
773
+ margin: 0;
774
+ }
775
  }
776
 
777
  .ce4wp-grid-item {
778
+ margin: 0;
779
+ box-sizing: border-box;
780
+ flex-grow: 0;
781
+ max-width: 33.333333%;
782
+ flex-basis: 33.333333%;
783
+ padding: 8px;
784
  }
785
 
786
  .ce4wp-grid-xs-2 {
787
+ flex-grow: 0;
788
+ max-width: 16.666667%;
789
+ flex-basis: 16.666667%;
790
  }
791
 
792
  .ce4wp-grid-xs-8 {
793
+ flex-grow: 0;
794
+ max-width: 66.666667%;
795
+ flex-basis: 66.666667%;
796
  }
797
 
798
  .ce4wp-grid-xs-10 {
799
+ flex-grow: 0;
800
+ max-width: 83.333333%;
801
+ flex-basis: 83.333333%;
802
  }
803
 
804
  @media (max-width:800px) {
805
+ .ce4wp-grid-item {
806
+ max-width: none;
807
+ flex-basis: 100%;
808
+ }
809
  }
810
 
811
  .ce4wp-grid-item-card {
812
+ box-sizing: inherit;
813
+ margin-bottom: 1.5rem !important;
814
+ color: rgba(0, 0, 0, 0.9);
815
+ transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, background-color 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
816
+ border-radius: 4px;
817
+ overflow: hidden;
818
+ position: relative;
819
+ min-width: 200px;
820
+ background: #fff;
821
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
822
  }
823
  @media (min-width:800px) {
824
+ .ce4wp-grid-item-card {
825
+ min-height: 150px;
826
+ }
827
  }
828
  @media (max-width:800px) {
829
+ .ce4wp-grid-item-card {
830
+ display: flex;
831
+ }
832
  }
833
 
834
  @media (max-width:450px) {
835
+ .ce4wp-grid-item-card {
836
+ margin: 0 !important;
837
+ }
838
  }
839
 
840
  .ce4wp-grid-item-card:hover {
841
+ cursor: pointer;
842
+ box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.1);
843
+ background-color: rgba(0, 0, 0, 0.03);
844
  }
845
  #skeleton .ce4wp-grid-item-card:hover {
846
+ cursor: default;
847
+ background-color: initial;
848
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
849
  }
850
  .ce4wp-grid-item-card-media {
851
+ display: block;
852
+ background-size: 80% 80%;
853
+ background-repeat: no-repeat;
854
+ background-position: center;
855
+ height: 0px;
856
+ padding-top: 56.25%;
857
+ background-color: #E7E2F6;
858
  }
859
 
860
  @media (max-width:800px) {
861
+ .ce4wp-grid-item-card-media {
862
+ height: auto;
863
+ padding-left: 30%;
864
+ padding-top: initial;
865
+ }
866
  }
867
 
868
  .ce4wp-grid-item-card-content-root {
869
+ padding: 16px;
870
+ padding-bottom: 24px;
871
+ width: 100%;
872
+ box-sizing: border-box;
873
  }
874
 
875
  @media (max-width: 450px){
876
+ .ce4wp-grid-item-card-content-root {
877
+ padding: 5px;
878
+ padding-bottom: 5px;
879
+ }
880
  }
881
 
882
  .skeleton-pulse {
883
+ animation: skeleton-keyframes-pulse 1.5s ease-in-out 0.5s infinite;
884
  }
885
  @keyframes skeleton-keyframes-pulse {
886
+ 0% {
887
+ opacity: 1;
888
+ }
889
+ 50% {
890
+ opacity: 0.4;
891
+ }
892
+ 100% {
893
+ opacity: 1;
894
+ }
895
  }
896
 
897
  .ce4wp-subapps-skeleton {
898
+ height: 24px;
899
+ width: 200px;
900
+ background-color: #F5F5F5;
901
  }
902
 
903
  .ce4wp-grid-item-card-media-skeleton {
904
+ background-color: #E4E4E4;
905
  }
906
 
907
  .ce4wp-grid-item-card-content-skeleton-title {
908
+ height: 20px;
909
+ width: 100%;
910
+ background-color: #F5F5F5;
911
  }
912
 
913
  .ce4wp-grid-item-card-content-skeleton-description {
914
+ height: 36px;
915
+ width: 100%;
916
+ background-color: #F5F5F5;
917
+ margin-top: 4px;
918
  }
919
 
920
  .ce4wp-dialog-root {
921
+ position: fixed;
922
+ z-index: 1300;
923
+ right: 0px;
924
+ bottom: 0px;
925
+ top: 0px;
926
+ left: 0px;
927
  }
928
  .ce4wp-dialog-root * {
929
+ box-sizing: border-box;
930
  }
931
  .ce4wp-backdrop-root {
932
+ top: 0;
933
+ left: 0;
934
+ right: 0;
935
+ bottom: 0;
936
+ display: flex;
937
+ z-index: -1;
938
+ position: fixed;
939
+ background: rgba(49, 57, 68, .7);
940
+ align-items: center;
941
+ justify-content: center;
942
+ background-color: rgba(0, 0, 0, 0.5);
943
+ -webkit-tap-highlight-color: transparent;
944
+ transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
945
  }
946
 
947
  .ce4wp-dialog-container {
948
+ height: 100%;
949
+ outline: 0;
950
+ transform: none;
951
+ transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
952
+ transform 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
953
+ display: flex;
954
+ align-items: center;
955
+ justify-content: center;
956
  }
957
 
958
  .ce4wp-dialog-wrapper {
959
+ height: auto;
960
+ max-height: calc(100% - 64px);
961
+ width: calc(100% - 64px);
962
+ max-width: 600px;
963
+ overflow: hidden;
964
+ transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
965
+ transform: translate3d(0, 0, 0);
966
+ box-shadow: 0px 11px 15px -7px rgba(0,0,0,0.2), 0px 24px 38px 3px rgba(0,0,0,0.14), 0px 9px 46px 8px rgba(0,0,0,0.12);
967
+ display: flex;
968
+ flex-direction: column;
969
+ margin: 32px;
970
+ position: relative;
971
+ overflow-y: auto;
972
+ border-radius: 4px;
973
+ color: rgba(0,0,0,0.9);
974
+ background-color: #fff;
975
  }
976
 
977
  .ce4wp-dialog-header {
978
+ width: 100%;
979
+ padding: 12px;
980
+ min-height: 64px;
981
+ position: fixed;
982
+ top: 0px;
983
+ left: 0px;
984
+ z-index: 10;
985
+ display: flex;
986
+ align-items: flex-start;
987
+ vertical-align: middle;
988
+ justify-content: space-between;
989
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
990
+ background: rgb(246, 246, 246);
991
  }
992
 
993
  .ce4wp-show-me-how-modal .ce4wp-dialog-header {
994
+ height: 180px;
995
  }
996
 
997
  .ce4wp-show-me-how-modal .ce4wp-dialog-header-close{
998
+ align-self: initial;
999
+ vertical-align: initial;
1000
  }
1001
 
1002
  .ce4wp-dialog-header-title {
1003
+ display: flex;
1004
+ align-self: center;
1005
+ align-items: center;
1006
+ vertical-align: middle;
1007
+ justify-content: flex-start;
1008
  }
1009
 
1010
  .ce4wp-dialog-header-close,
1011
  .ce4wp-dialog-footer-close {
1012
+ display: flex;
1013
+ align-self: center;
1014
+ align-items: center;
1015
+ vertical-align: middle;
1016
+ justify-content: flex-end;
1017
+ margin-left: auto;
1018
  }
1019
 
1020
  .ce4wp-dialog-header-title-wrapper {
1021
+ display: flex;
1022
+ align-items: center;
1023
+ vertical-align: middle;
1024
+ justify-content: flex-start;
1025
  }
1026
 
1027
  .ce4wp-dialog-header-title-wrapper > :last-of-type {
1028
+ margin-right: 0px !important;
1029
  }
1030
 
1031
  .ce4wp-dialog-header-title-wrapper > :first-of-type {
1032
+ margin-left: 0px !important;
1033
  }
1034
 
1035
  .ce4wp-dialog-header-title-wrapper > * {
1036
+ display: inline-block;
1037
+ vertical-align: top;
1038
+ margin: 0px 0px 0px 8px !important;
1039
  }
1040
 
1041
  .ce4wp-dialog-header-title-wrapper-content {
1042
+ padding-left: 12px;
1043
+ overflow: hidden;
1044
+ text-overflow: ellipsis;
1045
+ display: -webkit-box;
1046
+ -webkit-box-orient: vertical;
1047
+ -webkit-line-clamp: 3;
1048
+ line-height: 24px;
1049
+ max-height: 72px;
1050
  }
1051
 
1052
  .ce4wp-dialog-header-close-wrapper,
1053
  .ce4wp-dialog-footer-close-wrapper {
1054
+ display: flex;
1055
+ align-items: center;
1056
+ vertical-align: middle;
1057
+ justify-content: center;
1058
  }
1059
  .ce4wp-dialog-header-close-wrapper {
1060
+ width: 40px;
1061
+ height: 40px;
1062
+ cursor: pointer;
1063
  }
1064
 
1065
  .ce4wp-dialog-header-close-wrapper:hover {
1066
+ background-color: rgba(0, 0, 0, 0.04);
1067
  }
1068
  .ce4wp-dialog-header-close-wrapper {
1069
+ flex: 0 0 auto;
1070
+ color: rgba(0, 0, 0, 0.54);
1071
+ padding: 8px;
1072
+ overflow: visible;
1073
+ font-size: 1.5rem;
1074
+ text-align: center;
1075
+ transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
1076
+ border-radius: 4px;
1077
  }
1078
 
1079
  .ce4wp-dialog-content {
1080
+ flex: 1 1 auto;
1081
+ overflow-y: auto;
1082
+ position: relative;
1083
+ height: auto;
1084
+ margin-top: 64px;
1085
+ padding: 24px;
1086
  }
1087
 
1088
  .ce4wp-show-me-how-modal .ce4wp-dialog-content {
1089
+ margin-top: 180px;
1090
  }
1091
 
1092
  .ce4wp-consent {
1093
+ background-color: rgba(122, 92, 189, 0.1);
1094
+ border: 1px solid rgb(209, 179, 238);
1095
+ border-radius: 2px;
1096
+ padding: 16px;
1097
+ margin-bottom: 12px;
1098
  }
1099
 
1100
  .ce4wp-dialog-footer {
1101
+ display: flex;
1102
+ flex: 0 0 auto;
1103
+ align-items: center;
1104
+ justify-content: space-between;
1105
+ z-index: 1;
1106
+ padding: 8px;
1107
+ background: rgb(255, 255, 255);
1108
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
1109
  }
1110
  #ce4wp_admin_dashboard_widget .floater {
1111
+ float:right;
1112
  }
1113
  .ce4wp_dashboard_icon {
1114
+ background-image: url(../images/admin-dashboard-widget/logo.svg);
1115
+ height: 1.1em;
1116
+ width: 130px;
1117
+ background-size: cover;
1118
+ background-repeat: no-repeat;
1119
+ float: right;
1120
+ margin-left: 5px;
1121
  }
1122
 
1123
  .ce4wp-settings-card{
1124
+ padding: 8px 16px;
1125
+ cursor: pointer;
1126
+ border: 1px solid rgba(0,0,0,0.1);
1127
+ margin: 1px;
1128
+ border-radius: 4px;
1129
  }
1130
 
1131
  .ce4wp-selected{
1132
+ border: 2px solid #A78AE8;
1133
+ margin: 0;
1134
  }
1135
 
1136
  .ce4wp-settings-card:hover {
1137
+ background-color: rgba(122,92,189,0.1);
1138
  }
1139
  .ce4wp-settings-card-image{
1140
+ height: 32px;
1141
+ width: 32px;
1142
+ margin: 8px 0;
1143
+ background-size: contain;
1144
  }
1145
 
1146
  .ce4wp-settings-card-title{
1147
+ line-height: 48px;
1148
  }
1149
 
1150
  .ce4wp-settings-card-link{
1151
+ visibility: hidden;
1152
+ background-image: url(../images/launch-grey.svg);
1153
+ fill: #6f6f6f;
1154
+ height: 24px;
1155
+ width: 24px;
1156
+ margin-top: 12px;
1157
  }
1158
 
1159
  .ce4wp-settings-card:hover .ce4wp-settings-card-link{
1160
+ visibility: visible;
1161
  }
1162
 
1163
  .ce4wp-show-on-mobile{
1164
+ display: none;
1165
  }
1166
  @media (max-width: 450px) {
1167
+ .ce4wp-hide-on-mobile{
1168
+ display: none;
1169
+ }
1170
+ .ce4wp-show-on-mobile{
1171
+ display: initial;
1172
+ }
1173
  }
1174
 
1175
  .ce4wp-loader{
1176
+ color: #0076DF;
1177
+ animation: ce4wp-loader-rotate 1.4s linear infinite;
1178
+ animation-duration: 1.4s;
1179
+ animation-timing-function: linear;
1180
+ animation-delay: 0s;
1181
+ animation-iteration-count: infinite;
1182
+ animation-direction: normal;
1183
+ animation-fill-mode: none;
1184
+ animation-play-state: running;
1185
+ animation-name: ce4wp-loader-rotate;
1186
+ margin: 0 auto;
1187
  }
1188
 
1189
  .ce4wp-notice {
1190
+ border-left: 0;
1191
+ background-repeat: no-repeat;
1192
+ background-size: contain;
1193
+ display: flex;
1194
+ height: 175px;
1195
+ position: relative;
1196
+ margin-right: var(--large-gap);
1197
+ margin-bottom: 20px;
1198
+ max-width: 100%;
1199
  }
1200
 
1201
  .ce4wp-notice-primary {
1202
+ background-color: #7A5CBD;
1203
+ background-image: url(../images/woocommerce-banners/bg-blob.png);
1204
  }
1205
 
1206
  .ce4wp-notice-primary #close::before {
1207
+ color:white !important;
1208
  }
1209
 
1210
  .ce4wp-notice-secondary {
1211
+ background-color: #B5E5E7;
1212
+ background-image: url(../images/woocommerce-banners/bg-blob.png);
1213
+ padding: 0 0 0 50px;
1214
  }
1215
 
1216
  .ce4wp-notice-secondary section h1 {
1217
+ color: black !important;
1218
  }
1219
 
1220
  .ce4wp-notice-secondary section p {
1221
+ color: black !important;
1222
  }
1223
 
1224
  .ce4wp-notice img {
1225
+ max-height: 150px;
1226
+ margin-top: 25px;
1227
+ margin-left: 20px;
1228
  }
1229
  .ce4wp-notice section {
1230
+ margin-left: 40px;
1231
+ margin-top: 2px;
1232
  }
1233
 
1234
  .ce4wp-notice section h1 {
1235
+ color:white;
1236
+ margin-top: 1em;
1237
  }
1238
  .ce4wp-notice section p {
1239
+ color:white;
1240
+ font-size: 17px;
1241
+ line-height: 1;
1242
  }
1243
 
1244
  .ce4wp-notice section button {
1245
+ color:black !important;
1246
+ background: white !important;
1247
+ border-color: white !important;
1248
  }
1249
 
1250
  .ce4wp-notice #close {
1251
+ width: 16px;
1252
+ height: 16px;
1253
+ margin-left: 0.3em;
1254
+ cursor: pointer;
1255
+ position: absolute;
1256
+ top: 10px;
1257
+ right: 10px;
1258
  }
1259
 
1260
  .ce4wp-notice #close::before {
1261
+ color: #6f6f6f;
1262
+ font: 400 21px/1 dashicons;
1263
+ content: '\f158';
1264
  }
1265
 
1266
 
1267
  .ce4wp-hidden {
1268
+ display: none;
1269
  }
1270
 
1271
  .ce4wp-loader circle {
1272
+ animation: ce4wp-loader-circular-dash 1.4s ease-in-out infinite;
1273
+ animation-duration: 1.4s;
1274
+ animation-timing-function: ease-in-out;
1275
+ animation-delay: 0s;
1276
+ animation-iteration-count: infinite;
1277
+ animation-direction: normal;
1278
+ animation-fill-mode: none;
1279
+ animation-play-state: running;
1280
+ animation-name: ce4wp-loader-circular-dash;
1281
+ stroke-dasharray: 80px, 200px;
1282
+ stroke-dashoffset: 0px;
1283
+ stroke: currentColor;
1284
  }
1285
 
1286
  .ce4wp-banner {
1287
+ background-color: #7A5CBD;
1288
+ color: white;
1289
+ padding: 12px;
1290
+ border-radius: 4px;
1291
+ margin-top: 25px;
1292
+ display: flex;
1293
+ flex-direction: row;
1294
  }
1295
 
1296
  .ce4wp-banner .ce4wp-content {
1297
+ margin-left: 20px;
1298
  }
1299
 
1300
  .ce4wp-banner .ce4wp-content h2,.ce4wp-banner .ce4wp-content a{
1301
+ color: white
1302
  }
1303
 
1304
  .ce4wp-banner .ce4wp-content a {
1305
+ text-decoration: underline;
1306
+ font-weight: 600;
1307
  }
1308
 
1309
  .ce4wp-banner .ce4wp-content a:hover {
1313
 
1314
 
1315
  .ce4wp-ml-6 {
1316
+ margin-left: 24px;
1317
  }
1318
 
1319
  .ce4wp-show-me-how-screenshot{
1320
+ max-width: 280px;
1321
  }
1322
 
1323
  @keyframes ce4wp-loader-rotate {
1324
+ 0% {transform-origin: 50% 50%;}
1325
+ 100% {transform: rotate(360deg)};
1326
  }
1327
 
1328
  @keyframes ce4wp-loader-circular-dash {
1329
+ 0% {
1330
+ stroke-dasharray: 1px, 200px;
1331
+ stroke-dashoffset: 0px;
1332
+ }
1333
+ 50% {
1334
+ stroke-dasharray: 100px, 200px;
1335
+ stroke-dashoffset: -15px;
1336
+ }
1337
+ 100% {
1338
+ stroke-dasharray: 100px, 200px;
1339
+ stroke-dashoffset: -125px;
1340
+ }
1341
+ }
assets/css/deactivation.css CHANGED
@@ -12,37 +12,37 @@
12
  background: rgba(0,0,0,0.8);
13
  }
14
  .ce4wp-deactivate-survey-wrap {
15
- display: table-cell;
16
- vertical-align: middle;
17
  }
18
  .ce4wp-deactivate-survey {
19
- background-color: #f1f1f1;
20
- border: 0 solid #ccc;
21
- border-radius: 3px;
22
- margin: 0 auto;
23
- padding: 12px;
24
- width: 340px;
25
- direction: ltr;
26
  }
27
 
28
  .ce4wp-deactivate-survey fieldset {
29
- margin:25px;
30
  }
31
 
32
  .ce4wp-deactivate-survey span {
33
- float: left;
34
- margin: 5px;
35
  }
36
 
37
  .ce4wp-deactivate-survey span input {
38
- padding-right: 5px;
39
  }
40
 
41
  .ce4wp-deactivate-survey a.button {
42
- white-space: normal;
43
- height: auto;
44
  }
45
 
46
  #ce4wp-deactivate-survey-form-success {
47
- display: none;
48
  }
12
  background: rgba(0,0,0,0.8);
13
  }
14
  .ce4wp-deactivate-survey-wrap {
15
+ display: table-cell;
16
+ vertical-align: middle;
17
  }
18
  .ce4wp-deactivate-survey {
19
+ background-color: #f1f1f1;
20
+ border: 0 solid #ccc;
21
+ border-radius: 3px;
22
+ margin: 0 auto;
23
+ padding: 12px;
24
+ width: 340px;
25
+ direction: ltr;
26
  }
27
 
28
  .ce4wp-deactivate-survey fieldset {
29
+ margin:25px;
30
  }
31
 
32
  .ce4wp-deactivate-survey span {
33
+ float: left;
34
+ margin: 5px;
35
  }
36
 
37
  .ce4wp-deactivate-survey span input {
38
+ padding-right: 5px;
39
  }
40
 
41
  .ce4wp-deactivate-survey a.button {
42
+ white-space: normal;
43
+ height: auto;
44
  }
45
 
46
  #ce4wp-deactivate-survey-form-success {
47
+ display: none;
48
  }
assets/css/feedback_notice.css CHANGED
@@ -1,78 +1,78 @@
1
  #ce4wp-admin-feedback-notice {
2
- position: relative;
3
- display: flex;
4
- flex-direction: row;
5
- align-items: center;
6
- user-select: none;
7
- margin: 3rem 1.25rem 0 auto;
8
  }
9
 
10
  @media screen and (max-width: 782px) {
11
- #ce4wp-admin-feedback-notice {
12
- margin-top: calc(3rem + 20px);
13
- margin-right: 12px;
14
- }
15
  }
16
 
17
  #ce4wp-admin-feedback-notice[hidden] {
18
- display: none;
19
  }
20
 
21
  #ce4wp-admin-feedback-notice .icon {
22
- margin-right: 0.5em;
23
  }
24
 
25
  #ce4wp-admin-feedback-notice .icon:not(.dashicons) {
26
- height: 3em;
27
  }
28
 
29
  #ce4wp-admin-feedback-notice .content {
30
- flex: 1;
31
- display: flex;
32
- flex-direction: column;
33
  }
34
 
35
  #ce4wp-admin-feedback-notice .content .ce-logo {
36
- height: 0.9em;
37
- transform: translateY(.1em);
38
  }
39
 
40
  #ce4wp-admin-feedback-notice .content p:not(:last-child) {
41
- margin-bottom: 0;
42
  }
43
 
44
  #ce4wp-admin-feedback-notice .content :not(:first-child) {
45
- margin-top: 0;
46
  }
47
 
48
  #ce4wp-admin-feedback-notice #close {
49
- width: 16px;
50
- height: 16px;
51
- margin-left: 0.3em;
52
- cursor: pointer;
53
  }
54
 
55
  #ce4wp-admin-feedback-notice #close::before {
56
- color: #6f6f6f;
57
- font: 400 16px/1 dashicons;
58
- content: '\f158';
59
  }
60
 
61
  #ce4wp-admin-feedback-notice .dashicons {
62
- background-color: #53C65E;
63
- border-radius: 50%;
64
- font-size: 2em;
65
- width: 1.5em;
66
- height: 1.5em;
67
 
68
- display: flex;
69
- justify-content: center;
70
- align-items: center;
71
 
72
- margin-right: 0.5em;
73
  }
74
 
75
  #ce4wp-admin-feedback-notice .dashicons::before {
76
- color: white;
77
- transform: translateY(-0.1em);
78
- }
1
  #ce4wp-admin-feedback-notice {
2
+ position: relative;
3
+ display: flex;
4
+ flex-direction: row;
5
+ align-items: center;
6
+ user-select: none;
7
+ margin: 3rem 1.25rem 0 auto;
8
  }
9
 
10
  @media screen and (max-width: 782px) {
11
+ #ce4wp-admin-feedback-notice {
12
+ margin-top: calc(3rem + 20px);
13
+ margin-right: 12px;
14
+ }
15
  }
16
 
17
  #ce4wp-admin-feedback-notice[hidden] {
18
+ display: none;
19
  }
20
 
21
  #ce4wp-admin-feedback-notice .icon {
22
+ margin-right: 0.5em;
23
  }
24
 
25
  #ce4wp-admin-feedback-notice .icon:not(.dashicons) {
26
+ height: 3em;
27
  }
28
 
29
  #ce4wp-admin-feedback-notice .content {
30
+ flex: 1;
31
+ display: flex;
32
+ flex-direction: column;
33
  }
34
 
35
  #ce4wp-admin-feedback-notice .content .ce-logo {
36
+ height: 0.9em;
37
+ transform: translateY(.1em);
38
  }
39
 
40
  #ce4wp-admin-feedback-notice .content p:not(:last-child) {
41
+ margin-bottom: 0;
42
  }
43
 
44
  #ce4wp-admin-feedback-notice .content :not(:first-child) {
45
+ margin-top: 0;
46
  }
47
 
48
  #ce4wp-admin-feedback-notice #close {
49
+ width: 16px;
50
+ height: 16px;
51
+ margin-left: 0.3em;
52
+ cursor: pointer;
53
  }
54
 
55
  #ce4wp-admin-feedback-notice #close::before {
56
+ color: #6f6f6f;
57
+ font: 400 16px/1 dashicons;
58
+ content: '\f158';
59
  }
60
 
61
  #ce4wp-admin-feedback-notice .dashicons {
62
+ background-color: #53C65E;
63
+ border-radius: 50%;
64
+ font-size: 2em;
65
+ width: 1.5em;
66
+ height: 1.5em;
67
 
68
+ display: flex;
69
+ justify-content: center;
70
+ align-items: center;
71
 
72
+ margin-right: 0.5em;
73
  }
74
 
75
  #ce4wp-admin-feedback-notice .dashicons::before {
76
+ color: white;
77
+ transform: translateY(-0.1em);
78
+ }
assets/js/block/subscribe.asset.php CHANGED
@@ -1 +1 @@
1
- <?php return array('dependencies' => array('wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => '3dfa592b262000d14067391ccf4595bd');
1
+ <?php return array('dependencies' => array('wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => 'e8c54930fb0dd9840cf0248b2d202580');
assets/js/block/subscribe.js CHANGED
@@ -1 +1 @@
1
- !function(e){var t={};function a(n){if(t[n])return t[n].exports;var l=t[n]={i:n,l:!1,exports:{}};return e[n].call(l.exports,l,l.exports,a),l.l=!0,l.exports}a.m=e,a.c=t,a.d=function(e,t,n){a.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,t){if(1&t&&(e=a(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(a.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var l in e)a.d(n,l,function(t){return e[t]}.bind(null,l));return n},a.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(t,"a",t),t},a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.p="",a(a.s=16)}([function(e,t){e.exports=window.wp.element},function(e,t){e.exports=window.wp.blockEditor},function(e,t){e.exports=window.wp.components},function(e,t){e.exports=window.wp.i18n},function(e,t,a){var n=a(13),l=a(14),c=a(6),i=a(15);e.exports=function(e,t){return n(e)||l(e,t)||c(e,t)||i()},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(e,t){(null==t||t>e.length)&&(t=e.length);for(var a=0,n=new Array(t);a<t;a++)n[a]=e[a];return n},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t,a){var n=a(5);e.exports=function(e,t){if(e){if("string"==typeof e)return n(e,t);var a=Object.prototype.toString.call(e).slice(8,-1);return"Object"===a&&e.constructor&&(a=e.constructor.name),"Map"===a||"Set"===a?Array.from(e):"Arguments"===a||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(a)?n(e,t):void 0}},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=window.wp.blocks},function(e,t){e.exports=function(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t,a){var n=a(10),l=a(11),c=a(6),i=a(12);e.exports=function(e){return n(e)||l(e)||c(e)||i()},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t,a){var n=a(5);e.exports=function(e){if(Array.isArray(e))return n(e)},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(e){if(Array.isArray(e))return e},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(e,t){var a=e&&("undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"]);if(null!=a){var n,l,c=[],i=!0,s=!1;try{for(a=a.call(e);!(i=(n=a.next()).done)&&(c.push(n.value),!t||c.length!==t);i=!0);}catch(e){s=!0,l=e}finally{try{i||null==a.return||a.return()}finally{if(s)throw l}}return c}},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t,a){"use strict";a.r(t);var n=a(7),l=a(8),c=a.n(l),i=a(9),s=a.n(i),r=a(4),o=a.n(r),m=a(0),u=a(3),b=a(1),p=a(2);function d(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function O(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?d(Object(a),!0).forEach((function(t){c()(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):d(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}var f="notshow",j="optional",y="required",N="summary",h="message",E="redirect",v=function(e,t){var a=React.useState([]),n=o()(a,2),l=n[0],c=n[1],i=React.useState(!1),s=o()(i,2),r=s[0],m=s[1],u=React.useState(!1),b=o()(u,2),p=b[0],d=b[1];return React.useEffect((function(){var a;r||p||(m(!0),jQuery.post(null===(a=ce4wp_form_submit_data)||void 0===a?void 0:a.url,{action:e,nonce:t}).done((function(e){m(!1),d(!0),null!=(null==e?void 0:e.data)&&c(e.data)})))}),[r,p,l]),{data:l,loading:r,hasLoaded:p}};Object(n.registerBlockType)("ce4wp/subscribe",{edit:function(e){var t=this,a=e.attributes,n=e.setAttributes,l=e.className,c=e.clientId;a.blockId||n({blockId:c});var i,r,o=function(){var e,t=v("ce4wp_get_all_custom_lists",null===(e=ce4wp_form_submit_data)||void 0===e?void 0:e.listNonce),a=t.data,n=t.loading,l=t.hasLoaded,c=[];return null!=a&&null!=a.length&&(c=a.map((function(e){return{label:e.name,value:e.id}}))),{customLists:c,loading:n,hasLoaded:l}}().customLists,d={creativeEmailIsActivated:(r=v("ce4wp_creative_email_activated",null===(i=ce4wp_form_submit_data)||void 0===i?void 0:i.activatedNonce)).data,loading:r.loading,hasLoaded:r.hasLoaded}.creativeEmailIsActivated;return Object(m.createElement)("div",{className:"wp-block-ce4wp-subscribe ".concat(l||"")},Object(m.createElement)(b.BlockControls,{key:"setting"},Object(m.createElement)(b.InspectorControls,{key:"setting"},Object(m.createElement)(p.Panel,{header:"Settings"},Object(m.createElement)(p.PanelBody,{title:"Contact Segmentation",initialOpen:!0},Object(m.createElement)(p.PanelRow,{className:"no-flex"},Object(m.createElement)("fieldset",null,Object(m.createElement)("i",{className:"subTitle sub-header"},Object(u.__)("Automatically assign a new contact to a list when they subscribe","ce4wp"),Object(m.createElement)("br",null),Object(m.createElement)(p.ExternalLink,{onClick:function(){return ce4wpNavigateToDashboard(t,"fbcd9606-288a-4d82-be7c-449eaf5a3792",{source:"ce4wp_form_menu"},ce4wpDashboardStartCallback,ce4wpDashboardFinishCallback)}},Object(m.createElement)("span",{id:"ce4wp-manage-lists","data-link_reference":"836b20fc-9ff1-41b2-912b-a8646caf05a4"},Object(u.__)("Manage your lists","ce4wp")))),Object(m.createElement)("br",null),Object(m.createElement)("br",null),Object(m.createElement)(p.SelectControl,{label:"list",value:a.customList,options:[{label:Object(u.__)("Don't assign to a list","cewp4"),value:""}].concat(s()(o)),onChange:function(e){return n({customList:e})}})))),Object(m.createElement)(p.PanelBody,{title:"On submission",initialOpen:!0},Object(m.createElement)(p.PanelRow,null,Object(m.createElement)("fieldset",null,Object(m.createElement)(p.SelectControl,{label:"On submission",value:a.onSubmissionSetting,options:[{label:"Show a custom text message",value:h},{label:"Show a summary of submitted fields",value:N},{label:"Redirect",value:E}],onChange:function(e){return n({onSubmissionSetting:e})}}))),a.onSubmissionSetting===h&&Object(m.createElement)(p.PanelRow,null,Object(m.createElement)("fieldset",null,Object(m.createElement)(p.TextareaControl,{label:"Message text",value:a.onSubmission,onChange:function(e){return n({onSubmission:e})}}))),a.onSubmissionSetting===E&&Object(m.createElement)(p.PanelRow,null,Object(m.createElement)("fieldset",null,Object(m.createElement)(p.TextControl,{label:"Redirect link",value:a.redirectLink,onChange:function(e){return n({redirectLink:e})}})))),Object(m.createElement)(p.PanelBody,{title:"Disclaimer settings",initialOpen:!0},Object(m.createElement)(p.PanelRow,{className:"no-flex"},Object(m.createElement)("fieldset",null,Object(m.createElement)(p.SelectControl,{label:"Permission to mail",value:a.emailPermission,options:[{label:"message",value:"message"},{label:"checkbox",value:"checkbox"}],onChange:function(e){return n(O(O({},a),{},{emailPermission:e}))}})))),Object(m.createElement)(p.PanelBody,{title:"Field settings",initialOpen:!0},Object(m.createElement)(p.PanelRow,{className:"no-flex"},Object(m.createElement)("fieldset",null,Object(m.createElement)(p.SelectControl,{label:"First name field",value:a.displayFirstName,options:[{label:"Do not show",value:f},{label:"Optional",value:j},{label:"Required",value:y}],onChange:function(e){return n({displayFirstName:e})}}))),Object(m.createElement)(p.PanelRow,{className:"no-flex"},Object(m.createElement)("fieldset",null,Object(m.createElement)(p.SelectControl,{label:"Last name field",value:a.displayLastName,options:[{label:"Do not show",value:f},{label:"Optional",value:j},{label:"Required",value:y}],onChange:function(e){return n({displayLastName:e})}}))),Object(m.createElement)(p.PanelRow,{className:"no-flex"},Object(m.createElement)("fieldset",null,Object(m.createElement)(p.SelectControl,{label:"Telephone field",value:a.displayTelephone,options:[{label:"Do not show",value:f},{label:"Optional",value:j},{label:"Required",value:y}],onChange:function(e){return n({displayTelephone:e})}}))))))),Object(m.createElement)("form",{name:"contact-form"},Object(m.createElement)(b.RichText,{tagName:"h2",onChange:function(e){n({title:e})},value:a.title}),Object(m.createElement)(b.RichText,{tagName:"p",className:"subTitle",onChange:function(e){n({subTitle:e})},value:a.subTitle}),!1===d&&Object(m.createElement)("div",{className:"ce4wp-inline-notification ce4wp-inline-warning ce4wp-banner-clickable",onClick:function(){return ce4wpNavigateToDashboard(t,"d25f690a-217a-4d68-9c58-8693965d4673",{source:"ce4wp_form_menu"},ce4wpDashboardStartCallback,ce4wpDashboardFinishCallback)}},Object(m.createElement)(p.Dashicon,{className:"ce4wp-inline-warning-icon",icon:"warning"}),Object(m.createElement)("div",{className:"ce4wp-inline-warning-text"},Object(u.__)("Set up Creative Mail before you use this form on your website.")),Object(m.createElement)(p.Dashicon,{className:"ce4wp-inline-warning-arrow",icon:"arrow-right-alt2"})),a.displayFirstName!==f&&Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText,{tagName:"label",className:"firstNameLabel",onChange:function(e){n({firstNameLabel:e})},value:a.firstNameLabel}),a.displayFirstName===y&&Object(m.createElement)("p",{className:"required-text subTitle",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{name:"first_name",type:"text"})),a.displayLastName!==f&&Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText,{tagName:"label",className:"lastNameLabel",onChange:function(e){n({lastNameLabel:e})},value:a.lastNameLabel}),a.displayLastName===y&&Object(m.createElement)("p",{className:"required-text subTitle",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{name:"last_name",type:"text"})),a.displayTelephone!==f&&Object(m.createElement)("div",{class:"inputBlock"},Object(m.createElement)(b.RichText,{tagName:"label",className:"lastNameLabel",onChange:function(e){n({telephoneLabel:e})},value:a.telephoneLabel}),a.displayTelephone===y&&Object(m.createElement)("p",{className:"required-text subTitle",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{name:"telephone",type:"text"})),Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText,{tagName:"label",className:"emailLabel",onChange:function(e){n({emailLabel:e})},value:a.emailLabel}),Object(m.createElement)("p",{className:"required-text subTitle",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"textwidget",name:"email",type:"text"})),"message"==a.emailPermission&&Object(m.createElement)("div",{className:"disclaimer"},Object(m.createElement)(b.RichText,{tagName:"label",className:"disclaimer-text",onChange:function(e){n({disclaimer:e})},value:a.disclaimer})),"checkbox"==a.emailPermission&&Object(m.createElement)("div",{className:"disclaimer"},Object(m.createElement)("input",{type:"checkbox",name:"consent_check_".concat(c),id:"consent_check_".concat(c)}),Object(m.createElement)(b.RichText,{htmlFor:"consent_check_".concat(c),tagName:"label",className:"consentLabel disclaimer-label",onChange:function(e){n({consentLabel:e})},value:a.consentLabel})),Object(m.createElement)("button",{className:"wp-block-button__link submit-button",type:"button"},Object(u.__)("Subscribe","cewp4"))))},save:function(e){var t=e.attributes,a=e.className;return Object(m.createElement)("div",{className:"wp-block-ce4wp-subscribe ".concat(a||"")},Object(m.createElement)("div",{className:"onSubmission",style:{display:"none"}},Object(m.createElement)("input",{className:"onSubmissionSetting",name:"onSubmissionSetting",type:"hidden",value:t.onSubmissionSetting}),t.onSubmissionSetting!==h&&Object(m.createElement)("div",null,Object(m.createElement)(b.RichText.Content,{className:"title",tagName:"h2",value:t.title})),t.onSubmissionSetting===h&&Object(m.createElement)("div",null,Object(m.createElement)(b.RichText.Content,{className:"title",tagName:"h2",value:t.title}),Object(m.createElement)("p",{className:"subTitle"},Object(u.__)(t.onSubmission,"cewp4"))),t.onSubmissionSetting===N&&Object(m.createElement)("div",null,Object(m.createElement)("h3",null,"You have subscribed"),Object(m.createElement)("br",null),(t.displayFirstName!==f||t.displayLastName!==f)&&Object(m.createElement)("p",null,Object(m.createElement)("span",null,"Name: "),Object(m.createElement)("span",{className:"firstNameSummary"}),Object(m.createElement)("span",{className:"lastNameSummary"})),t.displayTelephone!==f&&Object(m.createElement)("p",null,Object(m.createElement)("span",null,"Telephone: "),Object(m.createElement)("span",{className:"telephoneSummary"})),Object(m.createElement)("p",null,Object(m.createElement)("span",null,"Email: "),Object(m.createElement)("span",{className:"emailSummary"}))),t.onSubmissionSetting===E&&Object(m.createElement)("input",{className:"redirect",name:"redirect",type:"hidden",value:t.redirectLink})),Object(m.createElement)("form",{className:"cm-contact-form",name:"contact-form"},Object(m.createElement)("input",{className:"list_id",name:"list_id",type:"hidden",value:t.customList}),Object(m.createElement)(b.RichText.Content,{className:"title",tagName:"h2",value:t.title})," ",Object(m.createElement)(b.RichText.Content,{className:"subTitle",tagName:"p",value:t.subTitle}),t.displayFirstName!==f&&Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.firstNameLabel}),t.displayFirstName===y&&Object(m.createElement)("span",{className:"wp-caption-text required-text",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"firstName",name:"first_name",type:"text",required:t.displayFirstName===y})),t.displayLastName!==f&&Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.lastNameLabel}),t.displayLastName===y&&Object(m.createElement)("span",{className:"wp-caption-text required-text",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"lastName",name:"last_name",type:"text",required:t.displayLastName===y})),t.displayTelephone!==f&&Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.telephoneLabel}),t.displayTelephone===y&&Object(m.createElement)("span",{className:"wp-caption-text required-text",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"telephone",name:"telephone",type:"tel",pattern:"[+]?[0-9\\(\\)\\s+-]{5,20}",oninvalid:"setCustomValidity('".concat(Object(u.__)("Please enter a valid phone number","cewp4"),"')"),oninput:"setCustomValidity('')",required:t.displayTelephone===y})),Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.emailLabel}),Object(m.createElement)("span",{className:"wp-caption-text required-text",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"email",name:"email",type:"email",oninvalid:"setCustomValidity('".concat(Object(u.__)("Please enter a valid email address","cewp4"),"')"),oninput:"setCustomValidity('')",required:!0})),"message"==t.emailPermission&&Object(m.createElement)("div",{className:"disclaimer"},Object(m.createElement)("input",{className:"consent_check",name:"consent",type:"hidden",checked:!0}),Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.disclaimer})),"checkbox"==t.emailPermission&&Object(m.createElement)("div",{className:"disclaimer"},Object(m.createElement)("input",{className:"consent_check",name:"consent_check_".concat(t.blockId),id:"consent_check_".concat(t.blockId),type:"checkbox"}),Object(m.createElement)(b.RichText.Content,{htmlFor:"consent_check_".concat(t.blockId),tagName:"label",value:t.consentLabel,className:"disclaimer-label"})),Object(m.createElement)("button",{className:"wp-block-button__link submit-button",type:"submit"},Object(u.__)("Subscribe","cewp4"))))},supports:{alignWide:!1},keywords:[Object(u.__)("contact"),Object(u.__)("form"),Object(u.__)("email"),Object(u.__)("mail")],deprecated:[{attributes:{blockId:{type:"string"},title:{type:"string",default:"Subscribe"},subTitle:{type:"string",default:"Sign up for our newsletter and stay up to date"},firstNameLabel:{type:"string",default:"First name"},lastNameLabel:{type:"string",default:"Last name"},emailLabel:{type:"string",default:"Email"},telephoneLabel:{type:"string",default:"Telephone"},emailPermission:{type:"string",default:"checkbox"},displayTelephone:{type:"string",default:"notshow"},displayFirstName:{type:"string",default:"optional"},displayLastName:{type:"string",default:"optional"},onSubmission:{type:"string",selector:"div",default:"Thank you for subscribing!"},customList:{type:"string",default:null}},save:function(e){var t=e.attributes,a=e.className;return Object(m.createElement)("div",{className:"wp-block-ce4wp-subscribe ".concat(a||"")},Object(m.createElement)("div",{className:"onSubmission",style:{display:"none"}},Object(m.createElement)(b.RichText.Content,{className:"title",tagName:"h2",value:t.title}),Object(m.createElement)("p",{className:"subTitle"},Object(u.__)(t.onSubmission,"cewp4"))),Object(m.createElement)("form",{className:"cm-contact-form",name:"contact-form"},Object(m.createElement)("input",{className:"list_id",name:"list_id",type:"hidden",value:t.customList}),Object(m.createElement)(b.RichText.Content,{className:"title",tagName:"h2",value:t.title})," ",Object(m.createElement)(b.RichText.Content,{className:"subTitle",tagName:"p",value:t.subTitle}),t.displayFirstName!==f&&Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.firstNameLabel}),t.displayFirstName===y&&Object(m.createElement)("span",{className:"wp-caption-text required-text",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"firstName",name:"first_name",type:"text",required:t.displayFirstName===y})),t.displayLastName!==f&&Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.lastNameLabel}),t.displayLastName===y&&Object(m.createElement)("span",{className:"wp-caption-text required-text",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"lastName",name:"last_name",type:"text",required:t.displayFirstName===y})),t.displayTelephone!==f&&Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.telephoneLabel}),t.displayTelephone===y&&Object(m.createElement)("span",{className:"wp-caption-text required-text",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"telephone",name:"telephone",type:"tel",pattern:"[+]?[0-9\\(\\)\\s+-]{5,20}",oninvalid:"setCustomValidity('".concat(Object(u.__)("Please enter a valid phone number","cewp4"),"')"),oninput:"setCustomValidity('')",required:t.displayFirstName===y})),Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.emailLabel}),Object(m.createElement)("span",{className:"wp-caption-text required-text",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"email",name:"email",type:"email",oninvalid:"setCustomValidity('".concat(Object(u.__)("Please enter a valid email address","cewp4"),"')"),oninput:"setCustomValidity('')",required:!0})),"message"==t.emailPermission&&Object(m.createElement)("span",{className:"disclaimer"},Object(m.createElement)("input",{className:"consent_check",name:"consent",type:"hidden",checked:!0}),Object(u.__)("By submitting your information, you are granting us permission to email you. You may unsubscribe at any time.","cewp4")),"checkbox"==t.emailPermission&&Object(m.createElement)("span",null,Object(m.createElement)("input",{className:"consent_check",name:"consent_check_".concat(t.blockId),id:"consent_check_".concat(t.blockId),type:"checkbox"}),Object(m.createElement)("label",{htmlFor:"consent_check_".concat(t.blockId),className:"disclaimer"},Object(u.__)("Can we send you an email from time to time?","cewp4"))),Object(m.createElement)("button",{className:"wp-block-button__link submit-button",type:"submit"},Object(u.__)("Subscribe","cewp4"))))}}]})}]);
1
+ !function(e){var t={};function a(n){if(t[n])return t[n].exports;var l=t[n]={i:n,l:!1,exports:{}};return e[n].call(l.exports,l,l.exports,a),l.l=!0,l.exports}a.m=e,a.c=t,a.d=function(e,t,n){a.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,t){if(1&t&&(e=a(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(a.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var l in e)a.d(n,l,function(t){return e[t]}.bind(null,l));return n},a.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(t,"a",t),t},a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.p="",a(a.s=16)}([function(e,t){e.exports=window.wp.element},function(e,t){e.exports=window.wp.blockEditor},function(e,t){e.exports=window.wp.components},function(e,t){e.exports=window.wp.i18n},function(e,t,a){var n=a(13),l=a(14),c=a(6),i=a(15);e.exports=function(e,t){return n(e)||l(e,t)||c(e,t)||i()},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(e,t){(null==t||t>e.length)&&(t=e.length);for(var a=0,n=new Array(t);a<t;a++)n[a]=e[a];return n},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t,a){var n=a(5);e.exports=function(e,t){if(e){if("string"==typeof e)return n(e,t);var a=Object.prototype.toString.call(e).slice(8,-1);return"Object"===a&&e.constructor&&(a=e.constructor.name),"Map"===a||"Set"===a?Array.from(e):"Arguments"===a||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(a)?n(e,t):void 0}},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=window.wp.blocks},function(e,t){e.exports=function(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t,a){var n=a(10),l=a(11),c=a(6),i=a(12);e.exports=function(e){return n(e)||l(e)||c(e)||i()},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t,a){var n=a(5);e.exports=function(e){if(Array.isArray(e))return n(e)},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(e){if(Array.isArray(e))return e},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(e,t){var a=e&&("undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"]);if(null!=a){var n,l,c=[],i=!0,s=!1;try{for(a=a.call(e);!(i=(n=a.next()).done)&&(c.push(n.value),!t||c.length!==t);i=!0);}catch(e){s=!0,l=e}finally{try{i||null==a.return||a.return()}finally{if(s)throw l}}return c}},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t,a){"use strict";a.r(t);var n=a(7),l=a(8),c=a.n(l),i=a(9),s=a.n(i),r=a(4),o=a.n(r),m=a(0),u=a(3),b=a(1),p=a(2);function d(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function O(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?d(Object(a),!0).forEach((function(t){c()(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):d(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}var f="notshow",j="optional",y="required",N="summary",h="message",E="redirect",v=function(e,t){var a=React.useState([]),n=o()(a,2),l=n[0],c=n[1],i=React.useState(!1),s=o()(i,2),r=s[0],m=s[1],u=React.useState(!1),b=o()(u,2),p=b[0],d=b[1];return React.useEffect((function(){var a;r||p||(m(!0),jQuery.post(null===(a=ce4wp_form_submit_data)||void 0===a?void 0:a.url,{action:e,nonce:t}).done((function(e){m(!1),d(!0),null!=(null==e?void 0:e.data)&&c(e.data)})))}),[r,p,l]),{data:l,loading:r,hasLoaded:p}};Object(n.registerBlockType)("ce4wp/subscribe",{edit:function(e){var t=this,a=e.attributes,n=e.setAttributes,l=e.className,c=e.clientId;a.blockId||n({blockId:c});var i,r,o=function(){var e,t=v("ce4wp_get_all_custom_lists",null===(e=ce4wp_form_submit_data)||void 0===e?void 0:e.listNonce),a=t.data,n=t.loading,l=t.hasLoaded,c=[];return null!=a&&null!=a.length&&(c=a.map((function(e){return{label:e.name,value:e.id}}))),{customLists:c,loading:n,hasLoaded:l}}().customLists,d={creativeEmailIsActivated:(r=v("ce4wp_creative_email_activated",null===(i=ce4wp_form_submit_data)||void 0===i?void 0:i.activatedNonce)).data,loading:r.loading,hasLoaded:r.hasLoaded}.creativeEmailIsActivated;return Object(m.createElement)("div",{className:"wp-block-ce4wp-subscribe ".concat(l||"")},Object(m.createElement)(b.BlockControls,{key:"setting"},Object(m.createElement)(b.InspectorControls,{key:"setting"},Object(m.createElement)(p.Panel,{header:"Settings"},Object(m.createElement)(p.PanelBody,{title:"Contact Segmentation",initialOpen:!0},Object(m.createElement)(p.PanelRow,{className:"no-flex"},Object(m.createElement)("fieldset",null,Object(m.createElement)("i",{className:"subTitle sub-header"},Object(u.__)("Automatically assign a new contact to a list when they subscribe","ce4wp"),Object(m.createElement)("br",null),Object(m.createElement)(p.ExternalLink,{onClick:function(){return ce4wpNavigateToDashboard(t,"fbcd9606-288a-4d82-be7c-449eaf5a3792",{source:"ce4wp_form_menu"},ce4wpDashboardStartCallback,ce4wpDashboardFinishCallback)}},Object(m.createElement)("span",{id:"ce4wp-manage-lists","data-link_reference":"836b20fc-9ff1-41b2-912b-a8646caf05a4"},Object(u.__)("Manage your lists","ce4wp")))),Object(m.createElement)("br",null),Object(m.createElement)("br",null),Object(m.createElement)(p.SelectControl,{label:"list",value:a.customList,options:[{label:Object(u.__)("Don't assign to a list","cewp4"),value:""}].concat(s()(o)),onChange:function(e){return n({customList:e})}})))),Object(m.createElement)(p.PanelBody,{title:"On submission",initialOpen:!0},Object(m.createElement)(p.PanelRow,null,Object(m.createElement)("fieldset",null,Object(m.createElement)(p.SelectControl,{label:"On submission",value:a.onSubmissionSetting,options:[{label:"Show a custom text message",value:h},{label:"Show a summary of submitted fields",value:N},{label:"Redirect",value:E}],onChange:function(e){return n({onSubmissionSetting:e})}}))),a.onSubmissionSetting===h&&Object(m.createElement)(p.PanelRow,null,Object(m.createElement)("fieldset",null,Object(m.createElement)(p.TextareaControl,{label:"Message text",value:a.onSubmission,onChange:function(e){return n({onSubmission:e})}}))),a.onSubmissionSetting===E&&Object(m.createElement)(p.PanelRow,null,Object(m.createElement)("fieldset",null,Object(m.createElement)(p.TextControl,{label:"Redirect link",value:a.redirectLink,onChange:function(e){return n({redirectLink:e})}})))),Object(m.createElement)(p.PanelBody,{title:"Disclaimer settings",initialOpen:!0},Object(m.createElement)(p.PanelRow,{className:"no-flex"},Object(m.createElement)("fieldset",null,Object(m.createElement)(p.SelectControl,{label:"Permission to mail",value:a.emailPermission,options:[{label:"message",value:"message"},{label:"checkbox",value:"checkbox"}],onChange:function(e){return n(O(O({},a),{},{emailPermission:e}))}})))),Object(m.createElement)(p.PanelBody,{title:"Field settings",initialOpen:!0},Object(m.createElement)(p.PanelRow,{className:"no-flex"},Object(m.createElement)("fieldset",null,Object(m.createElement)(p.SelectControl,{label:"First name field",value:a.displayFirstName,options:[{label:"Do not show",value:f},{label:"Optional",value:j},{label:"Required",value:y}],onChange:function(e){return n({displayFirstName:e})}}))),Object(m.createElement)(p.PanelRow,{className:"no-flex"},Object(m.createElement)("fieldset",null,Object(m.createElement)(p.SelectControl,{label:"Last name field",value:a.displayLastName,options:[{label:"Do not show",value:f},{label:"Optional",value:j},{label:"Required",value:y}],onChange:function(e){return n({displayLastName:e})}}))),Object(m.createElement)(p.PanelRow,{className:"no-flex"},Object(m.createElement)("fieldset",null,Object(m.createElement)(p.SelectControl,{label:"Telephone field",value:a.displayTelephone,options:[{label:"Do not show",value:f},{label:"Optional",value:j},{label:"Required",value:y}],onChange:function(e){return n({displayTelephone:e})}}))))))),Object(m.createElement)("form",{name:"contact-form"},Object(m.createElement)(b.RichText,{tagName:"h2",onChange:function(e){n({title:e})},value:a.title}),Object(m.createElement)(b.RichText,{tagName:"p",className:"subTitle",onChange:function(e){n({subTitle:e})},value:a.subTitle}),!1===d&&Object(m.createElement)("div",{className:"ce4wp-inline-notification ce4wp-inline-warning ce4wp-banner-clickable",onClick:function(){return ce4wpNavigateToDashboard(t,"d25f690a-217a-4d68-9c58-8693965d4673",{source:"ce4wp_form_menu"},ce4wpDashboardStartCallback,ce4wpDashboardFinishCallback)}},Object(m.createElement)(p.Dashicon,{className:"ce4wp-inline-warning-icon",icon:"warning"}),Object(m.createElement)("div",{className:"ce4wp-inline-warning-text"},Object(u.__)("Set up Creative Mail before you use this form on your website.")),Object(m.createElement)(p.Dashicon,{className:"ce4wp-inline-warning-arrow",icon:"arrow-right-alt2"})),a.displayFirstName!==f&&Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText,{tagName:"label",className:"firstNameLabel",onChange:function(e){n({firstNameLabel:e})},value:a.firstNameLabel}),a.displayFirstName===y&&Object(m.createElement)("p",{className:"required-text subTitle",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{name:"first_name",type:"text"})),a.displayLastName!==f&&Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText,{tagName:"label",className:"lastNameLabel",onChange:function(e){n({lastNameLabel:e})},value:a.lastNameLabel}),a.displayLastName===y&&Object(m.createElement)("p",{className:"required-text subTitle",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{name:"last_name",type:"text"})),a.displayTelephone!==f&&Object(m.createElement)("div",{class:"inputBlock"},Object(m.createElement)(b.RichText,{tagName:"label",className:"lastNameLabel",onChange:function(e){n({telephoneLabel:e})},value:a.telephoneLabel}),a.displayTelephone===y&&Object(m.createElement)("p",{className:"required-text subTitle",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{name:"telephone",type:"text"})),Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText,{tagName:"label",className:"emailLabel",onChange:function(e){n({emailLabel:e})},value:a.emailLabel}),Object(m.createElement)("p",{className:"required-text subTitle",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"textwidget",name:"email",type:"text"})),"message"==a.emailPermission&&Object(m.createElement)("div",{className:"disclaimer"},Object(m.createElement)(b.RichText,{tagName:"label",className:"disclaimer-text",onChange:function(e){n({disclaimer:e})},value:a.disclaimer})),"checkbox"==a.emailPermission&&Object(m.createElement)("div",{className:"disclaimer"},Object(m.createElement)("input",{type:"checkbox",name:"consent_check_".concat(c),id:"consent_check_".concat(c)}),Object(m.createElement)(b.RichText,{htmlFor:"consent_check_".concat(c),tagName:"label",className:"consentLabel disclaimer-label",onChange:function(e){n({consentLabel:e})},value:a.consentLabel})),Object(m.createElement)("button",{className:"wp-block-button__link submit-button",type:"button"},Object(u.__)("Subscribe","cewp4"))))},save:function(e){var t=e.attributes,a=e.className;return Object(m.createElement)("div",{className:"wp-block-ce4wp-subscribe ".concat(a||"")},Object(m.createElement)("div",{className:"onSubmission",style:{display:"none"}},Object(m.createElement)("input",{className:"onSubmissionSetting",name:"onSubmissionSetting",type:"hidden",value:t.onSubmissionSetting}),t.onSubmissionSetting!==h&&Object(m.createElement)("div",null,Object(m.createElement)(b.RichText.Content,{className:"title",tagName:"h2",value:t.title})),t.onSubmissionSetting===h&&Object(m.createElement)("div",null,Object(m.createElement)(b.RichText.Content,{className:"title",tagName:"h2",value:t.title}),Object(m.createElement)("p",{className:"subTitle"},t.onSubmission)),t.onSubmissionSetting===N&&Object(m.createElement)("div",null,Object(m.createElement)("h3",null,"You have subscribed"),Object(m.createElement)("br",null),(t.displayFirstName!==f||t.displayLastName!==f)&&Object(m.createElement)("p",null,Object(m.createElement)("span",null,"Name: "),Object(m.createElement)("span",{className:"firstNameSummary"}),Object(m.createElement)("span",{className:"lastNameSummary"})),t.displayTelephone!==f&&Object(m.createElement)("p",null,Object(m.createElement)("span",null,"Telephone: "),Object(m.createElement)("span",{className:"telephoneSummary"})),Object(m.createElement)("p",null,Object(m.createElement)("span",null,"Email: "),Object(m.createElement)("span",{className:"emailSummary"}))),t.onSubmissionSetting===E&&Object(m.createElement)("input",{className:"redirect",name:"redirect",type:"hidden",value:t.redirectLink})),Object(m.createElement)("form",{className:"cm-contact-form",name:"contact-form"},Object(m.createElement)("input",{className:"list_id",name:"list_id",type:"hidden",value:t.customList}),Object(m.createElement)(b.RichText.Content,{className:"title",tagName:"h2",value:t.title})," ",Object(m.createElement)(b.RichText.Content,{className:"subTitle",tagName:"p",value:t.subTitle}),t.displayFirstName!==f&&Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.firstNameLabel}),t.displayFirstName===y&&Object(m.createElement)("span",{className:"wp-caption-text required-text",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"firstName",name:"first_name",type:"text",required:t.displayFirstName===y})),t.displayLastName!==f&&Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.lastNameLabel}),t.displayLastName===y&&Object(m.createElement)("span",{className:"wp-caption-text required-text",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"lastName",name:"last_name",type:"text",required:t.displayLastName===y})),t.displayTelephone!==f&&Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.telephoneLabel}),t.displayTelephone===y&&Object(m.createElement)("span",{className:"wp-caption-text required-text",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"telephone",name:"telephone",type:"tel",pattern:"[+]?[0-9\\(\\)\\s+-]{5,20}",oninvalid:"setCustomValidity('".concat(Object(u.__)("Please enter a valid phone number","creative-mail-by-constant-contact"),"')"),oninput:"setCustomValidity('')",required:t.displayTelephone===y})),Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.emailLabel}),Object(m.createElement)("span",{className:"wp-caption-text required-text",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"email",name:"email",type:"email",oninvalid:"setCustomValidity('".concat(Object(u.__)("Please enter a valid email address","creative-mail-by-constant-contact"),"')"),oninput:"setCustomValidity('')",required:!0})),"message"==t.emailPermission&&Object(m.createElement)("div",{className:"disclaimer"},Object(m.createElement)("input",{className:"consent_check",name:"consent",type:"hidden",checked:!0}),Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.disclaimer})),"checkbox"==t.emailPermission&&Object(m.createElement)("div",{className:"disclaimer"},Object(m.createElement)("input",{className:"consent_check",name:"consent_check_".concat(t.blockId),id:"consent_check_".concat(t.blockId),type:"checkbox"}),Object(m.createElement)(b.RichText.Content,{htmlFor:"consent_check_".concat(t.blockId),tagName:"label",value:t.consentLabel,className:"disclaimer-label"})),Object(m.createElement)("button",{className:"wp-block-button__link submit-button",type:"submit"},Object(u.__)("Subscribe","creative-mail-by-constant-contact"))))},supports:{alignWide:!1},keywords:[Object(u.__)("contact","creative-mail-by-constant-contact"),Object(u.__)("form","creative-mail-by-constant-contact"),Object(u.__)("email","creative-mail-by-constant-contact"),Object(u.__)("mail","creative-mail-by-constant-contact")],deprecated:[{attributes:{blockId:{type:"string"},title:{type:"string",default:"Subscribe"},subTitle:{type:"string",default:"Sign up for our newsletter and stay up to date"},firstNameLabel:{type:"string",default:"First name"},lastNameLabel:{type:"string",default:"Last name"},emailLabel:{type:"string",default:"Email"},telephoneLabel:{type:"string",default:"Telephone"},emailPermission:{type:"string",default:"checkbox"},displayTelephone:{type:"string",default:"notshow"},displayFirstName:{type:"string",default:"optional"},displayLastName:{type:"string",default:"optional"},onSubmission:{type:"string",selector:"div",default:"Thank you for subscribing!"},customList:{type:"string",default:null}},save:function(e){var t=e.attributes,a=e.className;return Object(m.createElement)("div",{className:"wp-block-ce4wp-subscribe ".concat(a||"")},Object(m.createElement)("div",{className:"onSubmission",style:{display:"none"}},Object(m.createElement)(b.RichText.Content,{className:"title",tagName:"h2",value:t.title}),Object(m.createElement)("p",{className:"subTitle"},t.onSubmission)),Object(m.createElement)("form",{className:"cm-contact-form",name:"contact-form"},Object(m.createElement)("input",{className:"list_id",name:"list_id",type:"hidden",value:t.customList}),Object(m.createElement)(b.RichText.Content,{className:"title",tagName:"h2",value:t.title})," ",Object(m.createElement)(b.RichText.Content,{className:"subTitle",tagName:"p",value:t.subTitle}),t.displayFirstName!==f&&Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.firstNameLabel}),t.displayFirstName===y&&Object(m.createElement)("span",{className:"wp-caption-text required-text",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"firstName",name:"first_name",type:"text",required:t.displayFirstName===y})),t.displayLastName!==f&&Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.lastNameLabel}),t.displayLastName===y&&Object(m.createElement)("span",{className:"wp-caption-text required-text",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"lastName",name:"last_name",type:"text",required:t.displayFirstName===y})),t.displayTelephone!==f&&Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.telephoneLabel}),t.displayTelephone===y&&Object(m.createElement)("span",{className:"wp-caption-text required-text",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"telephone",name:"telephone",type:"tel",pattern:"[+]?[0-9\\(\\)\\s+-]{5,20}",oninvalid:"setCustomValidity('".concat(Object(u.__)("Please enter a valid phone number","creative-mail-by-constant-contact"),"')"),oninput:"setCustomValidity('')",required:t.displayFirstName===y})),Object(m.createElement)("div",{className:"inputBlock"},Object(m.createElement)(b.RichText.Content,{tagName:"label",value:t.emailLabel}),Object(m.createElement)("span",{className:"wp-caption-text required-text",style:{color:"#ee0000"}},"*"),Object(m.createElement)("input",{className:"email",name:"email",type:"email",oninvalid:"setCustomValidity('".concat(Object(u.__)("Please enter a valid email address","creative-mail-by-constant-contact"),"')"),oninput:"setCustomValidity('')",required:!0})),"message"==t.emailPermission&&Object(m.createElement)("span",{className:"disclaimer"},Object(m.createElement)("input",{className:"consent_check",name:"consent",type:"hidden",checked:!0}),Object(u.__)("By submitting your information, you are granting us permission to email you. You may unsubscribe at any time.","creative-mail-by-constant-contact")),"checkbox"==t.emailPermission&&Object(m.createElement)("span",null,Object(m.createElement)("input",{className:"consent_check",name:"consent_check_".concat(t.blockId),id:"consent_check_".concat(t.blockId),type:"checkbox"}),Object(m.createElement)("label",{htmlFor:"consent_check_".concat(t.blockId),className:"disclaimer"},Object(u.__)("Can we send you an email from time to time?","creative-mail-by-constant-contact"))),Object(m.createElement)("button",{className:"wp-block-button__link submit-button",type:"submit"},Object(u.__)("Subscribe","creative-mail-by-constant-contact"))))}}]})}]);
assets/js/deactivation.js CHANGED
@@ -4,48 +4,48 @@
4
  * @package CreativeMail
5
  */
6
  jQuery(function($){
7
- var deactivateLink = $('#the-list').find('[data-slug="creative-mail-by-constant-contact"] span.deactivate a');
8
- var form = $('#ce4wp-deactivate-survey-form');
9
- var thankyou = $('#ce4wp-deactivate-survey-form-success');
10
- var overlay = $('#ce4wp-deactivate-survey');
11
- var closeButton = $('#ce4wp-deactivate-survey-close');
12
- var formOpen = false;
13
 
14
- deactivateLink.on('click', function(event) {
15
- event.preventDefault();
16
- overlay.css('display', 'table');
17
- formOpen = true;
18
- });
19
 
20
- form.on('submit', function (event) {
21
- event.preventDefault();
22
 
23
- var formData = jQuery(this).serialize();
24
- jQuery.ajax({
25
- type : "POST",
26
- url : ce4wp_data.url,
27
- data : {
28
- nonce: ce4wp_data.nonce,
29
- data: formData,
30
- action: 'ce4wp_deactivate_survey'
31
- },
32
- success: function(data){
33
- form.hide();
34
- thankyou.show();
35
- }
36
- });
37
- });
38
 
39
- closeButton.on('click', function(event) {
40
- event.preventDefault();
41
- overlay.css('display', 'none');
42
- formOpen = false;
43
- location.href = deactivateLink.attr('href');
44
- });
45
 
46
- $(document).keyup(function(event) {
47
- if ((event.keyCode === 27) && formOpen) {
48
- location.href = deactivateLink.attr('href');
49
- }
50
- });
51
  });
4
  * @package CreativeMail
5
  */
6
  jQuery(function($){
7
+ var deactivateLink = $('#the-list').find('[data-slug="creative-mail-by-constant-contact"] span.deactivate a');
8
+ var form = $('#ce4wp-deactivate-survey-form');
9
+ var thankyou = $('#ce4wp-deactivate-survey-form-success');
10
+ var overlay = $('#ce4wp-deactivate-survey');
11
+ var closeButton = $('#ce4wp-deactivate-survey-close');
12
+ var formOpen = false;
13
 
14
+ deactivateLink.on('click', function(event) {
15
+ event.preventDefault();
16
+ overlay.css('display', 'table');
17
+ formOpen = true;
18
+ });
19
 
20
+ form.on('submit', function (event) {
21
+ event.preventDefault();
22
 
23
+ var formData = jQuery(this).serialize();
24
+ jQuery.ajax({
25
+ type : "POST",
26
+ url : ce4wp_data.url,
27
+ data : {
28
+ nonce: ce4wp_data.nonce,
29
+ data: formData,
30
+ action: 'ce4wp_deactivate_survey'
31
+ },
32
+ success: function(data){
33
+ form.hide();
34
+ thankyou.show();
35
+ }
36
+ });
37
+ });
38
 
39
+ closeButton.on('click', function(event) {
40
+ event.preventDefault();
41
+ overlay.css('display', 'none');
42
+ formOpen = false;
43
+ location.href = deactivateLink.attr('href');
44
+ });
45
 
46
+ $(document).keyup(function(event) {
47
+ if ((event.keyCode === 27) && formOpen) {
48
+ location.href = deactivateLink.attr('href');
49
+ }
50
+ });
51
  });
assets/js/feedback_notice.js CHANGED
@@ -5,25 +5,25 @@
5
  */
6
  jQuery(function($){
7
 
8
- window.addEventListener('load', () => {
9
- const parent = document.getElementById('wpbody-content')
10
- const screenMetaLinks = document.getElementById('screen-meta-links')
11
 
12
- const notice = document.getElementById('ce4wp-admin-feedback-notice')
13
 
14
- if ([parent, screenMetaLinks, notice].some(element => element == null)) {
15
- return
16
- }
17
 
18
- parent.insertBefore(notice, screenMetaLinks.nextSibling)
19
- notice.hidden = false
20
- });
21
 
22
  });
23
 
24
  function hideAdminFeedbackNotice (banner) {
25
- document.querySelector('#ce4wp-admin-feedback-notice').hidden = true
26
 
27
- const { hide_banner_url } = ce4wp_data
28
- fetch(`${hide_banner_url}${banner}`, { method: 'POST' })
29
  }
5
  */
6
  jQuery(function($){
7
 
8
+ window.addEventListener('load', () => {
9
+ const parent = document.getElementById('wpbody-content')
10
+ const screenMetaLinks = document.getElementById('screen-meta-links')
11
 
12
+ const notice = document.getElementById('ce4wp-admin-feedback-notice')
13
 
14
+ if ([parent, screenMetaLinks, notice].some(element => element == null)) {
15
+ return
16
+ }
17
 
18
+ parent.insertBefore(notice, screenMetaLinks.nextSibling)
19
+ notice.hidden = false
20
+ });
21
 
22
  });
23
 
24
  function hideAdminFeedbackNotice (banner) {
25
+ document.querySelector('#ce4wp-admin-feedback-notice').hidden = true
26
 
27
+ const { hide_banner_url } = ce4wp_data
28
+ fetch(`${hide_banner_url}${banner}`, { method: 'POST' })
29
  }
assets/js/footer_rating.js CHANGED
@@ -4,6 +4,6 @@
4
  * @package CreativeMail
5
  */
6
  jQuery( 'a.ce4wp-rating-link' ).click( function() {
7
- jQuery.post( 'admin-ajax.php', { action: 'woocommerce_ce4wp_rated' } );
8
- jQuery( this ).parent().text( jQuery( this ).data( 'rated' ) );
9
- });
4
  * @package CreativeMail
5
  */
6
  jQuery( 'a.ce4wp-rating-link' ).click( function() {
7
+ jQuery.post( 'admin-ajax.php', { action: 'woocommerce_ce4wp_rated' } );
8
+ jQuery( this ).parent().text( jQuery( this ).data( 'rated' ) );
9
+ });
composer.json CHANGED
@@ -12,11 +12,17 @@
12
  "ext-curl": "*",
13
  "ext-json": "*",
14
  "a5hleyrich/wp-background-processing": "^1.0",
15
- "squizlabs/php_codesniffer": "*",
16
  "ext-zip": "*",
17
  "mindscape/raygun4php": "1.*",
 
18
  "phpcompatibility/php-compatibility": "^9.3"
19
  },
 
 
 
 
 
 
20
  "autoload": {
21
  "psr-4": {
22
  "CreativeMail\\Managers\\": "src/managers/",
@@ -28,11 +34,5 @@
28
  "CreativeMail\\Blocks\\": "src/blocks/",
29
  "CreativeMail\\": "src/"
30
  }
31
- },
32
- "require-dev": {
33
- "phpstan/phpstan": "^1.8",
34
- "szepeviktor/phpstan-wordpress": "^1.1",
35
- "phpstan/extension-installer": "^1.1",
36
- "php-stubs/woocommerce-stubs": "^6.9"
37
  }
38
  }
12
  "ext-curl": "*",
13
  "ext-json": "*",
14
  "a5hleyrich/wp-background-processing": "^1.0",
 
15
  "ext-zip": "*",
16
  "mindscape/raygun4php": "1.*",
17
+ "squizlabs/php_codesniffer": "*",
18
  "phpcompatibility/php-compatibility": "^9.3"
19
  },
20
+ "require-dev": {
21
+ "phpstan/phpstan": "^1.8",
22
+ "szepeviktor/phpstan-wordpress": "^1.1",
23
+ "phpstan/extension-installer": "^1.1",
24
+ "php-stubs/woocommerce-stubs": "^6.9"
25
+ },
26
  "autoload": {
27
  "psr-4": {
28
  "CreativeMail\\Managers\\": "src/managers/",
34
  "CreativeMail\\Blocks\\": "src/blocks/",
35
  "CreativeMail\\": "src/"
36
  }
 
 
 
 
 
 
37
  }
38
  }
composer.lock CHANGED
@@ -4,7 +4,7 @@
4
  "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5
  "This file is @generated automatically"
6
  ],
7
- "content-hash": "29273c6343a1bdf1ea050939233aab9b",
8
  "packages": [
9
  {
10
  "name": "a5hleyrich/wp-background-processing",
@@ -43,10 +43,6 @@
43
  }
44
  ],
45
  "description": "WP Background Processing can be used to fire off non-blocking asynchronous requests or as a background processing tool, allowing you to queue tasks.",
46
- "support": {
47
- "issues": "https://github.com/deliciousbrains/wp-background-processing/issues",
48
- "source": "https://github.com/deliciousbrains/wp-background-processing/tree/1.0.2"
49
- },
50
  "time": "2020-07-31T07:00:11+00:00"
51
  },
52
  {
@@ -109,10 +105,6 @@
109
  "security",
110
  "symmetric key cryptography"
111
  ],
112
- "support": {
113
- "issues": "https://github.com/defuse/php-encryption/issues",
114
- "source": "https://github.com/defuse/php-encryption/tree/v2.3.1"
115
- },
116
  "time": "2021-04-09T23:57:26+00:00"
117
  },
118
  {
@@ -166,24 +158,20 @@
166
  "jwt",
167
  "php"
168
  ],
169
- "support": {
170
- "issues": "https://github.com/firebase/php-jwt/issues",
171
- "source": "https://github.com/firebase/php-jwt/tree/v5.5.1"
172
- },
173
  "time": "2021-11-08T20:18:51+00:00"
174
  },
175
  {
176
  "name": "mindscape/raygun4php",
177
- "version": "v1.8.4",
178
  "source": {
179
  "type": "git",
180
  "url": "https://github.com/MindscapeHQ/raygun4php.git",
181
- "reference": "7f841d251f5985817cec93e131bb334561c03338"
182
  },
183
  "dist": {
184
  "type": "zip",
185
- "url": "https://api.github.com/repos/MindscapeHQ/raygun4php/zipball/7f841d251f5985817cec93e131bb334561c03338",
186
- "reference": "7f841d251f5985817cec93e131bb334561c03338",
187
  "shasum": ""
188
  },
189
  "require": {
@@ -220,11 +208,7 @@
220
  "logging",
221
  "raygun"
222
  ],
223
- "support": {
224
- "issues": "https://github.com/MindscapeHQ/raygun4php/issues",
225
- "source": "https://github.com/MindscapeHQ/raygun4php/tree/v1.8.4"
226
- },
227
- "time": "2019-03-07T01:23:01+00:00"
228
  },
229
  {
230
  "name": "paragonie/random_compat",
@@ -269,11 +253,6 @@
269
  "pseudorandom",
270
  "random"
271
  ],
272
- "support": {
273
- "email": "info@paragonie.com",
274
- "issues": "https://github.com/paragonie/random_compat/issues",
275
- "source": "https://github.com/paragonie/random_compat"
276
- },
277
  "time": "2020-10-15T08:29:30+00:00"
278
  },
279
  {
@@ -332,24 +311,20 @@
332
  "phpcs",
333
  "standards"
334
  ],
335
- "support": {
336
- "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues",
337
- "source": "https://github.com/PHPCompatibility/PHPCompatibility"
338
- },
339
  "time": "2019-12-27T09:44:58+00:00"
340
  },
341
  {
342
  "name": "squizlabs/php_codesniffer",
343
- "version": "3.6.2",
344
  "source": {
345
  "type": "git",
346
  "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
347
- "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a"
348
  },
349
  "dist": {
350
  "type": "zip",
351
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a",
352
- "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a",
353
  "shasum": ""
354
  },
355
  "require": {
@@ -387,27 +362,22 @@
387
  "phpcs",
388
  "standards"
389
  ],
390
- "support": {
391
- "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
392
- "source": "https://github.com/squizlabs/PHP_CodeSniffer",
393
- "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
394
- },
395
- "time": "2021-12-12T21:44:58+00:00"
396
  }
397
  ],
398
  "packages-dev": [
399
  {
400
  "name": "php-stubs/woocommerce-stubs",
401
- "version": "v6.9.3",
402
  "source": {
403
  "type": "git",
404
  "url": "https://github.com/php-stubs/woocommerce-stubs.git",
405
- "reference": "870c0c0abcd5ae9a8be58fc797123a4d882e604e"
406
  },
407
  "dist": {
408
  "type": "zip",
409
- "url": "https://api.github.com/repos/php-stubs/woocommerce-stubs/zipball/870c0c0abcd5ae9a8be58fc797123a4d882e604e",
410
- "reference": "870c0c0abcd5ae9a8be58fc797123a4d882e604e",
411
  "shasum": ""
412
  },
413
  "require": {
@@ -434,24 +404,20 @@
434
  "woocommerce",
435
  "wordpress"
436
  ],
437
- "support": {
438
- "issues": "https://github.com/php-stubs/woocommerce-stubs/issues",
439
- "source": "https://github.com/php-stubs/woocommerce-stubs/tree/v6.9.3"
440
- },
441
- "time": "2022-09-20T23:28:43+00:00"
442
  },
443
  {
444
  "name": "php-stubs/wordpress-stubs",
445
- "version": "v6.0.1",
446
  "source": {
447
  "type": "git",
448
  "url": "https://github.com/php-stubs/wordpress-stubs.git",
449
- "reference": "e04781a84e364615a7b5f70fdc345c8253ca5b8f"
450
  },
451
  "dist": {
452
  "type": "zip",
453
- "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/e04781a84e364615a7b5f70fdc345c8253ca5b8f",
454
- "reference": "e04781a84e364615a7b5f70fdc345c8253ca5b8f",
455
  "shasum": ""
456
  },
457
  "replace": {
@@ -481,11 +447,7 @@
481
  "static analysis",
482
  "wordpress"
483
  ],
484
- "support": {
485
- "issues": "https://github.com/php-stubs/wordpress-stubs/issues",
486
- "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.0.1"
487
- },
488
- "time": "2022-07-15T11:10:45+00:00"
489
  },
490
  {
491
  "name": "phpstan/extension-installer",
@@ -526,24 +488,20 @@
526
  "MIT"
527
  ],
528
  "description": "Composer plugin for automatic installation of PHPStan extensions",
529
- "support": {
530
- "issues": "https://github.com/phpstan/extension-installer/issues",
531
- "source": "https://github.com/phpstan/extension-installer/tree/1.1.0"
532
- },
533
  "time": "2020-12-13T13:06:13+00:00"
534
  },
535
  {
536
  "name": "phpstan/phpstan",
537
- "version": "1.8.2",
538
  "source": {
539
  "type": "git",
540
  "url": "https://github.com/phpstan/phpstan.git",
541
- "reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c"
542
  },
543
  "dist": {
544
  "type": "zip",
545
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c53312ecc575caf07b0e90dee43883fdf90ca67c",
546
- "reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c",
547
  "shasum": ""
548
  },
549
  "require": {
@@ -567,10 +525,10 @@
567
  "MIT"
568
  ],
569
  "description": "PHPStan - PHP Static Analysis Tool",
570
- "support": {
571
- "issues": "https://github.com/phpstan/phpstan/issues",
572
- "source": "https://github.com/phpstan/phpstan/tree/1.8.2"
573
- },
574
  "funding": [
575
  {
576
  "url": "https://github.com/ondrejmirtes",
@@ -580,16 +538,12 @@
580
  "url": "https://github.com/phpstan",
581
  "type": "github"
582
  },
583
- {
584
- "url": "https://www.patreon.com/phpstan",
585
- "type": "patreon"
586
- },
587
  {
588
  "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan",
589
  "type": "tidelift"
590
  }
591
  ],
592
- "time": "2022-07-20T09:57:31+00:00"
593
  },
594
  {
595
  "name": "symfony/polyfill-php73",
@@ -651,9 +605,6 @@
651
  "portable",
652
  "shim"
653
  ],
654
- "support": {
655
- "source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0"
656
- },
657
  "funding": [
658
  {
659
  "url": "https://symfony.com/sponsor",
@@ -723,10 +674,6 @@
723
  "static analysis",
724
  "wordpress"
725
  ],
726
- "support": {
727
- "issues": "https://github.com/szepeviktor/phpstan-wordpress/issues",
728
- "source": "https://github.com/szepeviktor/phpstan-wordpress/tree/v1.1.3"
729
- },
730
  "funding": [
731
  {
732
  "url": "https://www.paypal.me/szepeviktor",
@@ -751,5 +698,5 @@
751
  "ext-zip": "*"
752
  },
753
  "platform-dev": [],
754
- "plugin-api-version": "2.3.0"
755
  }
4
  "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5
  "This file is @generated automatically"
6
  ],
7
+ "content-hash": "a595f3993052611cb44112c86eb8ba52",
8
  "packages": [
9
  {
10
  "name": "a5hleyrich/wp-background-processing",
43
  }
44
  ],
45
  "description": "WP Background Processing can be used to fire off non-blocking asynchronous requests or as a background processing tool, allowing you to queue tasks.",
 
 
 
 
46
  "time": "2020-07-31T07:00:11+00:00"
47
  },
48
  {
105
  "security",
106
  "symmetric key cryptography"
107
  ],
 
 
 
 
108
  "time": "2021-04-09T23:57:26+00:00"
109
  },
110
  {
158
  "jwt",
159
  "php"
160
  ],
 
 
 
 
161
  "time": "2021-11-08T20:18:51+00:00"
162
  },
163
  {
164
  "name": "mindscape/raygun4php",
165
+ "version": "v1.8.5",
166
  "source": {
167
  "type": "git",
168
  "url": "https://github.com/MindscapeHQ/raygun4php.git",
169
+ "reference": "ab5401d7bd042ce69810763274d250ac9c10068a"
170
  },
171
  "dist": {
172
  "type": "zip",
173
+ "url": "https://api.github.com/repos/MindscapeHQ/raygun4php/zipball/ab5401d7bd042ce69810763274d250ac9c10068a",
174
+ "reference": "ab5401d7bd042ce69810763274d250ac9c10068a",
175
  "shasum": ""
176
  },
177
  "require": {
208
  "logging",
209
  "raygun"
210
  ],
211
+ "time": "2022-07-11T22:19:37+00:00"
 
 
 
 
212
  },
213
  {
214
  "name": "paragonie/random_compat",
253
  "pseudorandom",
254
  "random"
255
  ],
 
 
 
 
 
256
  "time": "2020-10-15T08:29:30+00:00"
257
  },
258
  {
311
  "phpcs",
312
  "standards"
313
  ],
 
 
 
 
314
  "time": "2019-12-27T09:44:58+00:00"
315
  },
316
  {
317
  "name": "squizlabs/php_codesniffer",
318
+ "version": "3.7.1",
319
  "source": {
320
  "type": "git",
321
  "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
322
+ "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619"
323
  },
324
  "dist": {
325
  "type": "zip",
326
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619",
327
+ "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619",
328
  "shasum": ""
329
  },
330
  "require": {
362
  "phpcs",
363
  "standards"
364
  ],
365
+ "time": "2022-06-18T07:21:10+00:00"
 
 
 
 
 
366
  }
367
  ],
368
  "packages-dev": [
369
  {
370
  "name": "php-stubs/woocommerce-stubs",
371
+ "version": "v6.9.4",
372
  "source": {
373
  "type": "git",
374
  "url": "https://github.com/php-stubs/woocommerce-stubs.git",
375
+ "reference": "823aa38297d9013b96c5eab2846c260bbe12b975"
376
  },
377
  "dist": {
378
  "type": "zip",
379
+ "url": "https://api.github.com/repos/php-stubs/woocommerce-stubs/zipball/823aa38297d9013b96c5eab2846c260bbe12b975",
380
+ "reference": "823aa38297d9013b96c5eab2846c260bbe12b975",
381
  "shasum": ""
382
  },
383
  "require": {
404
  "woocommerce",
405
  "wordpress"
406
  ],
407
+ "time": "2022-10-12T08:01:21+00:00"
 
 
 
 
408
  },
409
  {
410
  "name": "php-stubs/wordpress-stubs",
411
+ "version": "v6.0.2",
412
  "source": {
413
  "type": "git",
414
  "url": "https://github.com/php-stubs/wordpress-stubs.git",
415
+ "reference": "165b84f082db851e76ec51bebcde550d03976893"
416
  },
417
  "dist": {
418
  "type": "zip",
419
+ "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/165b84f082db851e76ec51bebcde550d03976893",
420
+ "reference": "165b84f082db851e76ec51bebcde550d03976893",
421
  "shasum": ""
422
  },
423
  "replace": {
447
  "static analysis",
448
  "wordpress"
449
  ],
450
+ "time": "2022-09-30T17:46:11+00:00"
 
 
 
 
451
  },
452
  {
453
  "name": "phpstan/extension-installer",
488
  "MIT"
489
  ],
490
  "description": "Composer plugin for automatic installation of PHPStan extensions",
 
 
 
 
491
  "time": "2020-12-13T13:06:13+00:00"
492
  },
493
  {
494
  "name": "phpstan/phpstan",
495
+ "version": "1.8.11",
496
  "source": {
497
  "type": "git",
498
  "url": "https://github.com/phpstan/phpstan.git",
499
+ "reference": "46e223dd68a620da18855c23046ddb00940b4014"
500
  },
501
  "dist": {
502
  "type": "zip",
503
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/46e223dd68a620da18855c23046ddb00940b4014",
504
+ "reference": "46e223dd68a620da18855c23046ddb00940b4014",
505
  "shasum": ""
506
  },
507
  "require": {
525
  "MIT"
526
  ],
527
  "description": "PHPStan - PHP Static Analysis Tool",
528
+ "keywords": [
529
+ "dev",
530
+ "static analysis"
531
+ ],
532
  "funding": [
533
  {
534
  "url": "https://github.com/ondrejmirtes",
538
  "url": "https://github.com/phpstan",
539
  "type": "github"
540
  },
 
 
 
 
541
  {
542
  "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan",
543
  "type": "tidelift"
544
  }
545
  ],
546
+ "time": "2022-10-24T15:45:13+00:00"
547
  },
548
  {
549
  "name": "symfony/polyfill-php73",
605
  "portable",
606
  "shim"
607
  ],
 
 
 
608
  "funding": [
609
  {
610
  "url": "https://symfony.com/sponsor",
674
  "static analysis",
675
  "wordpress"
676
  ],
 
 
 
 
677
  "funding": [
678
  {
679
  "url": "https://www.paypal.me/szepeviktor",
698
  "ext-zip": "*"
699
  },
700
  "platform-dev": [],
701
+ "plugin-api-version": "1.1.0"
702
  }
creative-mail-plugin.php CHANGED
@@ -3,24 +3,24 @@
3
  * Creative Mail by Constant Contact
4
  *
5
  * @package CreativeMail
6
- */
7
  /**
8
  * Plugin Name: Creative Mail by Constant Contact
9
  * Plugin URI: https://wordpress.org/plugins/creative-mail-by-constant-contact/
10
  * Description: Free email marketing designed specifically for WordPress, Jetpack and WooCommerce. Send newsletters, promotions, updates and transactional e-commerce emails. Simple and easy, powered by Constant Contact’s rock solid reliability.
11
  * Author: Constant Contact
12
- * Version: 1.6.0
13
  * Author URI: https://www.constantcontact.com
14
  * WC requires at least: 3.6.0
15
  * WC tested up to: 6.8.2
16
- */
17
  use CreativeMail\CreativeMail;
18
  use CreativeMail\Blocks\LoadBlock;
19
 
20
  define('CE4WP_PLUGIN_DIR', __DIR__ . '/');
21
  define('CE4WP_PLUGIN_URL', plugin_dir_url(__FILE__) . '/');
22
  define('CE4WP_PLUGIN_FILE', __FILE__);
23
- define('CE4WP_PLUGIN_VERSION', '1.6.0');
24
  define('CE4WP_INSTANCE_UUID_KEY', 'ce4wp_instance_uuid');
25
  define('CE4WP_INSTANCE_HANDSHAKE_TOKEN', 'ce4wp_handshake_token');
26
  define('CE4WP_INSTANCE_HANDSHAKE_EXPIRATION', 'ce4wp_handshake_expiration');
@@ -37,7 +37,7 @@ define('CE4WP_CHECKOUT_CHECKBOX_ENABLED', 'ce4wp_checkout_checkbox_enabled');
37
  define('CE4WP_APP_GATEWAY_URL', 'https://app-gateway.creativemail.com/');
38
  define('CE4WP_APP_URL', 'https://app.creativemail.com/');
39
  define('CE4WP_ENVIRONMENT', 'PRODUCTION');
40
- define('CE4WP_BUILD_NUMBER', '1834');
41
  define('CE4WP_RAYGUN_PHP_KEY', 'Z85xL3mkgnW13Ri9DajGUg');
42
  define('CE4WP_BATCH_SIZE', 500);
43
  define('CE4WP_WC_API_KEY_ID', 'ce4wp_woocommerce_api_key_id');
@@ -45,73 +45,98 @@ define('CE4WP_WC_API_CONSUMER_KEY', 'ce4wp_woocommerce_consumer_key');
45
  define('CE4WP_REFERRED_BY', 'ce4wp_referred_by');
46
  define('CE4WP_HIDE_BANNER', 'ce4wp_hide_banner');
47
 
48
- function _load_ce4wp_plugin()
49
- {
50
- global $creativemail;
 
 
 
 
51
 
52
- if ($creativemail != null) {
53
- return true;
54
- }
55
 
56
- // Load all the required files.
57
- if (file_exists(__DIR__ . '/vendor/autoload.php')) {
58
- include_once __DIR__ . '/vendor/autoload.php';
59
- }
60
 
61
- $creativemail = CreativeMail::get_instance();
62
- $creativemail->add_hooks();
63
 
64
- if (version_compare($GLOBALS['wp_version'], '5.5', '>=')) {
65
- $loadBlock = LoadBlock::get_instance();
66
- $loadBlock->add_hooks();
67
- }
68
 
69
- return true;
70
  }
71
 
72
- function ce4wp_deactivate()
73
- {
74
- delete_option('ce4wp_activated');
75
- delete_option('ce4wp_install_date');
 
 
 
 
76
  }
77
 
78
- function ce4wp_activate()
79
- {
80
- add_option('ce4wp_activated', true);
81
- add_option('ce4wp_install_date', date('Y-m-d G:i:s'), '', 'yes');
82
- if (( isset($_REQUEST['action']) && 'activate-selected' === $_REQUEST['action'] )
83
- && ( isset($_POST['checked']) && count($_POST['checked']) > 1 )
84
- ) {
85
- return;
86
- }
87
- add_option('ce4wp_activation_redirect', wp_get_current_user()->ID);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  }
89
 
90
  add_action('plugins_loaded', '_load_ce4wp_plugin', 10);
91
  register_activation_hook(__FILE__, 'ce4wp_activate');
92
  register_deactivation_hook(__FILE__, 'ce4wp_deactivate');
93
 
94
- // Add on submit to subscribe buttons
95
  add_action('init', 'ce4wp_add_front_end_on_submit');
96
- function ce4wp_add_front_end_on_submit()
97
- {
98
- wp_enqueue_script(
99
- 'ce4wp_form_submit',
100
- plugins_url('assets/js/block/submit.js', __FILE__),
101
- array('jquery'),
102
- filemtime( plugin_dir_path( __FILE__ ) . 'assets/js/block/submit.js' ),
103
- true
104
- );
105
-
106
- wp_localize_script(
107
- 'ce4wp_form_submit',
108
- 'ce4wp_form_submit_data',
109
- [
110
- 'siteUrl' => get_site_url(),
111
- 'url' => admin_url('admin-ajax.php'),
112
- 'nonce' => wp_create_nonce( 'ce4wp_form_submission'),
113
- 'listNonce' => wp_create_nonce( 'ce4wp_get_lists' ),
114
- 'activatedNonce' => wp_create_nonce( 'ce4wp_get_creative_email_activated' )
115
- ]
116
- );
117
- }
3
  * Creative Mail by Constant Contact
4
  *
5
  * @package CreativeMail
6
+ */
7
  /**
8
  * Plugin Name: Creative Mail by Constant Contact
9
  * Plugin URI: https://wordpress.org/plugins/creative-mail-by-constant-contact/
10
  * Description: Free email marketing designed specifically for WordPress, Jetpack and WooCommerce. Send newsletters, promotions, updates and transactional e-commerce emails. Simple and easy, powered by Constant Contact’s rock solid reliability.
11
  * Author: Constant Contact
12
+ * Version: 1.6.1
13
  * Author URI: https://www.constantcontact.com
14
  * WC requires at least: 3.6.0
15
  * WC tested up to: 6.8.2
16
+ */
17
  use CreativeMail\CreativeMail;
18
  use CreativeMail\Blocks\LoadBlock;
19
 
20
  define('CE4WP_PLUGIN_DIR', __DIR__ . '/');
21
  define('CE4WP_PLUGIN_URL', plugin_dir_url(__FILE__) . '/');
22
  define('CE4WP_PLUGIN_FILE', __FILE__);
23
+ define('CE4WP_PLUGIN_VERSION', '1.6.1');
24
  define('CE4WP_INSTANCE_UUID_KEY', 'ce4wp_instance_uuid');
25
  define('CE4WP_INSTANCE_HANDSHAKE_TOKEN', 'ce4wp_handshake_token');
26
  define('CE4WP_INSTANCE_HANDSHAKE_EXPIRATION', 'ce4wp_handshake_expiration');
37
  define('CE4WP_APP_GATEWAY_URL', 'https://app-gateway.creativemail.com/');
38
  define('CE4WP_APP_URL', 'https://app.creativemail.com/');
39
  define('CE4WP_ENVIRONMENT', 'PRODUCTION');
40
+ define('CE4WP_BUILD_NUMBER', '1907');
41
  define('CE4WP_RAYGUN_PHP_KEY', 'Z85xL3mkgnW13Ri9DajGUg');
42
  define('CE4WP_BATCH_SIZE', 500);
43
  define('CE4WP_WC_API_KEY_ID', 'ce4wp_woocommerce_api_key_id');
45
  define('CE4WP_REFERRED_BY', 'ce4wp_referred_by');
46
  define('CE4WP_HIDE_BANNER', 'ce4wp_hide_banner');
47
 
48
+ /**
49
+ * Loads the plugin.
50
+ *
51
+ * @return bool
52
+ */
53
+ function _load_ce4wp_plugin() {
54
+ global $creativemail;
55
 
56
+ if ( null != $creativemail ) {
57
+ return true;
58
+ }
59
 
60
+ // Load all the required files.
61
+ if ( file_exists(__DIR__ . '/vendor/autoload.php') ) {
62
+ include_once __DIR__ . '/vendor/autoload.php';
63
+ }
64
 
65
+ $creativemail = CreativeMail::get_instance();
66
+ $creativemail->add_hooks();
67
 
68
+ if ( version_compare($GLOBALS['wp_version'], '5.5', '>=') ) {
69
+ $load_block = LoadBlock::get_instance();
70
+ $load_block->add_hooks();
71
+ }
72
 
73
+ return true;
74
  }
75
 
76
+ /**
77
+ * Deactivates the plugin.
78
+ *
79
+ * @return void
80
+ */
81
+ function ce4wp_deactivate() {
82
+ delete_option('ce4wp_activated');
83
+ delete_option('ce4wp_install_date');
84
  }
85
 
86
+ /**
87
+ * Activates the plugin.
88
+ *
89
+ * @return void
90
+ */
91
+ function ce4wp_activate() {
92
+ $nonce_action = 'activate-plugin_' . plugin_basename( __FILE__ );
93
+
94
+ add_option('ce4wp_activated', true);
95
+ add_option('ce4wp_install_date', gmdate('Y-m-d G:i:s'));
96
+
97
+ if ( isset ( $_REQUEST['_wpnonce'] )
98
+ && wp_verify_nonce( sanitize_text_field(wp_unslash($_REQUEST['_wpnonce'])), $nonce_action )
99
+ ) {
100
+ if ( ( isset($_REQUEST['action']) && 'activate-selected' === $_REQUEST['action'] )
101
+ && ( isset($_POST['checked']) && count($_POST['checked']) > 1 )
102
+ ) {
103
+ return;
104
+ }
105
+ }
106
+
107
+ add_option('ce4wp_activation_redirect', wp_get_current_user()->ID);
108
+ }
109
+
110
+ /**
111
+ * Adds plugin front-end scripts.
112
+ *
113
+ * @return void
114
+ */
115
+ function ce4wp_add_front_end_on_submit() {
116
+ wp_enqueue_script(
117
+ 'ce4wp_form_submit',
118
+ plugins_url('assets/js/block/submit.js', __FILE__),
119
+ array( 'jquery' ),
120
+ filemtime( plugin_dir_path( __FILE__ ) . 'assets/js/block/submit.js' ),
121
+ true
122
+ );
123
+
124
+ wp_localize_script(
125
+ 'ce4wp_form_submit',
126
+ 'ce4wp_form_submit_data',
127
+ array(
128
+ 'siteUrl' => get_site_url(),
129
+ 'url' => admin_url('admin-ajax.php'),
130
+ 'nonce' => wp_create_nonce( 'ce4wp_form_submission' ),
131
+ 'listNonce' => wp_create_nonce( 'ce4wp_get_lists' ),
132
+ 'activatedNonce' => wp_create_nonce( 'ce4wp_get_creative_email_activated' ),
133
+ )
134
+ );
135
  }
136
 
137
  add_action('plugins_loaded', '_load_ce4wp_plugin', 10);
138
  register_activation_hook(__FILE__, 'ce4wp_activate');
139
  register_deactivation_hook(__FILE__, 'ce4wp_deactivate');
140
 
141
+ // Add on submit to subscribe buttons.
142
  add_action('init', 'ce4wp_add_front_end_on_submit');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: Constant Contact
3
  Tags: email, marketing, newsletter, subscribe, contact form, constant contact, crm, automations, ecommerce, promotion, offers, retargeting
4
  Requires at least: 4.9
5
  Tested up to: 6.0.2
6
- Stable tag: 1.6.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
  Requires PHP: 7.2
@@ -102,6 +102,7 @@ Creative Mail by Constant Contact [Privacy Notice](https://www.endurance.com/pri
102
  6. Enhance your brand with LogoBuilder
103
 
104
  == Changelog ==
 
105
  * 1.6.0 - Security update, Bug fixes and Support to sync Address Fields for Contact Form 7
106
  * 1.5.4 - Migration to WordPress version 6.0.2 and Checkout mail templates update
107
  * 1.5.3 - README update
3
  Tags: email, marketing, newsletter, subscribe, contact form, constant contact, crm, automations, ecommerce, promotion, offers, retargeting
4
  Requires at least: 4.9
5
  Tested up to: 6.0.2
6
+ Stable tag: 1.6.1
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
  Requires PHP: 7.2
102
  6. Enhance your brand with LogoBuilder
103
 
104
  == Changelog ==
105
+ * 1.6.1 - Security update
106
  * 1.6.0 - Security update, Bug fixes and Support to sync Address Fields for Contact Form 7
107
  * 1.5.4 - Migration to WordPress version 6.0.2 and Checkout mail templates update
108
  * 1.5.3 - README update
src/Clients/CreativeMailClient.php CHANGED
@@ -7,105 +7,146 @@ use CreativeMail\Helpers\EnvironmentHelper;
7
  use CreativeMail\Helpers\OptionsHelper;
8
  use CreativeMail\Models\Campaign;
9
 
10
- class CreativeMailClient {
11
-
12
- private $instance_api_key;
13
- private $connected_account_id;
14
-
15
- public function __construct()
16
- {
17
- $this->instance_api_key = OptionsHelper::get_instance_api_key();
18
- $this->connected_account_id = OptionsHelper::get_connected_account_id();
19
- }
20
-
21
- public function get_account_status()
22
- {
23
- $response = wp_remote_get(
24
- EnvironmentHelper::get_app_gateway_url() . 'wordpress/v1.0/account/status',
25
- $this->get_default_headers()
26
- );
27
-
28
- if ( is_wp_error( $response ) ) {
29
- throw new CreativeMailException( 'Could not get account status' );
30
- }
31
-
32
- if ($response['response']['code'] === 401) {
33
- return null;
34
- }
35
-
36
- return json_decode( $response['body'], true );
37
- }
38
-
39
- public function get_most_recent_campaigns()
40
- {
41
- $response = wp_remote_get(
42
- EnvironmentHelper::get_app_gateway_url() . 'wordpress/v1.0/campaign-statistics/most-recent',
43
- $this->get_default_headers()
44
- );
45
-
46
- if ( is_wp_error( $response ) ) {
47
- throw new CreativeMailException( 'Could not get most recent campaigns' );
48
- }
49
-
50
- $campaigns_data = json_decode( $response['body'], true );
51
- return $this->parse_most_recent_campaigns( $campaigns_data );
52
- }
53
-
54
- public function get_all_custom_lists()
55
- {
56
- $response = wp_remote_get(
57
- EnvironmentHelper::get_app_gateway_url() . 'wordpress/v1.0/lists',
58
- $this->get_default_headers()
59
- );
60
-
61
- if ( is_wp_error( $response ) ) {
62
- throw new CreativeMailException( 'Could not get all custom lists' );
63
- }
64
-
65
- return json_decode( $response['body'], true );
66
- }
67
-
68
- private function parse_most_recent_campaigns( $campaigns_data )
69
- {
70
- $most_recent_campaigns = [];
71
-
72
- foreach ( $campaigns_data as $campaign_data ) {
73
- $campaign = new Campaign();
74
- $campaign->id = $campaign_data['external_id'];
75
- $campaign->name = $campaign_data['name'];
76
-
77
- if ( empty( $campaign_data['scheduled_on'] ) ) {
78
- $campaign->status = __( 'Draft', 'ce4wp' );
79
- $campaign->is_draft = true;
80
- } else if ( empty( $campaign_data['activity_summaries'] ) ) {
81
- $scheduled_on = date( "m/d/Y", strtotime( $campaign_data['scheduled_on'] ) );
82
- $campaign->status = sprintf( __( 'Scheduled on %s', 'ce4wp' ), $scheduled_on );
83
- $campaign->is_draft = false;
84
- } else {
85
- $sent_on = date( "m/d/Y", strtotime( $campaign_data['scheduled_on'] ) );
86
- $campaign->status = sprintf( __( 'Sent on %s', 'ce4wp' ), $sent_on );
87
- $campaign->is_draft = false;
88
-
89
- $activity_summary = $campaign_data['activity_summaries'][0];
90
- $number_of_opens = $activity_summary['stats']['em_opens'];
91
- $number_of_sends = $activity_summary['stats']['em_sends'];
92
- $campaign->open_rate = floor( ( $number_of_opens / $number_of_sends ) * 100 );
93
- }
94
-
95
- $most_recent_campaigns[] = $campaign;
96
- }
97
-
98
- return $most_recent_campaigns;
99
- }
100
-
101
- private function get_default_headers()
102
- {
103
- return [
104
- 'headers' => [
105
- 'x-api-key' => $this->instance_api_key,
106
- 'x-account-id' => $this->connected_account_id
107
- ],
108
- ];
109
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
 
111
  }
7
  use CreativeMail\Helpers\OptionsHelper;
8
  use CreativeMail\Models\Campaign;
9
 
10
+ final class CreativeMailClient {
11
+
12
+ /**
13
+ * Holds the Instance Api Key.
14
+ *
15
+ * @var string
16
+ */
17
+ private $instance_api_key;
18
+
19
+ /**
20
+ * Holds the Connected Account ID.
21
+ *
22
+ * @var int|null
23
+ */
24
+ private $connected_account_id;
25
+
26
+ public function __construct() {
27
+ $this->instance_api_key = OptionsHelper::get_instance_api_key();
28
+ $this->connected_account_id = OptionsHelper::get_connected_account_id();
29
+ }
30
+
31
+ /**
32
+ * Get the instance of the CreativeMailClient class.
33
+ *
34
+ * @return mixed|null
35
+ *
36
+ * @throws CreativeMailException
37
+ */
38
+ public function get_account_status() {
39
+ $response = wp_remote_get(
40
+ EnvironmentHelper::get_app_gateway_url('wordpress/v1.0/account/status'),
41
+ $this->get_default_headers()
42
+ );
43
+
44
+ if ( is_wp_error( $response ) ) {
45
+ throw new CreativeMailException( 'Could not get account status' );
46
+ }
47
+
48
+ if ( 401 === $response['response']['code'] ) {
49
+ return null;
50
+ }
51
+
52
+ return json_decode( $response['body'], true );
53
+ }
54
+
55
+ /**
56
+ * Get the most recent campaigns.
57
+ *
58
+ * @return array<Campaign>
59
+ *
60
+ * @throws CreativeMailException
61
+ */
62
+ public function get_most_recent_campaigns(): array {
63
+ $response = wp_remote_get(
64
+ EnvironmentHelper::get_app_gateway_url('wordpress/v1.0/campaign-statistics/most-recent'),
65
+ $this->get_default_headers()
66
+ );
67
+
68
+ if ( is_wp_error( $response ) ) {
69
+ throw new CreativeMailException( 'Could not get most recent campaigns' );
70
+ }
71
+
72
+ $campaigns_data = json_decode( $response['body'], true );
73
+
74
+ return $this->parse_most_recent_campaigns( $campaigns_data );
75
+ }
76
+
77
+ /**
78
+ * Get all the custom lists.
79
+ *
80
+ * @return mixed
81
+ *
82
+ * @throws CreativeMailException
83
+ */
84
+ public function get_all_custom_lists() {
85
+ $response = wp_remote_get(
86
+ EnvironmentHelper::get_app_gateway_url('wordpress/v1.0/lists'),
87
+ $this->get_default_headers()
88
+ );
89
+
90
+ if ( is_wp_error( $response ) ) {
91
+ throw new CreativeMailException( 'Could not get all custom lists' );
92
+ }
93
+
94
+ return json_decode( $response['body'], true );
95
+ }
96
+
97
+ /**
98
+ * Parse the most recent campaigns.
99
+ *
100
+ * @param ?string $campaigns_data The campaigns data.
101
+ *
102
+ * @return array<Campaign>
103
+ */
104
+ private function parse_most_recent_campaigns( $campaigns_data ): array {
105
+ $most_recent_campaigns = array();
106
+
107
+ foreach ( $campaigns_data as $campaign_data ) {
108
+ $campaign = new Campaign();
109
+ $campaign->id = $campaign_data['external_id'];
110
+ $campaign->name = $campaign_data['name'];
111
+
112
+ if ( empty( $campaign_data['scheduled_on'] ) ) {
113
+ $campaign->status = __( 'Draft', 'creative-mail-by-constant-contact' );
114
+ $campaign->is_draft = true;
115
+ } elseif ( empty( $campaign_data['activity_summaries'] ) ) {
116
+ $scheduled_on = gmdate( 'm/d/Y', strtotime( $campaign_data['scheduled_on'] ) );
117
+ // translators: %s is the date scheduled of the campaign.
118
+ $campaign->status = sprintf( __( 'Scheduled on %s', 'creative-mail-by-constant-contact' ), $scheduled_on );
119
+ $campaign->is_draft = false;
120
+ } else {
121
+ $sent_on = gmdate( 'm/d/Y', strtotime( $campaign_data['scheduled_on'] ) );
122
+ // translators: %s is the sent date of the campaign.
123
+ $campaign->status = sprintf( __( 'Sent on %s', 'creative-mail-by-constant-contact' ), $sent_on );
124
+ $campaign->is_draft = false;
125
+
126
+ $activity_summary = $campaign_data['activity_summaries'][0];
127
+ $number_of_opens = $activity_summary['stats']['em_opens'];
128
+ $number_of_sends = $activity_summary['stats']['em_sends'];
129
+ $campaign->open_rate = floor( ( $number_of_opens / $number_of_sends ) * 100 );
130
+ }
131
+
132
+ $most_recent_campaigns[] = $campaign;
133
+ }
134
+
135
+ return $most_recent_campaigns;
136
+ }
137
+
138
+ /**
139
+ * Get the default headers.
140
+ *
141
+ * @return array<array<string,string>>
142
+ */
143
+ private function get_default_headers(): array {
144
+ return array(
145
+ 'headers' => array(
146
+ 'x-api-key' => $this->instance_api_key,
147
+ 'x-account-id' => $this->connected_account_id,
148
+ ),
149
+ );
150
+ }
151
 
152
  }
src/Constants/EnvironmentNames.php CHANGED
@@ -2,9 +2,9 @@
2
 
3
  namespace CreativeMail\Constants;
4
 
5
- class EnvironmentNames
6
- {
7
- const DEVELOPMENT = 'DEVELOP';
8
- const QA = 'QA';
9
- const PRODUCTION = 'PRODUCTION';
10
  }
2
 
3
  namespace CreativeMail\Constants;
4
 
5
+ class EnvironmentNames {
6
+
7
+ const DEVELOPMENT = 'DEVELOP';
8
+ const QA = 'QA';
9
+ const PRODUCTION = 'PRODUCTION';
10
  }
src/CreativeMail.php CHANGED
@@ -1,6 +1,5 @@
1
  <?php
2
 
3
-
4
  namespace CreativeMail;
5
 
6
  use CreativeMail\Helpers\OptionsHelper;
@@ -14,119 +13,223 @@ use CreativeMail\Managers\InstanceManager;
14
  use CreativeMail\Managers\IntegrationManager;
15
  use CreativeMail\Modules\Contacts\Managers\ContactsSyncManager;
16
 
17
- class CreativeMail
18
- {
19
- private static $instance;
20
-
21
- private $admin_manager;
22
- private $api_manager;
23
- private $instance_manager;
24
- private $integration_manager;
25
- private $email_manager;
26
- private $database_manager;
27
- private $checkout_manager;
28
- private $contacts_sync_manager;
29
- private $form_manager;
30
-
31
- public function __construct()
32
- {
33
- if (current_user_can('administrator')) {
34
- $this->admin_manager = new AdminManager();
35
- }
36
-
37
- $this->database_manager = new DatabaseManager();
38
- $this->instance_manager = new InstanceManager();
39
- $this->api_manager = new ApiManager();
40
- $this->integration_manager = new IntegrationManager();
41
- $this->email_manager = new EmailManager();
42
- $this->checkout_manager = new CheckoutManager();
43
- $this->contacts_sync_manager = new ContactsSyncManager();
44
- $this->form_manager = new FormManager();
45
- }
46
-
47
- public function add_hooks()
48
- {
49
- if (!$this->is_active()) {
50
- return;
51
- }
52
-
53
- if ($this->admin_manager !== null) {
54
- $this->admin_manager->add_hooks();
55
- }
56
- if ($this->database_manager !== null) {
57
- $this->database_manager->add_hooks();
58
- }
59
-
60
- $this->api_manager->add_hooks();
61
- $this->integration_manager->add_hooks();
62
- $this->instance_manager->add_hooks();
63
- $this->email_manager->add_hooks();
64
- $this->form_manager->add_hooks();
65
-
66
- // check if abandoned cart email is managed by creative mail
67
- $enabled = $this->email_manager->is_email_managed('cart_abandoned_ce4wp');
68
- if ($enabled) {
69
- $this->checkout_manager->add_hooks();
70
- }
71
-
72
- if (!empty(OptionsHelper::get_instance_id())) {
73
- if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
74
- $this->checkout_manager->add_order_completed_wc_hooks();
75
- }
76
- }
77
- }
78
-
79
- public function get_database_manager()
80
- {
81
- return $this->database_manager;
82
- }
83
-
84
- public function get_integration_manager()
85
- {
86
- return $this->integration_manager;
87
- }
88
-
89
- public function get_instance_manager()
90
- {
91
- return $this->instance_manager;
92
- }
93
-
94
- public function get_api_manager()
95
- {
96
- return $this->api_manager;
97
- }
98
-
99
- public function get_email_manager()
100
- {
101
- return $this->email_manager;
102
- }
103
-
104
- public function get_admin_manager()
105
- {
106
- return $this->admin_manager;
107
- }
108
-
109
- public function get_contacts_sync_manager()
110
- {
111
- return $this->contacts_sync_manager;
112
- }
113
-
114
- public function get_form_manager()
115
- {
116
- return $this->form_manager;
117
- }
118
-
119
- public function is_active()
120
- {
121
- return in_array(plugin_basename(CE4WP_PLUGIN_FILE), apply_filters('active_plugins', get_option('active_plugins')));
122
- }
123
-
124
- public static function get_instance()
125
- {
126
- if (self::$instance === null) {
127
- self::$instance = new CreativeMail();
128
- }
129
-
130
- return self::$instance;
131
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  }
1
  <?php
2
 
 
3
  namespace CreativeMail;
4
 
5
  use CreativeMail\Helpers\OptionsHelper;
13
  use CreativeMail\Managers\IntegrationManager;
14
  use CreativeMail\Modules\Contacts\Managers\ContactsSyncManager;
15
 
16
+ final class CreativeMail {
17
+
18
+ /**
19
+ * Sets the instance of the CreativeMail class.
20
+ *
21
+ * @var CreativeMail
22
+ */
23
+ private static $instance;
24
+
25
+ /**
26
+ * Sets the instance of the AdminManager class.
27
+ *
28
+ * @var AdminManager
29
+ */
30
+ private $admin_manager;
31
+
32
+ /**
33
+ * Sets the instance of the ApiManager class.
34
+ *
35
+ * @var ApiManager
36
+ */
37
+ private $api_manager;
38
+
39
+ /**
40
+ * Sets the instance of the InstanceManager class.
41
+ *
42
+ * @var InstanceManager
43
+ */
44
+ private $instance_manager;
45
+
46
+ /**
47
+ * Sets the instance of the IntegrationManager class.
48
+ *
49
+ * @var IntegrationManager
50
+ */
51
+ private $integration_manager;
52
+
53
+ /**
54
+ * Sets the instance of the EmailManager class.
55
+ *
56
+ * @var EmailManager
57
+ */
58
+ private $email_manager;
59
+
60
+ /**
61
+ * Sets the instance of the DatabaseManager class.
62
+ *
63
+ * @var DatabaseManager
64
+ */
65
+ private $database_manager;
66
+
67
+ /**
68
+ * Sets the instance of the CheckoutManager class.
69
+ *
70
+ * @var CheckoutManager
71
+ */
72
+ private $checkout_manager;
73
+
74
+ /**
75
+ * Sets the instance of the ContactsSyncManager class.
76
+ *
77
+ * @var ContactsSyncManager
78
+ */
79
+ private $contacts_sync_manager;
80
+
81
+ /**
82
+ * Sets the instance of the FormManager class.
83
+ *
84
+ * @var FormManager
85
+ */
86
+ private $form_manager;
87
+
88
+ public function __construct() {
89
+ if ( current_user_can('administrator') ) {
90
+ $this->admin_manager = new AdminManager();
91
+ }
92
+
93
+ $this->database_manager = new DatabaseManager();
94
+ $this->instance_manager = new InstanceManager();
95
+ $this->api_manager = new ApiManager();
96
+ $this->integration_manager = new IntegrationManager();
97
+ $this->email_manager = new EmailManager();
98
+ $this->checkout_manager = new CheckoutManager();
99
+ $this->contacts_sync_manager = new ContactsSyncManager();
100
+ $this->form_manager = new FormManager();
101
+ }
102
+
103
+ /**
104
+ * Add all the hooks required by the plugin.
105
+ *
106
+ * @return void
107
+ */
108
+ public function add_hooks() {
109
+ if ( ! $this->is_active() ) {
110
+ return;
111
+ }
112
+
113
+ if ( null !== $this->admin_manager ) {
114
+ $this->admin_manager->add_hooks();
115
+ }
116
+ if ( null !== $this->database_manager ) {
117
+ $this->database_manager->add_hooks();
118
+ }
119
+ $this->api_manager->add_hooks();
120
+ $this->integration_manager->add_hooks();
121
+ $this->instance_manager->add_hooks();
122
+ $this->email_manager->add_hooks();
123
+ $this->form_manager->add_hooks();
124
+
125
+ // Check if abandoned cart email is managed by creative mail.
126
+ $enabled = $this->email_manager->is_email_managed('cart_abandoned_ce4wp');
127
+
128
+ if ( $enabled ) {
129
+ $this->checkout_manager->add_hooks();
130
+ }
131
+ if ( ! empty(OptionsHelper::get_instance_id()) ) {
132
+ if ( in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')), true) ) {
133
+ $this->checkout_manager->add_order_completed_wc_hooks();
134
+ }
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Returns the Database Manager instance.
140
+ *
141
+ * @return DatabaseManager
142
+ */
143
+ public function get_database_manager(): DatabaseManager {
144
+ return $this->database_manager;
145
+ }
146
+
147
+ /**
148
+ * Returns the Integration Manager instance.
149
+ *
150
+ * @return IntegrationManager
151
+ */
152
+ public function get_integration_manager(): IntegrationManager {
153
+ return $this->integration_manager;
154
+ }
155
+
156
+ /**
157
+ * Returns the Instance Manager instance.
158
+ *
159
+ * @return InstanceManager
160
+ */
161
+ public function get_instance_manager(): InstanceManager {
162
+ return $this->instance_manager;
163
+ }
164
+
165
+ /**
166
+ * Returns the Api Manager instance.
167
+ *
168
+ * @return ApiManager
169
+ */
170
+ public function get_api_manager(): ApiManager {
171
+ return $this->api_manager;
172
+ }
173
+
174
+ /**
175
+ * Returns the Email Manager instance.
176
+ *
177
+ * @return EmailManager
178
+ */
179
+ public function get_email_manager(): EmailManager {
180
+ return $this->email_manager;
181
+ }
182
+
183
+ /**
184
+ * Returns the Admin Manager instance.
185
+ *
186
+ * @return AdminManager
187
+ */
188
+ public function get_admin_manager(): AdminManager {
189
+ return $this->admin_manager;
190
+ }
191
+
192
+ /**
193
+ * Returns the Contacts Sync Manager instance.
194
+ *
195
+ * @return ContactsSyncManager
196
+ */
197
+ public function get_contacts_sync_manager(): ContactsSyncManager {
198
+ return $this->contacts_sync_manager;
199
+ }
200
+
201
+ /**
202
+ * Returns the Form Manager instance.
203
+ *
204
+ * @return FormManager
205
+ */
206
+ public function get_form_manager(): FormManager {
207
+ return $this->form_manager;
208
+ }
209
+
210
+ /**
211
+ * Checks if the plugin is active.
212
+ *
213
+ * @return bool
214
+ */
215
+ public function is_active(): bool {
216
+ return in_array(
217
+ plugin_basename(CE4WP_PLUGIN_FILE),
218
+ apply_filters('active_plugins', get_option('active_plugins')),
219
+ true
220
+ );
221
+ }
222
+
223
+ /**
224
+ * Returns the instance of the CreativeMail class.
225
+ *
226
+ * @return CreativeMail
227
+ */
228
+ public static function get_instance(): CreativeMail {
229
+ if ( null === self::$instance ) {
230
+ self::$instance = new CreativeMail();
231
+ }
232
+
233
+ return self::$instance;
234
+ }
235
  }
src/Exceptions/CreativeMailException.php CHANGED
@@ -4,11 +4,14 @@ namespace CreativeMail\Exceptions;
4
 
5
  use Exception;
6
 
7
- class CreativeMailException extends Exception {
8
-
9
- public function __construct ( $message )
10
- {
11
- parent::__construct( '[Creative Mail] ' . $message );
12
- }
13
 
 
 
 
 
 
 
 
 
14
  }
4
 
5
  use Exception;
6
 
7
+ final class CreativeMailException extends Exception {
 
 
 
 
 
8
 
9
+ /**
10
+ * Constructs the message of the CreativeMailException class.
11
+ *
12
+ * @param string $message Receives the message of the exception.
13
+ */
14
+ public function __construct( string $message ) {
15
+ parent::__construct( '[Creative Mail] ' . $message );
16
+ }
17
  }
src/Helpers/EncryptionHelper.php CHANGED
@@ -10,85 +10,81 @@ use Defuse\Crypto\Exception\EnvironmentIsBrokenException;
10
  use Defuse\Crypto\Key;
11
  use Exception;
12
 
13
- class EncryptionHelper
14
- {
15
 
16
- /**
17
- * Will get the previously used encryption key, or will generate a new key of no key is present.
18
- *
19
- * @return Key
20
- * @throws BadFormatException
21
- * @throws EnvironmentIsBrokenException
22
- */
23
- private static function get_encryption_key()
24
- {
25
- $key = get_option(CE4WP_ENCRYPTION_KEY_KEY, null);
26
- if ($key === null) {
27
- $key = Key::createNewRandomKey();
28
- update_option(CE4WP_ENCRYPTION_KEY_KEY, $key->saveToAsciiSafeString());
29
- }
30
- else {
31
- if (is_string($key)) {
32
- $key = Key::loadFromAsciiSafeString($key);
33
- }
34
- }
35
 
36
- return $key;
37
- }
38
 
39
- /**
40
- * Will update an existing option or create the option if it is not available.
41
- *
42
- * @param $option string The name of the option.
43
- * @param $value mixed The value that should be stored encrypted
44
- * @param $autoload bool Should this option be auto loaded.
45
- *
46
- * @return bool
47
- * @throws BadFormatException
48
- * @throws EnvironmentIsBrokenException
49
- */
50
- public static function update_option($option, $value, $autoload = null)
51
- {
52
- return update_option($option, Crypto::encrypt($value, self::get_encryption_key()), $autoload);
53
- }
54
 
55
- /**
56
- * Will store and encrypt the option.
57
- *
58
- * @param $option string The name of the option.
59
- * @param $value mixed The value that should be stored encrypted
60
- * @param $autoload bool Should this option be auto loaded.
61
- *
62
- * @throws BadFormatException
63
- * @throws EnvironmentIsBrokenException
64
- */
65
- public static function add_option($option, $value, $autoload = true)
66
- {
67
- add_option($option, Crypto::encrypt($value, self::get_encryption_key()), '', $autoload);
68
- }
69
 
70
- /**
71
- * Will load and decrypt the option.
72
- *
73
- * @param $option string The name of the option you want to load.
74
- * @param bool $default The fallback value that should be used when the option is not available.
75
- *
76
- * @return mixed
77
- */
78
- public static function get_option($option, $default = false)
79
- {
80
- $encrypted = get_option($option, $default);
81
- if ($encrypted === $default ) {
82
- return $default;
83
- } else {
84
- try {
85
- if (is_string($encrypted)) {
86
- return Crypto::decrypt($encrypted, self::get_encryption_key());
87
- }
88
- } catch ( Exception $e ) {
89
- RaygunManager::get_instance()->exception_handler($e);
90
- }
91
- }
92
- return $encrypted;
93
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  }
10
  use Defuse\Crypto\Key;
11
  use Exception;
12
 
13
+ final class EncryptionHelper {
 
14
 
15
+ /**
16
+ * Will get the previously used encryption key, or will generate a new key of no key is present.
17
+ *
18
+ * @return Key
19
+ * @throws BadFormatException
20
+ * @throws EnvironmentIsBrokenException
21
+ */
22
+ private static function get_encryption_key(): Key {
23
+ $key = get_option(CE4WP_ENCRYPTION_KEY_KEY, null);
 
 
 
 
 
 
 
 
 
 
24
 
25
+ if ( null === $key ) {
26
+ $key = Key::createNewRandomKey();
27
 
28
+ update_option(CE4WP_ENCRYPTION_KEY_KEY, $key->saveToAsciiSafeString());
29
+ } else {
30
+ $key = Key::loadFromAsciiSafeString($key);
31
+ }
 
 
 
 
 
 
 
 
 
 
 
32
 
33
+ return $key;
34
+ }
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
+ /**
37
+ * Will update an existing option or create the option if it is not available.
38
+ *
39
+ * @param string $option The name of the option.
40
+ * @param mixed $value The value that should be stored encrypted.
41
+ * @param bool $autoload Should this option be autoloaded.
42
+ *
43
+ * @return bool
44
+ * @throws BadFormatException
45
+ * @throws EnvironmentIsBrokenException
46
+ */
47
+ public static function update_option( string $option, $value, ?bool $autoload = null ): bool {
48
+ return update_option($option, Crypto::encrypt($value, self::get_encryption_key()), $autoload);
49
+ }
50
+
51
+ /**
52
+ * Will store and encrypt the option.
53
+ *
54
+ * @param string $option string The name of the option.
55
+ * @param mixed $value mixed The value that should be stored encrypted.
56
+ * @param bool $autoload bool Should this option be autoloaded.
57
+ *
58
+ * @throws BadFormatException
59
+ * @throws EnvironmentIsBrokenException
60
+ */
61
+ public static function add_option( string $option, $value, bool $autoload = true ): void {
62
+ add_option($option, Crypto::encrypt($value, self::get_encryption_key()), '', $autoload);
63
+ }
64
+
65
+ /**
66
+ * Will load and decrypt the option.
67
+ *
68
+ * @param string $option The name of the option you want to load.
69
+ * @param bool $default The fallback value that should be used when the option is not available.
70
+ *
71
+ * @return mixed
72
+ */
73
+ public static function get_option( string $option, bool $default = false ) {
74
+ $encrypted = get_option($option, $default);
75
+
76
+ if ( $encrypted === $default ) {
77
+ return $default;
78
+ } else {
79
+ try {
80
+ if ( is_string($encrypted) ) {
81
+ return Crypto::decrypt($encrypted, self::get_encryption_key());
82
+ }
83
+ } catch ( Exception $e ) {
84
+ RaygunManager::get_instance()->exception_handler($e);
85
+ }
86
+ }
87
+
88
+ return $encrypted;
89
+ }
90
  }
src/Helpers/EnvironmentHelper.php CHANGED
@@ -1,6 +1,5 @@
1
  <?php declare(strict_types = 1);
2
 
3
-
4
  namespace CreativeMail\Helpers;
5
 
6
  use CreativeMail\Constants\EnvironmentNames;
@@ -10,67 +9,65 @@ use CreativeMail\Constants\EnvironmentNames;
10
  *
11
  * @package CreativeMail\Helpers
12
  */
13
- class EnvironmentHelper
14
- {
15
- /**
16
- * Determines if the plugin is currently pointing towards a test environment.
17
- *
18
- * @returns bool
19
- */
20
- public static function is_test_environment()
21
- {
22
- return self::get_environment() !== EnvironmentNames::PRODUCTION;
23
- }
 
 
 
 
 
 
 
 
 
 
 
24
 
25
- /**
26
- * Gets the name of the environment this version of the plugin is build for.
27
- *
28
- * @return string
29
- */
30
- public static function get_environment()
31
- {
32
- $environment = CE4WP_ENVIRONMENT;
33
 
34
- if ($environment === "{ENV}") {
35
- $environment = EnvironmentNames::DEVELOPMENT;
36
- }
 
 
 
 
 
 
37
 
38
- return $environment;
39
- }
 
40
 
41
- /**
42
- * Gets the url of the app-gateway.
43
- *
44
- * @param string $path
45
- *
46
- * @return string
47
- */
48
- public static function get_app_gateway_url($path = '')
49
- {
50
- $url = CE4WP_APP_GATEWAY_URL;
51
 
52
- if ($url === '{GATEWAY_URL}') {
53
- $url = 'https://app-gateway.creativemail.com/';
54
- }
55
- if (!empty($path)) {
56
- $url .= $path;
57
- }
58
 
59
- return $url;
60
- }
 
 
 
 
 
61
 
62
- /**
63
- * Gets the url of the app.
64
- *
65
- * @return string
66
- */
67
- public static function get_app_url()
68
- {
69
- $url = CE4WP_APP_URL;
70
- if ($url === '{APP_URL}') {
71
- $url = 'https://app.creativemail.com/';
72
- }
73
 
74
- return $url;
75
- }
76
  }
1
  <?php declare(strict_types = 1);
2
 
 
3
  namespace CreativeMail\Helpers;
4
 
5
  use CreativeMail\Constants\EnvironmentNames;
9
  *
10
  * @package CreativeMail\Helpers
11
  */
12
+ final class EnvironmentHelper {
13
+
14
+ /**
15
+ * Determines if the plugin is currently pointing towards a test environment.
16
+ *
17
+ * @returns bool
18
+ */
19
+ public static function is_test_environment(): bool {
20
+ return self::get_environment() !== EnvironmentNames::PRODUCTION;
21
+ }
22
+
23
+ /**
24
+ * Gets the name of the environment this version of the plugin is build for.
25
+ *
26
+ * @return string
27
+ */
28
+ public static function get_environment(): string {
29
+ $environment = CE4WP_ENVIRONMENT;
30
+
31
+ if ( '{ENV}' === $environment ) {
32
+ $environment = EnvironmentNames::DEVELOPMENT;
33
+ }
34
 
35
+ return $environment;
36
+ }
 
 
 
 
 
 
37
 
38
+ /**
39
+ * Gets the url of the app-gateway.
40
+ *
41
+ * @param string $path Indicates the URL path that should be appended to the app-gateway URL.
42
+ *
43
+ * @return string
44
+ */
45
+ public static function get_app_gateway_url( string $path = '' ): string {
46
+ $url = CE4WP_APP_GATEWAY_URL;
47
 
48
+ if ( '{GATEWAY_URL}' === $url ) {
49
+ $url = 'https://app-gateway.creativemail.com/';
50
+ }
51
 
52
+ if ( ! empty($path) ) {
53
+ $url .= $path;
54
+ }
 
 
 
 
 
 
 
55
 
56
+ return $url;
57
+ }
 
 
 
 
58
 
59
+ /**
60
+ * Gets the url of the app.
61
+ *
62
+ * @return string
63
+ */
64
+ public static function get_app_url(): string {
65
+ $url = CE4WP_APP_URL;
66
 
67
+ if ( '{APP_URL}' === $url ) {
68
+ $url = 'https://app.creativemail.com/';
69
+ }
 
 
 
 
 
 
 
 
70
 
71
+ return $url;
72
+ }
73
  }
src/Helpers/GuidHelper.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
 
3
  namespace CreativeMail\Helpers;
4
 
@@ -7,13 +7,24 @@ namespace CreativeMail\Helpers;
7
  *
8
  * @package CreativeMail\Helpers
9
  */
10
- class GuidHelper
11
- {
12
-
13
- public static function generate_guid()
14
- {
15
-
16
- return sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535));
17
- }
18
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  }
1
+ <?php declare(strict_types = 1);
2
 
3
  namespace CreativeMail\Helpers;
4
 
7
  *
8
  * @package CreativeMail\Helpers
9
  */
10
+ final class GuidHelper {
 
 
 
 
 
 
 
11
 
12
+ /**
13
+ * Generates a GUID.
14
+ *
15
+ * @return string
16
+ */
17
+ public static function generate_guid(): string {
18
+ return sprintf(
19
+ '%04X%04X-%04X-%04X-%04X-%04X%04X%04X',
20
+ wp_rand(0, 65535),
21
+ wp_rand(0, 65535),
22
+ wp_rand(0, 65535),
23
+ wp_rand(16384, 20479),
24
+ wp_rand(32768, 49151),
25
+ wp_rand(0, 65535),
26
+ wp_rand(0, 65535),
27
+ wp_rand(0, 65535)
28
+ );
29
+ }
30
  }
src/Helpers/OptionsHelper.php CHANGED
@@ -13,399 +13,386 @@ use Defuse\Crypto\Exception\EnvironmentIsBrokenException;
13
  * @package CreativeMail\Helpers
14
  * @access private
15
  */
16
- class OptionsHelper
17
- {
18
- /**
19
- * Gets the generated unique id for this WP instance, or will generate a new unique id if none is present.
20
- *
21
- * @return string
22
- */
23
- public static function get_instance_uuid()
24
- {
25
- // Do we already have a UUID?
26
- $instanceUuid = get_option(CE4WP_INSTANCE_UUID_KEY, null);
27
-
28
- if ($instanceUuid === null) {
29
- // Just generate one and store it.
30
- $instanceUuid = uniqid();
31
- add_option(CE4WP_INSTANCE_UUID_KEY, $instanceUuid);
32
- } else {
33
- $instanceUuid = (string) $instanceUuid;
34
- }
35
-
36
- return $instanceUuid;
37
- }
38
-
39
- /**
40
- * Gets the generated handshake token that should be used during setup.
41
- *
42
- * @return string
43
- */
44
- public static function get_handshake_token()
45
- {
46
-
47
- // Do we already have a UUID?
48
- $token = get_option(CE4WP_INSTANCE_HANDSHAKE_TOKEN, null);
49
- $expiration = self::get_handshake_expiration();
50
- if ($token === null || $expiration === null || $expiration < time()) {
51
-
52
- // No token is known or it expired, generate a new one
53
- $token = GuidHelper::generate_guid();
54
- update_option(CE4WP_INSTANCE_HANDSHAKE_TOKEN, $token);
55
- update_option(CE4WP_INSTANCE_HANDSHAKE_EXPIRATION, time() + 3600);
56
- }
57
-
58
- return $token;
59
- }
60
-
61
- /**
62
- * Gets the expiration time associated with the generated handshake token.
63
- *
64
- * @return int|null
65
- */
66
- public static function get_handshake_expiration()
67
- {
68
- $handshake_expiration = get_option(CE4WP_INSTANCE_HANDSHAKE_EXPIRATION, null);
69
- return !empty($handshake_expiration) ? (int) $handshake_expiration : null;
70
- }
71
-
72
- /**
73
- * Gets the consumer API key that can be used to interact with the Creative Mail platform.
74
- *
75
- * @return string|null
76
- */
77
- public static function get_wc_consumer_key()
78
- {
79
- $wc_consumer_key = get_option(CE4WP_WC_API_CONSUMER_KEY, null);
80
- return is_string($wc_consumer_key) ? $wc_consumer_key : null;
81
- }
82
-
83
- /**
84
- * Sets the consumer key that can be used to interact with the Creative Mail platform.
85
- *
86
- * @param $value string
87
- *
88
- * @throws BadFormatException
89
- * @throws EnvironmentIsBrokenException
90
- */
91
- public static function set_wc_consumer_key($value)
92
- {
93
- EncryptionHelper::add_option(CE4WP_WC_API_CONSUMER_KEY, $value);
94
- }
95
-
96
- /**
97
- * Deletes the consumer key.
98
- *
99
- * @return bool
100
- */
101
- public static function delete_wc_consumer_key()
102
- {
103
- return delete_option(CE4WP_WC_API_CONSUMER_KEY);
104
- }
105
-
106
- /**
107
- * Gets the assigned api key id.
108
- *
109
- * @return int|null
110
- */
111
- public static function get_wc_api_key_id()
112
- {
113
- $wc_api_key_id = get_option(CE4WP_WC_API_KEY_ID, null);
114
- return !empty($wc_api_key_id) && is_numeric($wc_api_key_id) ? (int) $wc_api_key_id : null;
115
- }
116
-
117
- /**
118
- * Sets the assigned api key id that is generated when connecting this WP instance to the Creative Mail account.
119
- *
120
- * @param $value int
121
- */
122
- public static function set_wc_api_key_id($value)
123
- {
124
- add_option(CE4WP_WC_API_KEY_ID, $value);
125
- }
126
-
127
- /**
128
- * Deletes the api key id.
129
- *
130
- * @return bool
131
- */
132
- public static function delete_wc_api_key_id()
133
- {
134
- return delete_option(CE4WP_WC_API_KEY_ID);
135
- }
136
-
137
- /**
138
- * Gets the assigned instance id.
139
- *
140
- * @return int|null
141
- */
142
- public static function get_instance_id()
143
- {
144
- return get_option(CE4WP_INSTANCE_ID_KEY, null);
145
- }
146
-
147
- /**
148
- * Sets the assigned instance id that is generated when connecting this WP instance to the Creative Mail account.
149
- *
150
- * @param $value int
151
- */
152
- public static function set_instance_id($value)
153
- {
154
- add_option(CE4WP_INSTANCE_ID_KEY, $value);
155
- }
156
-
157
- /**
158
- * Gets the assigned checkbox text.
159
- *
160
- * @return string
161
- */
162
- public static function get_checkout_checkbox_text()
163
- {
164
- return get_option(CE4WP_CHECKOUT_CHECKBOX_TEXT, "Yes, I'm ok with you sending me additional newsletter and email content");
165
- }
166
-
167
- /**
168
- * Sets the assigned checkout checkbox text.
169
- *
170
- * @param $value string
171
- */
172
- public static function set_checkout_checkbox_text($value)
173
- {
174
- update_option(CE4WP_CHECKOUT_CHECKBOX_TEXT, $value);
175
- }
176
-
177
- /**
178
- * Sets the assigned checkout checkbox enabled.
179
- *
180
- * @param $value bool
181
- */
182
- public static function set_checkout_checkbox_enabled($value)
183
- {
184
- update_option(CE4WP_CHECKOUT_CHECKBOX_ENABLED, $value);
185
- }
186
-
187
- /**
188
- * Gets the assigned checkout checkbox enabled value
189
- *
190
- * @return int|bool
191
- */
192
- public static function get_checkout_checkbox_enabled()
193
- {
194
- return get_option(CE4WP_CHECKOUT_CHECKBOX_ENABLED, '1');
195
- }
196
-
197
- /**
198
- * Gets the id of the account that is connected to the combination of this WP unique id and Creative Mail account id.
199
- *
200
- * @return int|null
201
- */
202
- public static function get_connected_account_id()
203
- {
204
- return get_option(CE4WP_CONNECTED_ACCOUNT_ID, null);
205
- }
206
-
207
- /**
208
- * Sets the id of the account that is connected to the combination of this WP unique id and Creative Mail account id.
209
- *
210
- * @param $value int
211
- */
212
- public static function set_connected_account_id($value)
213
- {
214
- add_option(CE4WP_CONNECTED_ACCOUNT_ID, $value);
215
- }
216
-
217
- /**
218
- * Gets the API key that can be used to interact with the Creative Mail platform.
219
- *
220
- * @return string
221
- */
222
- public static function get_instance_api_key()
223
- {
224
- return EncryptionHelper::get_option(CE4WP_INSTANCE_API_KEY_KEY);
225
- }
226
-
227
- /**
228
- * Sets the API key that can be used to interact with the Creative Mail platform.
229
- *
230
- * @param $value string
231
- *
232
- * @throws BadFormatException
233
- * @throws EnvironmentIsBrokenException
234
- */
235
- public static function set_instance_api_key($value)
236
- {
237
- EncryptionHelper::add_option(CE4WP_INSTANCE_API_KEY_KEY, $value);
238
- }
239
-
240
- /**
241
- * Gets a string representing all the plugins that were activated for synchronization during the setup process.
242
- *
243
- * @return string|array
244
- */
245
- public static function get_activated_plugins()
246
- {
247
- return get_option(CE4WP_ACTIVATED_PLUGINS, array());
248
- }
249
-
250
- /**
251
- * Sets a string represeadminnting all the plugins that were activated for synchronization during the setup process.
252
- *
253
- * @param $plugins
254
- */
255
- public static function set_activated_plugins($plugins)
256
- {
257
- update_option(CE4WP_ACTIVATED_PLUGINS, $plugins);
258
- }
259
-
260
- /**
261
- * Get managed email notification array or string
262
- *
263
- * @return array
264
- */
265
- public static function get_managed_email_notifications()
266
- {
267
- global $wpdb;
268
- $rows = $wpdb->get_results($wpdb->prepare("SELECT option_name, option_value FROM $wpdb->options WHERE option_name like %s", CE4WP_MANAGED_EMAIL_NOTIFICATIONS . '%'));
269
- $result = array();
270
- foreach ( $rows as $row ) {
271
- $name = $row->option_name;
272
- if ($name === CE4WP_MANAGED_EMAIL_NOTIFICATIONS ) {
273
- // Convert old to new format.
274
- return self::convert_managed_email_notifications($row->option_value);
275
- }
276
-
277
- $item = new OptionsSchema();
278
- $item->name = str_replace(CE4WP_MANAGED_EMAIL_NOTIFICATIONS . '_', '', $name);
279
- $item->active = $row->option_value == 'true';
280
- array_push($result, $item);
281
- }
282
-
283
- return $result;
284
- }
285
-
286
- /**
287
- * One time converts the email notifications to the new format
288
- *
289
- * @return array
290
- */
291
- private static function convert_managed_email_notifications($items)
292
- {
293
- $items = maybe_unserialize($items);
294
- if (empty($items) || $items == null ) {
295
- return array();
296
- }
297
-
298
- $result = array();
299
- foreach ( $items as $item ) {
300
- if (property_exists($item, 'name') ) {
301
- OptionsHelper::set_managed_email_notification($item->name, $item->active == true ? 'true' : 'false');
302
- array_push($result, $item);
303
- }
304
- }
305
-
306
- delete_option(CE4WP_MANAGED_EMAIL_NOTIFICATIONS);
307
- return $result;
308
- }
309
-
310
- /**
311
- * Deletes all the email notifications options
312
- */
313
- private static function delete_managed_email_notifications()
314
- {
315
- $managed_notifications = self::get_managed_email_notifications();
316
- foreach ( $managed_notifications as $item ) {
317
- if (property_exists($item, 'name') ) {
318
- delete_option(CE4WP_MANAGED_EMAIL_NOTIFICATIONS . '_' . $item->name);
319
- }
320
- }
321
- }
322
-
323
- /**
324
- * Set managed email notification by name
325
- *
326
- * @param $data
327
- * @param $active
328
- */
329
- public static function set_managed_email_notification($name, $active)
330
- {
331
- update_option(CE4WP_MANAGED_EMAIL_NOTIFICATIONS . '_' . $name, $active);
332
- }
333
-
334
- /**
335
- * Gets an int value representing when the user did accept the terms on our consent screen.
336
- *
337
- * @return int|null
338
- */
339
- public static function get_consent_accept_date()
340
- {
341
- return get_option(CE4WP_ACCEPTED_CONSENT, null);
342
- }
343
-
344
- /**
345
- * Sets the current time value indicated the user accepted the terms on the consent screen.
346
- */
347
- public static function set_did_accept_consent()
348
- {
349
- update_option(CE4WP_ACCEPTED_CONSENT, time());
350
- }
351
-
352
- /**
353
- * Gets a string value representing who referred this customer
354
- *
355
- * @return string
356
- */
357
- public static function get_referred_by()
358
- {
359
- return get_option(CE4WP_REFERRED_BY, '');
360
- }
361
-
362
- /**
363
- * Gets the hide banner option for the given banner.
364
- *
365
- * @param $banner string
366
- *
367
- * @return bool
368
- */
369
- public static function get_hide_banner($banner)
370
- {
371
- return get_option(CE4WP_HIDE_BANNER . ':' . $banner, false);
372
- }
373
-
374
- /**
375
- * Sets the hide banner option for the given banner.
376
- *
377
- * @param $banner string
378
- * @param $hide bool
379
- */
380
- public static function set_hide_banner($banner, $hide = true)
381
- {
382
- update_option(CE4WP_HIDE_BANNER . ':' . $banner, $hide);
383
- }
384
-
385
- /**
386
- * Will clear all the registered options for this plugin.
387
- * Only the Unique Id won't be cleared so that we can restore the link when the plugin is reactivated.
388
- *
389
- * @param $clear_all bool When set to 'true' the instance UUID will be re-generated, this will cause the link between the plugin and the user account to break.
390
- */
391
- public static function clear_options($clear_all)
392
- {
393
- delete_option(CE4WP_INSTANCE_ID_KEY);
394
- delete_option(CE4WP_INSTANCE_API_KEY_KEY);
395
- delete_option(CE4WP_CONNECTED_ACCOUNT_ID);
396
- delete_option(CE4WP_ACTIVATED_PLUGINS);
397
- delete_option(CE4WP_ACCEPTED_CONSENT);
398
- delete_option(CE4WP_WC_API_KEY_ID);
399
- delete_option(CE4WP_WC_API_CONSUMER_KEY);
400
- delete_option(CE4WP_INSTANCE_HANDSHAKE_TOKEN);
401
- delete_option(CE4WP_INSTANCE_HANDSHAKE_EXPIRATION);
402
- delete_option(CE4WP_MANAGED_EMAIL_NOTIFICATIONS);
403
- delete_option(CE4WP_CHECKOUT_CHECKBOX_TEXT);
404
- self::delete_managed_email_notifications();
405
-
406
- if($clear_all === true) {
407
- delete_option(CE4WP_INSTANCE_UUID_KEY);
408
- delete_option(CE4WP_ENCRYPTION_KEY_KEY);
409
- }
410
- }
411
  }
13
  * @package CreativeMail\Helpers
14
  * @access private
15
  */
16
+ final class OptionsHelper {
17
+
18
+ /**
19
+ * Gets the generated unique id for this WP instance, or will generate a new unique id if none is present.
20
+ *
21
+ * @return string
22
+ */
23
+ public static function get_instance_uuid(): string {
24
+ // Do we already have a UUID?
25
+ $instanceUuid = get_option(CE4WP_INSTANCE_UUID_KEY, null);
26
+
27
+ if ( null === $instanceUuid ) {
28
+ // Just generate one and store it.
29
+ $instanceUuid = uniqid();
30
+ add_option(CE4WP_INSTANCE_UUID_KEY, $instanceUuid);
31
+ } else {
32
+ $instanceUuid = strval($instanceUuid);
33
+ }
34
+
35
+ return $instanceUuid;
36
+ }
37
+
38
+ /**
39
+ * Gets the generated handshake token that should be used during setup.
40
+ *
41
+ * @return string
42
+ */
43
+ public static function get_handshake_token(): string {
44
+ // Do we already have a UUID?
45
+ $token = get_option(CE4WP_INSTANCE_HANDSHAKE_TOKEN, null);
46
+ $expiration = self::get_handshake_expiration();
47
+
48
+ if ( null === $token || null === $expiration || $expiration < time() ) {
49
+ // No token is known, or it expired, generate a new one.
50
+ $token = GuidHelper::generate_guid();
51
+
52
+ update_option(CE4WP_INSTANCE_HANDSHAKE_TOKEN, $token);
53
+ update_option(CE4WP_INSTANCE_HANDSHAKE_EXPIRATION, time() + 3600);
54
+ }
55
+
56
+ return $token;
57
+ }
58
+
59
+ /**
60
+ * Gets the expiration time associated with the generated handshake token.
61
+ *
62
+ * @return int|null
63
+ */
64
+ public static function get_handshake_expiration(): ?int {
65
+ $handshake_expiration = get_option(CE4WP_INSTANCE_HANDSHAKE_EXPIRATION, null);
66
+
67
+ return ! empty($handshake_expiration) ? intval($handshake_expiration) : null;
68
+ }
69
+
70
+ /**
71
+ * Gets the consumer API key that can be used to interact with the Creative Mail platform.
72
+ *
73
+ * @return string|null
74
+ */
75
+ public static function get_wc_consumer_key(): ?string {
76
+ $wc_consumer_key = get_option(CE4WP_WC_API_CONSUMER_KEY, null);
77
+
78
+ return is_string($wc_consumer_key) ? $wc_consumer_key : null;
79
+ }
80
+
81
+ /**
82
+ * Sets the consumer key that can be used to interact with the Creative Mail platform.
83
+ *
84
+ * @param string $value The consumer key that should be stored.
85
+ *
86
+ * @throws BadFormatException
87
+ * @throws EnvironmentIsBrokenException
88
+ */
89
+ public static function set_wc_consumer_key( string $value ): void {
90
+ EncryptionHelper::add_option(CE4WP_WC_API_CONSUMER_KEY, $value);
91
+ }
92
+
93
+ /**
94
+ * Deletes the consumer key.
95
+ *
96
+ * @return bool
97
+ */
98
+ public static function delete_wc_consumer_key(): bool {
99
+ return delete_option(CE4WP_WC_API_CONSUMER_KEY);
100
+ }
101
+
102
+ /**
103
+ * Gets the assigned api key id.
104
+ *
105
+ * @return int|null
106
+ */
107
+ public static function get_wc_api_key_id(): ?int {
108
+ $wc_api_key_id = get_option(CE4WP_WC_API_KEY_ID, null);
109
+
110
+ return ! empty($wc_api_key_id) && is_numeric($wc_api_key_id) ? (int) $wc_api_key_id : null;
111
+ }
112
+
113
+ /**
114
+ * Sets the assigned api key id that is generated when connecting this WP instance to the Creative Mail account.
115
+ *
116
+ * @param int $value The api key id that should be stored.
117
+ */
118
+ public static function set_wc_api_key_id( int $value ): void {
119
+ add_option(CE4WP_WC_API_KEY_ID, $value);
120
+ }
121
+
122
+ /**
123
+ * Deletes the api key id.
124
+ *
125
+ * @return bool
126
+ */
127
+ public static function delete_wc_api_key_id(): bool {
128
+ return delete_option(CE4WP_WC_API_KEY_ID);
129
+ }
130
+
131
+ /**
132
+ * Gets the assigned instance id.
133
+ *
134
+ * @return int|null
135
+ */
136
+ public static function get_instance_id(): ?int {
137
+ return get_option(CE4WP_INSTANCE_ID_KEY, null);
138
+ }
139
+
140
+ /**
141
+ * Sets the assigned instance id that is generated when connecting this WP instance to the Creative Mail account.
142
+ *
143
+ * @param int $value The instance id that should be stored.
144
+ */
145
+ public static function set_instance_id( int $value ): void {
146
+ add_option(CE4WP_INSTANCE_ID_KEY, $value);
147
+ }
148
+
149
+ /**
150
+ * Gets the assigned checkbox text.
151
+ *
152
+ * @return string
153
+ */
154
+ public static function get_checkout_checkbox_text(): string {
155
+ return get_option(CE4WP_CHECKOUT_CHECKBOX_TEXT, "Yes, I'm ok with you sending me additional newsletter and email content");
156
+ }
157
+
158
+ /**
159
+ * Sets the assigned checkout checkbox text.
160
+ *
161
+ * @param string $value The checkout checkbox text that should be stored.
162
+ */
163
+ public static function set_checkout_checkbox_text( string $value ): void {
164
+ update_option(CE4WP_CHECKOUT_CHECKBOX_TEXT, $value);
165
+ }
166
+
167
+ /**
168
+ * Sets the assigned checkout checkbox enabled.
169
+ *
170
+ * @param string $value The checkout checkbox enabled that should be stored.
171
+ */
172
+ public static function set_checkout_checkbox_enabled( string $value ): void {
173
+ if ( '0' != $value && '1' != $value ) {
174
+ return;
175
+ }
176
+
177
+ update_option(CE4WP_CHECKOUT_CHECKBOX_ENABLED, $value);
178
+ }
179
+
180
+ /**
181
+ * Gets the assigned checkout checkbox enabled value
182
+ *
183
+ * @return int|bool
184
+ */
185
+ public static function get_checkout_checkbox_enabled() {
186
+ return get_option(CE4WP_CHECKOUT_CHECKBOX_ENABLED, '1');
187
+ }
188
+
189
+ /**
190
+ * Gets the id of the account that is connected to the combination of this WP unique id and Creative Mail account id.
191
+ *
192
+ * @return int|null
193
+ */
194
+ public static function get_connected_account_id(): ?int {
195
+ return get_option(CE4WP_CONNECTED_ACCOUNT_ID, null);
196
+ }
197
+
198
+ /**
199
+ * Sets the id of the account that is connected to the combination of this WP unique id and Creative Mail account id.
200
+ *
201
+ * @param int $value The account id that should be stored.
202
+ */
203
+ public static function set_connected_account_id( int $value ): void {
204
+ add_option(CE4WP_CONNECTED_ACCOUNT_ID, $value);
205
+ }
206
+
207
+ /**
208
+ * Gets the API key that can be used to interact with the Creative Mail platform.
209
+ *
210
+ * @return string
211
+ */
212
+ public static function get_instance_api_key(): string {
213
+ return EncryptionHelper::get_option(CE4WP_INSTANCE_API_KEY_KEY);
214
+ }
215
+
216
+ /**
217
+ * Sets the API key that can be used to interact with the Creative Mail platform.
218
+ *
219
+ * @param string $value The API key that should be stored.
220
+ *
221
+ * @throws BadFormatException
222
+ * @throws EnvironmentIsBrokenException
223
+ */
224
+ public static function set_instance_api_key( string $value ): void {
225
+ EncryptionHelper::add_option(CE4WP_INSTANCE_API_KEY_KEY, $value);
226
+ }
227
+
228
+ /**
229
+ * Gets a string representing all the plugins that were activated for synchronization during the setup process.
230
+ *
231
+ * @return string|array
232
+ */
233
+ public static function get_activated_plugins() {
234
+ return get_option(CE4WP_ACTIVATED_PLUGINS, array());
235
+ }
236
+
237
+ /**
238
+ * Sets a string representing all the plugins that were activated for synchronization during the setup process.
239
+ *
240
+ * @param mixed $plugins The plugins that should be stored.
241
+ */
242
+ public static function set_activated_plugins( $plugins ): void {
243
+ update_option(CE4WP_ACTIVATED_PLUGINS, $plugins);
244
+ }
245
+
246
+ /**
247
+ * Get managed email notification array or string
248
+ *
249
+ * @return array<OptionsSchema>
250
+ */
251
+ public static function get_managed_email_notifications(): array {
252
+ global $wpdb;
253
+
254
+ $rows = $wpdb->get_results($wpdb->prepare("SELECT option_name, option_value FROM $wpdb->options WHERE option_name like %s", CE4WP_MANAGED_EMAIL_NOTIFICATIONS . '%'));
255
+ $result = array();
256
+
257
+ foreach ( $rows as $row ) {
258
+ $name = $row->option_name;
259
+ if ( CE4WP_MANAGED_EMAIL_NOTIFICATIONS === $name ) {
260
+ // Convert old to new format.
261
+ return self::convert_managed_email_notifications($row->option_value);
262
+ }
263
+
264
+ $item = new OptionsSchema();
265
+ $item->name = str_replace(CE4WP_MANAGED_EMAIL_NOTIFICATIONS . '_', '', $name);
266
+ $item->active = 'true' == $row->option_value;
267
+
268
+ $result[] = $item;
269
+ }
270
+
271
+ return $result;
272
+ }
273
+
274
+ /**
275
+ * One time converts the email notifications to the new format.
276
+ *
277
+ * @param mixed $items The items that should be converted.
278
+ *
279
+ * @return array
280
+ */
281
+ private static function convert_managed_email_notifications( $items ): array {
282
+ $items = maybe_unserialize($items);
283
+
284
+ if ( empty($items) ) {
285
+ return array();
286
+ }
287
+
288
+ $result = array();
289
+
290
+ foreach ( $items as $item ) {
291
+ if ( property_exists($item, 'name') ) {
292
+ self::set_managed_email_notification($item->name, $item->active ? 'true' : 'false');
293
+ array_push($result, $item);
294
+ }
295
+ }
296
+
297
+ delete_option(CE4WP_MANAGED_EMAIL_NOTIFICATIONS);
298
+
299
+ return $result;
300
+ }
301
+
302
+ /**
303
+ * Deletes all the email notifications options
304
+ */
305
+ private static function delete_managed_email_notifications(): void {
306
+ $managed_notifications = self::get_managed_email_notifications();
307
+
308
+ foreach ( $managed_notifications as $item ) {
309
+ if ( property_exists($item, 'name') ) {
310
+ delete_option(CE4WP_MANAGED_EMAIL_NOTIFICATIONS . '_' . $item->name);
311
+ }
312
+ }
313
+ }
314
+
315
+ /**
316
+ * Set managed email notification by name
317
+ *
318
+ * @param string $name The name of the email notification.
319
+ * @param bool $active The active state of the email notification.
320
+ */
321
+ public static function set_managed_email_notification( string $name, bool $active ): void {
322
+ $is_active = var_export($active, true);
323
+ update_option(CE4WP_MANAGED_EMAIL_NOTIFICATIONS . '_' . $name, $is_active);
324
+ }
325
+
326
+ /**
327
+ * Gets an int value representing when the user did accept the terms on our consent screen.
328
+ *
329
+ * @return int|null
330
+ */
331
+ public static function get_consent_accept_date(): ?int {
332
+ return get_option(CE4WP_ACCEPTED_CONSENT, null);
333
+ }
334
+
335
+ /**
336
+ * Sets the current time value indicated the user accepted the terms on the consent screen.
337
+ */
338
+ public static function set_did_accept_consent(): void {
339
+ update_option(CE4WP_ACCEPTED_CONSENT, time());
340
+ }
341
+
342
+ /**
343
+ * Gets a string value representing who referred this customer
344
+ *
345
+ * @return string
346
+ */
347
+ public static function get_referred_by(): string {
348
+ return get_option(CE4WP_REFERRED_BY, '');
349
+ }
350
+
351
+ /**
352
+ * Gets the hide banner option for the given banner.
353
+ *
354
+ * @param string $banner The banner to get the hide option for.
355
+ *
356
+ * @return bool
357
+ */
358
+ public static function get_hide_banner( string $banner ): bool {
359
+ return get_option(CE4WP_HIDE_BANNER . ':' . $banner, false);
360
+ }
361
+
362
+ /**
363
+ * Sets the hide banner option for the given banner.
364
+ *
365
+ * @param string $banner The banner to hide.
366
+ * @param bool $hide Whether the banner should be hidden or not.
367
+ */
368
+ public static function set_hide_banner( string $banner, bool $hide = true ): void {
369
+ $is_hidden = var_export($hide, true);
370
+ update_option(CE4WP_HIDE_BANNER . ':' . $banner, $is_hidden);
371
+ }
372
+
373
+ /**
374
+ * Will clear all the registered options for this plugin.
375
+ * Only the Unique Id won't be cleared so that we can restore the link when the plugin is reactivated.
376
+ *
377
+ * @param bool $clear_all When set to 'true' the instance UUID will be re-generated, this will cause the link between the plugin and the user account to break.
378
+ */
379
+ public static function clear_options( bool $clear_all ): void {
380
+ delete_option(CE4WP_INSTANCE_ID_KEY);
381
+ delete_option(CE4WP_INSTANCE_API_KEY_KEY);
382
+ delete_option(CE4WP_CONNECTED_ACCOUNT_ID);
383
+ delete_option(CE4WP_ACTIVATED_PLUGINS);
384
+ delete_option(CE4WP_ACCEPTED_CONSENT);
385
+ delete_option(CE4WP_WC_API_KEY_ID);
386
+ delete_option(CE4WP_WC_API_CONSUMER_KEY);
387
+ delete_option(CE4WP_INSTANCE_HANDSHAKE_TOKEN);
388
+ delete_option(CE4WP_INSTANCE_HANDSHAKE_EXPIRATION);
389
+ delete_option(CE4WP_MANAGED_EMAIL_NOTIFICATIONS);
390
+ delete_option(CE4WP_CHECKOUT_CHECKBOX_TEXT);
391
+ self::delete_managed_email_notifications();
392
+
393
+ if ( true === $clear_all ) {
394
+ delete_option(CE4WP_INSTANCE_UUID_KEY);
395
+ delete_option(CE4WP_ENCRYPTION_KEY_KEY);
396
+ }
397
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
398
  }
src/Helpers/SsoHelper.php CHANGED
@@ -10,65 +10,74 @@ use Exception;
10
  *
11
  * @package CreativeMail\Helpers
12
  */
13
- class SsoHelper
14
- {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
- /**
17
- * Will request a one-time use link that can be used to initiate a single sign on into the Creative Mail product.
18
- *
19
- * @param $instanceId int
20
- * @param $apiKey string
21
- * @param $connectedAccountId int
22
- * @param $linkReference string|null
23
- * @param $linkParameters array|null
24
- *
25
- * @return string|null Returns the sso link or null if the link could not be generated.
26
- *
27
- * @throws Exception When one of the required arguments is not present.
28
- */
29
- public static function generate_sso_link($instanceId, $apiKey, $connectedAccountId, $linkReference = null, $linkParameters = null)
30
- {
31
 
32
- if(!isset($instanceId)) { throw new Exception("Please provide a valid siteId");
33
- }
34
- if(!isset($apiKey)) { throw new Exception("Please provide a valid apiKey");
35
- }
36
- if(!isset($connectedAccountId)) { throw new Exception("Please provide a valid connectedAccountId");
37
- }
38
 
39
- // Build the request
40
- $arguments = array(
41
- 'method' => 'POST',
42
- 'headers' => array(
43
- 'x-api-key' => $apiKey,
44
- 'x-account-id' => $connectedAccountId,
45
- 'content-type' => 'application/json'
46
- ),
47
- 'body' => wp_json_encode(
48
- array(
49
- 'instance_url' => get_bloginfo('wpurl'),
50
- 'plugin_version' => CE4WP_PLUGIN_VERSION,
51
- 'word_press_version' => get_bloginfo('version'),
52
- 'link_reference' => $linkReference,
53
- 'link_parameters' => $linkParameters
54
- )
55
- )
56
- );
57
 
58
- $response = wp_remote_post(EnvironmentHelper::get_app_gateway_url() . 'wordpress/v1.0/account/sso', $arguments);
59
- if (is_wp_error($response)) {
60
- return null;
61
- }
62
 
63
- $properties = json_decode($response["body"], true);
 
 
64
 
65
- if ($properties === null) {
66
- return null;
67
- }
68
- if(array_key_exists('login_url', $properties)) {
69
- return $properties['login_url'];
70
- }
71
 
72
- return null;
73
- }
 
 
 
 
 
 
 
 
74
  }
10
  *
11
  * @package CreativeMail\Helpers
12
  */
13
+ final class SsoHelper {
14
+ /**
15
+ * Will request a one-time use link that can be used to initiate a single sign on into the Creative Mail product.
16
+ *
17
+ * @param int $instanceId The instance id of the Creative Mail product.
18
+ * @param string $apiKey The api key of the Creative Mail product.
19
+ * @param int $connectedAccountId The connected account id of the Creative Mail product.
20
+ * @param string|null $linkReference The link reference of the Creative Mail product.
21
+ * @param array|null $linkParameters The link parameters of the Creative Mail product.
22
+ *
23
+ * @return string|null Returns the sso link or null if the link could not be generated.
24
+ *
25
+ * @throws Exception When one of the required arguments is not present.
26
+ */
27
+ public static function generate_sso_link(
28
+ int $instanceId,
29
+ string $apiKey,
30
+ int $connectedAccountId,
31
+ ?string $linkReference = null,
32
+ ?array $linkParameters = null
33
+ ): ?string {
34
+ if ( ! isset( $instanceId ) ) {
35
+ throw new Exception('Please provide a valid siteId');
36
+ }
37
 
38
+ if ( ! isset( $apiKey ) ) {
39
+ throw new Exception('Please provide a valid apiKey');
40
+ }
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
+ if ( ! isset( $connectedAccountId ) ) {
43
+ throw new Exception('Please provide a valid connectedAccountId');
44
+ }
 
 
 
45
 
46
+ // Build the request.
47
+ $arguments = array(
48
+ 'method' => 'POST',
49
+ 'headers' => array(
50
+ 'x-api-key' => $apiKey,
51
+ 'x-account-id' => $connectedAccountId,
52
+ 'content-type' => 'application/json',
53
+ ),
54
+ 'body' => wp_json_encode(
55
+ array(
56
+ 'instance_url' => get_bloginfo('wpurl'),
57
+ 'plugin_version' => CE4WP_PLUGIN_VERSION,
58
+ 'word_press_version' => get_bloginfo('version'),
59
+ 'link_reference' => $linkReference,
60
+ 'link_parameters' => $linkParameters,
61
+ )
62
+ ),
63
+ );
64
 
65
+ $response = wp_remote_post(EnvironmentHelper::get_app_gateway_url('wordpress/v1.0/account/sso'), $arguments);
 
 
 
66
 
67
+ if ( is_wp_error($response) ) {
68
+ return null;
69
+ }
70
 
71
+ $properties = json_decode($response['body'], true);
 
 
 
 
 
72
 
73
+ if ( null === $properties ) {
74
+ return null;
75
+ }
76
+
77
+ if ( array_key_exists('login_url', $properties) ) {
78
+ return $properties['login_url'];
79
+ }
80
+
81
+ return null;
82
+ }
83
  }
src/Integrations/Integration.php CHANGED
@@ -11,118 +11,165 @@ use CreativeMail\Modules\Contacts\Handlers\BaseContactFormPluginHandler;
11
  *
12
  * @package CreativeMail\Integrations
13
  */
14
- class Integration
15
- {
16
- private $name;
17
- private $class;
18
- private $integrationHandler;
19
- private $slug;
20
- private $hide_from_suggestions;
21
- private $url;
22
- private $has_multiple_plugins;
23
- private $hide_from_active_list;
24
-
25
- /**
26
- * Integration constructor.
27
- *
28
- * @param $slug string The slug that you want to use for this integration.
29
- * @param $name string The display name of the plugin
30
- * @param $class string The path the plugin class that should be used to check if the plugin required for this integration is installed.
31
- * @param $integration_handler object The class that should be instantiated when this integration gets activated.
32
- * @param $hide_from_suggestions boolean If you want to hide this plugin from the suggestion list, set this to true
33
- * @param $url string The link to the plugin store, default will set it based on the slug
34
- * @param $has_multiple_plugins boolean If true the plugin will search using the basename (some plugins have different directories depending on license)
35
- * @param $hide_from_active_list boolean If you want to hide this plugin from the active plugins list, set this to true
36
- */
37
- public function __construct($slug, $name, $class, $integration_handler, $hide_from_suggestions, $url = null, $has_multiple_plugins = false, $hide_from_active_list = false)
38
- {
39
- $this->slug = $slug;
40
- $this->name = $name;
41
- $this->class = $class;
42
- $this->integrationHandler = $integration_handler;
43
- $this->hide_from_suggestions = $hide_from_suggestions;
44
- $this->url = is_null($url) ? admin_url("plugin-install.php?tab=plugin-information&plugin=$slug&TB_iframe=true&width=772&height=1144") : $url;
45
- $this->has_multiple_plugins = $has_multiple_plugins;
46
- $this->hide_from_active_list = $hide_from_active_list;
47
- }
48
-
49
- /**
50
- * Gets the slug assigned to this integration.
51
- *
52
- * @return string
53
- */
54
- public function get_slug()
55
- {
56
- return $this->slug;
57
- }
58
-
59
- /**
60
- * Gets the display name assigned to this integration.
61
- *
62
- * @return string
63
- */
64
- public function get_name()
65
- {
66
- return $this->name;
67
- }
68
-
69
- /**
70
- * Gets the path to the main class of the plugin that is required for this integration.
71
- *
72
- * @return string
73
- */
74
- public function get_class()
75
- {
76
- return $this->class;
77
- }
78
-
79
- /**
80
- * Gets the name of the class that should be instantiated when activating this integration.
81
- *
82
- * @return object
83
- */
84
- public function get_integration_handler()
85
- {
86
- return $this->integrationHandler;
87
- }
88
-
89
- /**
90
- * Gets if this integration should be hidden from the suggestion list
91
- *
92
- * @return bool
93
- */
94
- public function is_hidden_from_suggestions()
95
- {
96
- return $this->hide_from_suggestions;
97
- }
98
-
99
- /**
100
- * Gets if this integration should be hidden from the active plugins list
101
- *
102
- * @return bool
103
- */
104
- public function is_hidden_from_active_list()
105
- {
106
- return $this->hide_from_active_list;
107
- }
108
-
109
- /**
110
- * Gets the market url of the plugin
111
- *
112
- * @return bool
113
- */
114
- public function get_url()
115
- {
116
- return $this->url;
117
- }
118
-
119
- /**
120
- * Use basename if integration has multiple plugins with different directories
121
- *
122
- * @return bool
123
- */
124
- public function use_basename()
125
- {
126
- return $this->has_multiple_plugins;
127
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  }
11
  *
12
  * @package CreativeMail\Integrations
13
  */
14
+ final class Integration {
15
+
16
+ /**
17
+ * The display name of the plugin.
18
+ *
19
+ * @var string
20
+ */
21
+ private $name;
22
+
23
+ /**
24
+ * The path the plugin class that should be used to check if the plugin required for this integration is installed.
25
+ *
26
+ * @var string
27
+ */
28
+ private $class;
29
+
30
+ /**
31
+ * The class that should be instantiated when this integration gets activated.
32
+ *
33
+ * @var string
34
+ */
35
+ private $integrationHandler;
36
+
37
+ /**
38
+ * The slug that you want to use for this integration.
39
+ *
40
+ * @var string
41
+ */
42
+ private $slug;
43
+
44
+ /**
45
+ * If you want to hide this plugin from the suggestion list, set this to true.
46
+ *
47
+ * @var bool
48
+ */
49
+ private $hide_from_suggestions;
50
+
51
+ /**
52
+ * The link to the plugin store, default will set it based on the slug.
53
+ *
54
+ * @var string
55
+ */
56
+ private $url;
57
+
58
+ /**
59
+ * If true the plugin will search using the basename (some plugins have different directories depending on license).
60
+ *
61
+ * @var bool
62
+ */
63
+ private $has_multiple_plugins;
64
+
65
+ /**
66
+ * If you want to hide this plugin from the active plugins list, set this to true.
67
+ *
68
+ * @var bool
69
+ */
70
+ private $hide_from_active_list;
71
+
72
+ /**
73
+ * Integration constructor.
74
+ *
75
+ * @param string $slug The slug that you want to use for this integration.
76
+ * @param string $name The display name of the plugin.
77
+ * @param string $class The path the plugin class that should be used to check if the plugin required for this integration is installed.
78
+ * @param string $integration_handler The class that should be instantiated when this integration gets activated.
79
+ * @param bool $hide_from_suggestions If you want to hide this plugin from the suggestion list, set this to true.
80
+ * @param string|null $url The link to the plugin store, default will set it based on the slug.
81
+ * @param bool $has_multiple_plugins If true the plugin will search using the basename (some plugins have different directories depending on license).
82
+ * @param bool $hide_from_active_list If you want to hide this plugin from the active plugins list, set this to true.
83
+ */
84
+ public function __construct(
85
+ string $slug,
86
+ string $name,
87
+ string $class,
88
+ string $integration_handler,
89
+ bool $hide_from_suggestions,
90
+ ?string $url = null,
91
+ bool $has_multiple_plugins = false,
92
+ bool $hide_from_active_list = false
93
+ ) {
94
+ $this->slug = $slug;
95
+ $this->name = $name;
96
+ $this->class = $class;
97
+ $this->integrationHandler = $integration_handler;
98
+ $this->hide_from_suggestions = $hide_from_suggestions;
99
+ $this->url = is_null($url) ? admin_url("plugin-install.php?tab=plugin-information&plugin=$slug&TB_iframe=true&width=772&height=1144") : $url;
100
+ $this->has_multiple_plugins = $has_multiple_plugins;
101
+ $this->hide_from_active_list = $hide_from_active_list;
102
+ }
103
+
104
+ /**
105
+ * Gets the slug assigned to this integration.
106
+ *
107
+ * @return string
108
+ */
109
+ public function get_slug(): string {
110
+ return $this->slug;
111
+ }
112
+
113
+ /**
114
+ * Gets the display name assigned to this integration.
115
+ *
116
+ * @return string
117
+ */
118
+ public function get_name(): string {
119
+ return $this->name;
120
+ }
121
+
122
+ /**
123
+ * Gets the path to the main class of the plugin that is required for this integration.
124
+ *
125
+ * @return string
126
+ */
127
+ public function get_class(): string {
128
+ return $this->class;
129
+ }
130
+
131
+ /**
132
+ * Gets the name of the class that should be instantiated when activating this integration.
133
+ *
134
+ * @return string
135
+ */
136
+ public function get_integration_handler(): string {
137
+ return $this->integrationHandler;
138
+ }
139
+
140
+ /**
141
+ * Gets if this integration should be hidden from the suggestion list
142
+ *
143
+ * @return bool
144
+ */
145
+ public function is_hidden_from_suggestions(): bool {
146
+ return $this->hide_from_suggestions;
147
+ }
148
+
149
+ /**
150
+ * Gets if this integration should be hidden from the active plugins list
151
+ *
152
+ * @return bool
153
+ */
154
+ public function is_hidden_from_active_list(): bool {
155
+ return $this->hide_from_active_list;
156
+ }
157
+
158
+ /**
159
+ * Gets the market url of the plugin
160
+ *
161
+ * @return string
162
+ */
163
+ public function get_url(): string {
164
+ return $this->url;
165
+ }
166
+
167
+ /**
168
+ * Use basename if integration has multiple plugins with different directories
169
+ *
170
+ * @return bool
171
+ */
172
+ public function use_basename(): bool {
173
+ return $this->has_multiple_plugins;
174
+ }
175
  }
src/Managers/AdminManager.php CHANGED
@@ -16,211 +16,307 @@ use Exception;
16
  *
17
  * @ignore
18
  */
19
- class AdminManager
20
- {
21
-
22
- protected $instance_name;
23
- protected $instance_uuid;
24
- protected $instance_handshake_token;
25
- protected $instance_id;
26
- protected $instance_url;
27
- protected $instance_callback_url;
28
- protected $dashboard_url;
29
-
30
- const ADMIN_NOTICES_HOOK = 'admin_notices';
31
- const ADMIN_INIT_HOOK = 'admin_init';
32
- const ADMIN_MENU_HOOK = 'admin_menu';
33
- const ADMIN_ENQUEUE_SCRIPTS_HOOK = 'admin_enqueue_scripts';
34
-
35
- const ADMIN_AJAX_NONCE = 'ajax-nonce';
36
- const ADMIN_NONCE = 'nonce';
37
-
38
- const ADMIN_WOOCOMMERCE = 'woocommerce';
39
- const DOMAIN_CE4WP = 'ce4wp';
40
- const ADMIN_CE4WP_DATA_VAR = 'ce4wp_data';
41
-
42
- /**
43
- * AdminManager constructor.
44
- */
45
- public function __construct()
46
- {
47
- $this->instance_name = rawurlencode(get_bloginfo('name'));
48
- $this->instance_handshake_token = OptionsHelper::get_handshake_token();
49
- $this->instance_uuid = OptionsHelper::get_instance_uuid();
50
- $this->instance_id = OptionsHelper::get_instance_id();
51
- $this->instance_url = rawurlencode(get_bloginfo('wpurl'));
52
- $this->instance_callback_url = rawurlencode(get_bloginfo('wpurl') . '?rest_route=/creativemail/v1/callback');
53
- $this->dashboard_url = EnvironmentHelper::get_app_url() . 'marketing/dashboard?wp_site_name=' . $this->instance_name
54
- . '&wp_site_uuid=' . $this->instance_uuid
55
- . '&wp_callback_url=' . $this->instance_callback_url
56
- . '&wp_instance_url=' . $this->instance_url
57
- . '&wp_version=' . get_bloginfo('version')
58
- . '&plugin_version=' . CE4WP_PLUGIN_VERSION;
59
- }
60
-
61
- /**
62
- * Will register all the hooks for the admin portion of the plugin.
63
- */
64
- public function add_hooks()
65
- {
66
- add_action(self::ADMIN_MENU_HOOK, array( $this, 'build_menu' ));
67
- add_action(self::ADMIN_ENQUEUE_SCRIPTS_HOOK, array( $this, 'add_assets' ));
68
- add_action(self::ADMIN_NOTICES_HOOK, array($this, 'add_admin_notice_permalink' ));
69
- add_action(self::ADMIN_NOTICES_HOOK, array($this, 'add_admin_notice_review' ));
70
- add_action(self::ADMIN_NOTICES_HOOK, array($this, 'add_admin_get_started_banner' ));
71
- add_action(self::ADMIN_NOTICES_HOOK, array($this, 'add_admin_feedback_notice' ));
72
- add_action(self::ADMIN_INIT_HOOK, array($this, 'activation_redirect' ));
73
- add_action(self::ADMIN_INIT_HOOK, array($this, 'ignore_review_notice' ));
74
-
75
- add_filter('admin_footer_text', array( $this, 'admin_footer_text' ), 1 );
76
- add_action('wp_ajax_woocommerce_ce4wp_rated', array( $this, 'mark_as_rated' ) );
77
- add_action('wp_dashboard_setup', array( $this, 'add_admin_dashboard_widget' ) );
78
-
79
- // sso request
80
- add_action('wp_ajax_ce4wp_request_sso', [$this, 'request_single_sign_on_url'] );
81
-
82
- // deactivation footer
83
- add_action(self::ADMIN_ENQUEUE_SCRIPTS_HOOK, [$this, 'deactivation_modal_js'], 20);
84
- add_action(self::ADMIN_ENQUEUE_SCRIPTS_HOOK, [$this, 'deactivation_modal_css']);
85
- add_action('admin_footer', [$this, 'show_deactivation_modal']);
86
- add_action('wp_ajax_ce4wp_deactivate_survey', [$this, 'deactivate_survey_post'] );
87
- }
88
-
89
- private function check_nonce()
90
- {
91
- $nonce = $_POST[self::ADMIN_NONCE];
92
-
93
- if (!wp_verify_nonce($nonce,self::ADMIN_AJAX_NONCE))
94
- {
95
- $response = new Response();
96
- $response->url = admin_url('admin.php?page=creativemail');
97
- wp_send_json_success($response);
98
- }
99
- }
100
-
101
- private function create_nonce()
102
- {
103
- return wp_create_nonce(self::ADMIN_AJAX_NONCE);
104
- }
105
-
106
- function request_single_sign_on_url_internal($linkReference = null, $linkParameters = null) {
107
- $sso = $this->get_sso_link($linkReference, $linkParameters);
108
-
109
- if (is_null($sso))
110
- {
111
- $current_user = wp_get_current_user();
112
- $redirectUrl = EnvironmentHelper::get_app_gateway_url('wordpress/v1.0/instances/open?clearSession=true&redirectUrl=');
113
- $onboardingUrl = EnvironmentHelper::get_app_url() . 'marketing/onboarding/signup?wp_site_name=' . $this->instance_name
114
- . '&wp_site_uuid=' . $this->instance_uuid
115
- . '&wp_handshake=' . $this->instance_handshake_token
116
- . '&wp_callback_url=' . $this->instance_callback_url
117
- . '&wp_instance_url=' . $this->instance_url
118
- . '&wp_version=' . get_bloginfo('version')
119
- . '&plugin_version=' . CE4WP_PLUGIN_VERSION
120
- . '&first_name=' . urlencode( $current_user->user_firstname )
121
- . '&last_name=' . urlencode( $current_user->user_lastname )
122
- . '&email=' . urlencode( $current_user->user_email );
123
- $referred_by = OptionsHelper::get_referred_by();
124
-
125
- if (!empty($referred_by)) {
126
- $utm_campaign = '';
127
- if (is_string($referred_by)) {
128
- $utm_campaign = str_replace(';', '|', $referred_by);
129
- }
130
- $onboardingUrl .= '&utm_source=wordpress&utm_medium=plugin&utm_campaign=' . $utm_campaign;
131
- }
132
- return $redirectUrl . rawurlencode($onboardingUrl);
133
- }
134
- return $sso;
135
- }
136
-
137
- function request_single_sign_on_url()
138
- {
139
- // Check for nonce security.
140
- $this->check_nonce();
141
-
142
- $linkReference = array_key_exists('link_reference', $_POST) ? $_POST['link_reference'] : null;
143
- $linkParameters = array_key_exists('link_parameters', $_POST) ? $_POST['link_parameters'] : null;
144
-
145
- $response = new Response();
146
- $response->url = $this->request_single_sign_on_url_internal($linkReference, $linkParameters);
147
-
148
- wp_send_json_success($response);
149
- }
150
-
151
- function deactivate_survey_post()
152
- {
153
- // Check for nonce security.
154
- $this->check_nonce();
155
-
156
- $instance_id = OptionsHelper::get_instance_id();
157
- $instance_api_key = OptionsHelper::get_instance_api_key();
158
- $connected_account_id = OptionsHelper::get_connected_account_id();
159
-
160
- parse_str($_POST['data'], $post_data);
161
-
162
- $survey_value = $post_data['ce4wp_deactivation_option'];
163
- if (is_null($survey_value))
164
- {
165
- wp_send_json_success();
166
- }
167
-
168
- $arguments = array(
169
- 'method' => 'POST',
170
- 'headers' => array(
171
- 'x-api-key' => $instance_api_key,
172
- 'x-account-id' => $connected_account_id,
173
- 'content-type' => 'application/json'
174
- ),
175
- 'body' => wp_json_encode(
176
- array(
177
- 'instance_id' => $instance_id,
178
- 'survey_id' => 1,
179
- 'value' => $survey_value,
180
- 'message' => $post_data['other']
181
- )
182
- )
183
- );
184
-
185
- wp_remote_post(EnvironmentHelper::get_app_gateway_url() . 'wordpress/v1.0/survey', $arguments);
186
-
187
- wp_send_json_success();
188
- }
189
-
190
- private function should_show_deactivation_modal() {
191
- if (!function_exists('get_current_screen')) {
192
- return false;
193
- }
194
- $screen = get_current_screen();
195
- if (is_null($screen)) {
196
- return false;
197
- }
198
- return (in_array($screen->id, ['plugins', 'plugins-network'], true));
199
- }
200
-
201
- function deactivation_modal_js() {
202
- if (!$this->should_show_deactivation_modal()) {
203
- return;
204
- }
205
- wp_enqueue_script('ce4wp_deactivate_survey', CE4WP_PLUGIN_URL.'assets/js/deactivation.js', [],CE4WP_PLUGIN_VERSION,true);
206
- wp_localize_script('ce4wp_deactivate_survey', self::ADMIN_CE4WP_DATA_VAR, array(
207
- 'url' => admin_url('admin-ajax.php'),
208
- 'nonce' => $this->create_nonce()
209
- ));
210
- }
211
-
212
- function deactivation_modal_css() {
213
- if (!$this->should_show_deactivation_modal()) {
214
- return;
215
- }
216
- wp_enqueue_style('ce4wp_deactivate_survey', CE4WP_PLUGIN_URL.'assets/css/deactivation.css', [],CE4WP_PLUGIN_VERSION,'');
217
- }
218
-
219
- function show_deactivation_modal() {
220
- if (!$this->should_show_deactivation_modal()) {
221
- return;
222
- }
223
- printf('<div class="ce4wp-deactivate-survey-modal" id="ce4wp-deactivate-survey">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  <div class="ce4wp-deactivate-survey-wrap">
225
  <div class="ce4wp-deactivate-survey">
226
  <h2>%s</h2>
@@ -243,352 +339,371 @@ class AdminManager
243
  </div>
244
  </div>
245
  </div>',
246
- __('Sadness... why leave so soon?', self::DOMAIN_CE4WP),
247
- __('I’m not sending email campaigns right now', self::DOMAIN_CE4WP),
248
- __('It didn’t have the features I want', self::DOMAIN_CE4WP),
249
- __('I didn’t like the email editor', self::DOMAIN_CE4WP),
250
- __('It was too confusing', self::DOMAIN_CE4WP),
251
- __('There were technical issues', self::DOMAIN_CE4WP),
252
- __('I don’t have enough email contacts', self::DOMAIN_CE4WP),
253
- __('It’s a temporary deactivation', self::DOMAIN_CE4WP),
254
- __('Other', self::DOMAIN_CE4WP),
255
- __('Thank you', self::DOMAIN_CE4WP),
256
- __('Close this window and deactivate Creative Mail', self::DOMAIN_CE4WP)
257
- );
258
- }
259
-
260
- function add_admin_notice_review()
261
- {
262
-
263
- $install_date = get_option('ce4wp_install_date');
264
- if (!$install_date) {
265
- return false;
266
- }
267
-
268
- $install_date = date_create($install_date);
269
- $date_now = date_create(date('Y-m-d G:i:s'));
270
- // @phpstan-ignore-next-line
271
- $date_diff = date_diff($install_date, $date_now);
272
-
273
- if ($date_diff->format("%d") < 7 ) {
274
-
275
- return false;
276
- }
277
-
278
- if (! get_option('ce4wp_ignore_review_notice') ) {
279
-
280
- echo '<div class="updated"><p>';
281
-
282
- /* translators: text. */
283
- printf(
284
- __( 'Awesome, you\'ve been using <a href="admin.php?page=creativemail">Creative Mail</a> for more than 1 week. May we ask you to give it a 5-star rating on WordPress? | <a href="%2$s" target="_blank">Ok, you deserved it</a> | <a href="%1$s">I already did</a> | <a href="%1$s">No, not good enough</a>', self::DOMAIN_CE4WP ), '?ce4wp-ignore-notice=0',
285
- 'https://wordpress.org/plugins/creative-mail-by-constant-contact/'
286
- );
287
- echo "</p></div>";
288
- }
289
- }
290
-
291
- public function ignore_review_notice()
292
- {
293
- if (isset($_GET['ce4wp-ignore-notice']) && '0' == $_GET['ce4wp-ignore-notice'] ) {
294
- update_option('ce4wp_ignore_review_notice', 'true');
295
- }
296
- }
297
-
298
- public function mark_as_rated()
299
- {
300
-
301
- update_option('ce4wp_admin_footer_text_rated', 1);
302
-
303
- wp_send_json_success();
304
- }
305
-
306
- /**
307
- * Changes the admin footer text on admin pages.
308
- *
309
- * @param string $footer_text
310
- *
311
- * @return string
312
- */
313
- public function admin_footer_text( $footer_text )
314
- {
315
- if ($this->is_cm_screen_and_show_footer())
316
- {
317
- $footer_text = sprintf(
318
- esc_html__('If you like %1$s please leave us a %2$s rating. A huge thanks in advance!', self::DOMAIN_CE4WP),
319
- sprintf('<strong>%s</strong>', esc_html__('Creative Mail', self::DOMAIN_CE4WP)),
320
- '<a href="https://wordpress.org/plugins/creative-mail-by-constant-contact/#reviews?rate=5#new-post" target="_blank" class="ce4wp-rating-link" data-rated="' . esc_attr__('Thank You', self::DOMAIN_CE4WP) . '">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
321
- );
322
- }
323
-
324
- return $footer_text;
325
- }
326
-
327
- function is_cm_screen_and_show_footer() {
328
- $screen = get_current_screen();
329
-
330
- if (! empty($screen)
331
- && ('toplevel_page_creativemail' === $screen->id || 'creative-mail_page_creativemail_settings' === $screen->id )
332
- && ! get_option('ce4wp_admin_footer_text_rated')
333
- ) {
334
- return true;
335
- }
336
- return false;
337
- }
338
-
339
- /**
340
- * Redirects the user after plugin activation.
341
- */
342
- function activation_redirect()
343
- {
344
- if (intval(get_option('ce4wp_activation_redirect', false)) === wp_get_current_user()->ID ) {
345
- // Make sure we don't redirect again after this one
346
- delete_option('ce4wp_activation_redirect');
347
-
348
- // don't do the redirect while activating the plugin through the rest request.
349
- if ((defined( 'REST_REQUEST' ) && REST_REQUEST)) {
350
- return;
351
- }
352
-
353
- // the woocommerce onboarding wizard will have a profile
354
- $onboarding_profile = get_option('woocommerce_onboarding_profile');
355
- // if the onboarding profile has business extensions
356
- if (is_array($onboarding_profile) && array_key_exists('business_extensions', $onboarding_profile)) {
357
- // if the business extensions contains our plugin, we just skip this.
358
- if (is_array($onboarding_profile['business_extensions']) && in_array('creative-mail-by-constant-contact', $onboarding_profile['business_extensions'])) {
359
- return;
360
- }
361
- }
362
- // Only do this for single site installs.
363
- if ( isset( $_GET['activate-multi'] ) || is_network_admin() ) {
364
- return;
365
- }
366
-
367
- wp_safe_redirect(admin_url('admin.php?page=creativemail'));
368
- exit;
369
- }
370
- }
371
-
372
- /**
373
- * Will add all the required assets for the admin portion of the plugin.
374
- */
375
- public function add_assets()
376
- {
377
- wp_register_style('ce4wp_admin', CE4WP_PLUGIN_URL . 'assets/css/admin.css', [], CE4WP_PLUGIN_VERSION);
378
- wp_enqueue_style('ce4wp_admin');
379
- wp_enqueue_style('ce4wp-font-poppins', 'https://fonts.googleapis.com/css?family=Poppins:400,500');
380
- wp_enqueue_script('wp-api');
381
-
382
- $this->enqueue_dashboard_js();
383
-
384
- if ($this->is_cm_screen_and_show_footer())
385
- {
386
- wp_enqueue_script('ce4wp_admin_footer_rating', CE4WP_PLUGIN_URL . 'assets/js/footer_rating.js', ['wp-api'], CE4WP_PLUGIN_VERSION, true);
387
- }
388
- }
389
-
390
- /**
391
- * Will build the menu for WP-Admin
392
- */
393
- public function build_menu()
394
- {
395
- $hasConnectedAccount = OptionsHelper::get_instance_id() !== null;
396
- // Did the user complete the entire setup?
397
- $main_action = $hasConnectedAccount
398
- ? array( $this, 'show_dashboard' )
399
- : array( $this, 'show_setup' );
400
-
401
- // Create the root menu item.
402
- $icon = (string) file_get_contents(CE4WP_PLUGIN_DIR . 'assets/images/icon.svg');
403
- // Filter to change the menu position if there is any conflict.
404
- $position = apply_filters( 'ce4wp_menu_position', '35.5' );
405
- // @phpstan-ignore-next-line
406
- add_menu_page('Creative Mail', esc_html__('Creative Mail', self::DOMAIN_CE4WP), 'manage_options', 'creativemail', $main_action, 'data:image/svg+xml;base64,' . base64_encode($icon), $position);
407
-
408
- $sub_actions = array();
409
-
410
- if ($hasConnectedAccount) {
411
- $sub_actions[] = array(
412
- 'title' => esc_html__('Campaigns', self::DOMAIN_CE4WP),
413
- 'text' => '<span id="ce4wp-menu-campaigns" data-link_reference="5166faec-1dbb-4434-bad0-bb2f75898f92">' . __('Campaigns', self::DOMAIN_CE4WP) . '</span>',
414
- 'slug' => 'creativemail_campaigns',
415
- 'callback' => null
416
- );
417
- $sub_actions[] = array(
418
- 'title' => esc_html__('Contacts', self::DOMAIN_CE4WP),
419
- 'text' => '<span id="ce4wp-menu-contacts" data-link_reference="836b20fc-9ff1-41b2-912b-a8646caf05a4">' . __('Contacts', self::DOMAIN_CE4WP) . '</span>',
420
- 'slug' => 'creativemail_contacts',
421
- 'callback' => null
422
- );
423
- $sub_actions[] = array(
424
- 'title' => esc_html__('WooCommerce', self::DOMAIN_CE4WP),
425
- 'text' => '<span id="ce4wp-menu-woocommerce" data-link_reference="1fabdbe2-95ed-4e1e-a2f3-ba0278f5096f">' . __('WooCommerce', self::DOMAIN_CE4WP) . '</span>',
426
- 'slug' => 'creativemail_woocommerce',
427
- 'callback' => null
428
- );
429
- $sub_actions[] = array(
430
- 'title' => esc_html__('Automation', self::DOMAIN_CE4WP),
431
- 'text' => '<span id="ce4wp-menu-automation" data-link_reference="d5baea05-c603-4cca-852e-f8e82414f6b0">' . __('Automation', self::DOMAIN_CE4WP) . '</span>',
432
- 'slug' => 'creativemail_automation',
433
- 'callback' => null
434
- );
435
- }
436
- $sub_actions[] = array(
437
- 'title' => esc_html__('Settings', self::DOMAIN_CE4WP),
438
- 'text' => __('Settings', self::DOMAIN_CE4WP),
439
- 'slug' => 'creativemail_settings',
440
- 'callback' => array($this, 'show_settings_page')
441
- );
442
-
443
- foreach ($sub_actions as $sub_action) {
444
- add_submenu_page(
445
- 'creativemail',
446
- 'Creative Mail - ' . $sub_action['title'],
447
- $sub_action['text'],
448
- 'manage_options',
449
- $sub_action['slug'],
450
- // @phpstan-ignore-next-line
451
- $sub_action['callback']
452
- );
453
- }
454
-
455
- // Add woocommerce sub-menu page.
456
- add_submenu_page(
457
- self::ADMIN_WOOCOMMERCE,
458
- esc_html__('Creative Mail', self::DOMAIN_CE4WP),
459
- esc_html__('Creative Mail', self::DOMAIN_CE4WP),
460
- 'manage_woocommerce',
461
- 'ce4wp-woo-settings',
462
- // @phpstan-ignore-next-line
463
- $main_action
464
- );
465
- }
466
-
467
- public function add_admin_notice_permalink()
468
- {
469
- if (CreativeMail::get_instance()->get_integration_manager()->is_plugin_active(self::ADMIN_WOOCOMMERCE)) {
470
- if (! CreativeMail::get_instance()->get_integration_manager()->get_permalinks_enabled() ) {
471
- print( '<div class="notice notice-error is-dismissible"><p>'. esc_html__('Ohoh, pretty permalinks are disabled. To enable the CreativeMail WooCommerce integration', self::DOMAIN_CE4WP) .' <a href="/wp-admin/options-permalink.php">'. esc_html__('please update your permalink settings', self::DOMAIN_CE4WP) .'</a>.</p></div>');
472
- return;
473
- }
474
- }
475
- }
476
-
477
- public function add_admin_notice_password_protected()
478
- {
479
- print( '<div class="notice notice-error is-dismissible"><p>'. esc_html__('We see that you have the Password Protected plugin installed and activated on your WordPress site. While this plugin is active, CreativeMail wont be able to complete the setup since the Password Protected plugin is prohibiting us from interacting with your WordPress site.', self::DOMAIN_CE4WP) .' '. esc_html__('Please disable this plugin to start using CreativeMail.', self::DOMAIN_CE4WP) .'</p></div>');
480
- return;
481
- }
482
-
483
- public function add_admin_get_started_banner()
484
- {
485
- $ce_has_account = OptionsHelper::get_instance_id() != null;
486
- $ce_hide_banner = OptionsHelper::get_hide_banner('get_started');
487
-
488
- global $pagenow;
489
- if ( $pagenow == 'plugins.php' && !$ce_has_account && !$ce_hide_banner ) {
490
- $ce_hide_banner_url = get_rest_url( null, 'creativemail/v1/hide_banner?banner=get_started' );
491
- include CE4WP_PLUGIN_DIR . 'src/views/admin-get-started-banner.php';
492
- }
493
- }
494
-
495
- public function add_admin_feedback_notice()
496
- {
497
- global $pagenow;
498
- global $post_type;
499
-
500
- if ( $pagenow == 'edit.php' && $post_type == 'feedback' ) {
501
- $feedback_notice_module = new FeedbackNoticeModule();
502
- $feedback_notice_module->display();
503
- }
504
- }
505
-
506
- public function add_admin_dashboard_widget()
507
- {
508
- $widget_title = wp_kses(
509
- /* translators: Placeholder is a CreativeMail logo. */
510
- __( 'Email Marketing <span class="floater">By<div class="ce4wp_dashboard_icon"></div></span>', self::DOMAIN_CE4WP),
511
- array( 'span' => array( 'class' => array() ), 'div' => array( 'class' => array() ) )
512
- );
513
-
514
- add_meta_box(
515
- 'ce4wp_admin_dashboard_widget',
516
- $widget_title,
517
- array( $this, 'show_ce4wp_admin_dashboard_widget' ),
518
- 'dashboard',
519
- 'normal',
520
- 'high'
521
- );
522
- }
523
-
524
- public function show_ce4wp_admin_dashboard_widget()
525
- {
526
- $dashboard_widget_module = new DashboardWidgetModule();
527
- $dashboard_widget_module->show();
528
- }
529
-
530
- /**
531
- * Renders the onboarding flow.
532
- */
533
- public function show_setup()
534
- {
535
- include CE4WP_PLUGIN_DIR . 'src/views/onboarding.php';
536
- }
537
-
538
- /**
539
- * Renders the Creative Mail dashboard when the site is connected to an account.
540
- */
541
- public function show_dashboard()
542
- {
543
- include CE4WP_PLUGIN_DIR . 'src/views/dashboard.php';
544
- }
545
-
546
- private function enqueue_dashboard_js() {
547
- wp_enqueue_script('ce4wp_dashboard', CE4WP_PLUGIN_URL.'assets/js/dashboard.js', ['jquery'],CE4WP_PLUGIN_VERSION);
548
- wp_localize_script('ce4wp_dashboard', self::ADMIN_CE4WP_DATA_VAR, array(
549
- 'url' => admin_url('admin-ajax.php'),
550
- 'nonce' => $this->create_nonce()
551
- ));
552
- }
553
-
554
- /**
555
- * Generates an SSO link for the current user.
556
- *
557
- * @param $linkReference string|null
558
- * @param $linkParameters array|null
559
- *
560
- * @return string|null
561
- * @since 1.1.5
562
- */
563
- public function get_sso_link(string $linkReference = null, array $linkParameters = null)
564
- {
565
- // Only if you are running in wp-admin
566
- if(!current_user_can('administrator')) {
567
- return null;
568
- }
569
-
570
- // If all the three values are available, we can use the SSO flow
571
- $instance_id = OptionsHelper::get_instance_id();
572
- $instance_api_key = OptionsHelper::get_instance_api_key();
573
- $connected_account_id = OptionsHelper::get_connected_account_id();
574
-
575
- if (isset($instance_id) && !empty($instance_api_key) && isset($connected_account_id)) {
576
- try {
577
- return SsoHelper::generate_sso_link($instance_id, $instance_api_key, $connected_account_id, $linkReference, $linkParameters);
578
- }
579
- catch(Exception $ex) {
580
- RaygunManager::get_instance()->exception_handler($ex);
581
- }
582
- }
583
-
584
- return null;
585
- }
586
-
587
- /**
588
- * Renders the settings page for this plugin.
589
- */
590
- public function show_settings_page()
591
- {
592
- include CE4WP_PLUGIN_DIR . 'src/views/settings.php';
593
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
594
  }
16
  *
17
  * @ignore
18
  */
19
+ final class AdminManager {
20
+
21
+ /**
22
+ * Holds the instance of the AdminManager class.
23
+ *
24
+ * @var string
25
+ */
26
+ protected $instance_name;
27
+
28
+ /**
29
+ * Holds the instance UUID.
30
+ *
31
+ * @var string
32
+ */
33
+ protected $instance_uuid;
34
+
35
+ /**
36
+ * Holds the Instance Handshake Token.
37
+ *
38
+ * @var string
39
+ */
40
+ protected $instance_handshake_token;
41
+
42
+ /**
43
+ * Holds the Instance Key.
44
+ *
45
+ * @var int|null
46
+ */
47
+ protected $instance_id;
48
+
49
+ /**
50
+ * Holds the Instance URL.
51
+ *
52
+ * @var string
53
+ */
54
+ protected $instance_url;
55
+
56
+ /**
57
+ * Holds the Instance Callback URL.
58
+ *
59
+ * @var string
60
+ */
61
+ protected $instance_callback_url;
62
+
63
+ /**
64
+ * Holds the Dashboard URL.
65
+ *
66
+ * @var string
67
+ */
68
+ protected $dashboard_url;
69
+
70
+ const ADMIN_NOTICES_HOOK = 'admin_notices';
71
+ const ADMIN_INIT_HOOK = 'admin_init';
72
+ const ADMIN_MENU_HOOK = 'admin_menu';
73
+ const ADMIN_ENQUEUE_SCRIPTS_HOOK = 'admin_enqueue_scripts';
74
+
75
+ const ADMIN_AJAX_NONCE = 'ajax-nonce';
76
+ const ADMIN_NONCE = 'nonce';
77
+
78
+ const ADMIN_WOOCOMMERCE = 'woocommerce';
79
+ const DOMAIN_CE4WP = 'creative-mail-by-constant-contact';
80
+ const ADMIN_CE4WP_DATA_VAR = 'ce4wp_data';
81
+
82
+ /**
83
+ * AdminManager constructor.
84
+ */
85
+ public function __construct() {
86
+ $this->instance_name = rawurlencode(get_bloginfo('name'));
87
+ $this->instance_handshake_token = OptionsHelper::get_handshake_token();
88
+ $this->instance_uuid = OptionsHelper::get_instance_uuid();
89
+ $this->instance_id = OptionsHelper::get_instance_id();
90
+ $this->instance_url = rawurlencode(get_bloginfo('wpurl'));
91
+ $this->instance_callback_url = rawurlencode(get_bloginfo('wpurl') . '?rest_route=/creativemail/v1/callback');
92
+ $this->dashboard_url = EnvironmentHelper::get_app_url() . 'marketing/dashboard?wp_site_name=' . $this->instance_name
93
+ . '&wp_site_uuid=' . $this->instance_uuid
94
+ . '&wp_callback_url=' . $this->instance_callback_url
95
+ . '&wp_instance_url=' . $this->instance_url
96
+ . '&wp_version=' . get_bloginfo('version')
97
+ . '&plugin_version=' . CE4WP_PLUGIN_VERSION;
98
+ }
99
+
100
+ /**
101
+ * Will register all the hooks for the admin portion of the plugin.
102
+ *
103
+ * @return void
104
+ */
105
+ public function add_hooks(): void {
106
+ add_action(self::ADMIN_MENU_HOOK, array( $this, 'build_menu' ));
107
+ add_action(self::ADMIN_ENQUEUE_SCRIPTS_HOOK, array( $this, 'add_assets' ));
108
+ add_action(self::ADMIN_NOTICES_HOOK, array( $this, 'add_admin_notice_permalink' ));
109
+ add_action(self::ADMIN_NOTICES_HOOK, array( $this, 'add_admin_notice_review' ));
110
+ add_action(self::ADMIN_NOTICES_HOOK, array( $this, 'add_admin_get_started_banner' ));
111
+ add_action(self::ADMIN_NOTICES_HOOK, array( $this, 'add_admin_feedback_notice' ));
112
+ add_action(self::ADMIN_INIT_HOOK, array( $this, 'activation_redirect' ));
113
+ add_action(self::ADMIN_INIT_HOOK, array( $this, 'ignore_review_notice' ));
114
+
115
+ add_filter('admin_footer_text', array( $this, 'admin_footer_text' ), 1 );
116
+ add_action('wp_ajax_woocommerce_ce4wp_rated', array( $this, 'mark_as_rated' ) );
117
+ add_action('wp_dashboard_setup', array( $this, 'add_admin_dashboard_widget' ) );
118
+
119
+ // Sso request.
120
+ add_action('wp_ajax_ce4wp_request_sso', array( $this, 'request_single_sign_on_url' ) );
121
+
122
+ // Deactivation footer.
123
+ add_action(self::ADMIN_ENQUEUE_SCRIPTS_HOOK, array( $this, 'deactivation_modal_js' ), 20);
124
+ add_action(self::ADMIN_ENQUEUE_SCRIPTS_HOOK, array( $this, 'deactivation_modal_css' ));
125
+ add_action('admin_footer', array( $this, 'show_deactivation_modal' ));
126
+ add_action('wp_ajax_ce4wp_deactivate_survey', array( $this, 'deactivate_survey_post' ) );
127
+ }
128
+
129
+ /**
130
+ * Check for the nonce.
131
+ *
132
+ * @return void
133
+ */
134
+ private function check_nonce(): void {
135
+ $nonce = '';
136
+ if ( isset( $_POST[ self::ADMIN_NONCE ] )
137
+ && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST[ self::ADMIN_NONCE ] ) ), self::ADMIN_AJAX_NONCE ) ) {
138
+ $nonce = sanitize_text_field( wp_unslash( $_POST[ self::ADMIN_NONCE ] ) );
139
+ }
140
+ if ( ! wp_verify_nonce( $nonce, self::ADMIN_AJAX_NONCE ) ) {
141
+ $response = new Response();
142
+ $response->url = admin_url('admin.php?page=creativemail');
143
+
144
+ wp_send_json_success($response);
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Creates the nonce for the Admin Manager.
150
+ *
151
+ * @return false|string
152
+ */
153
+ private function create_nonce(): string {
154
+ return wp_create_nonce(self::ADMIN_AJAX_NONCE);
155
+ }
156
+
157
+ /**
158
+ * Sends the SSO URL for internal purposes.
159
+ *
160
+ * @param string|null $linkReference The link reference.
161
+ * @param array<string,string>|null $linkParameters The link parameters.
162
+ *
163
+ * @return string
164
+ */
165
+ public function request_single_sign_on_url_internal(
166
+ ?string $linkReference = null,
167
+ ?array $linkParameters = null
168
+ ): string {
169
+ $sso = $this->get_sso_link($linkReference, $linkParameters);
170
+
171
+ if ( is_null($sso) ) {
172
+ $current_user = wp_get_current_user();
173
+ $redirectUrl = EnvironmentHelper::get_app_gateway_url('wordpress/v1.0/instances/open?clearSession=true&redirectUrl=');
174
+ $onboardingUrl = EnvironmentHelper::get_app_url() . 'marketing/onboarding/signup?wp_site_name=' . $this->instance_name
175
+ . '&wp_site_uuid=' . $this->instance_uuid
176
+ . '&wp_handshake=' . $this->instance_handshake_token
177
+ . '&wp_callback_url=' . $this->instance_callback_url
178
+ . '&wp_instance_url=' . $this->instance_url
179
+ . '&wp_version=' . get_bloginfo('version')
180
+ . '&plugin_version=' . CE4WP_PLUGIN_VERSION
181
+ . '&first_name=' . urlencode( $current_user->user_firstname )
182
+ . '&last_name=' . urlencode( $current_user->user_lastname )
183
+ . '&email=' . urlencode( $current_user->user_email );
184
+ $referred_by = OptionsHelper::get_referred_by();
185
+
186
+ if ( ! empty($referred_by) ) {
187
+ $utm_campaign = '';
188
+
189
+ if ( is_string($referred_by) ) {
190
+ $utm_campaign = str_replace(';', '|', $referred_by);
191
+ }
192
+
193
+ $onboardingUrl .= '&utm_source=wordpress&utm_medium=plugin&utm_campaign=' . $utm_campaign;
194
+ }
195
+
196
+ return $redirectUrl . rawurlencode($onboardingUrl);
197
+ }
198
+
199
+ return $sso;
200
+ }
201
+
202
+ /**
203
+ * Sends the SSO URL for external purposes.
204
+ *
205
+ * @return void
206
+ */
207
+ public function request_single_sign_on_url() {
208
+ // Check for nonce security.
209
+ $this->check_nonce();
210
+
211
+ $linkReference = array_key_exists('link_reference', $_POST) ? sanitize_text_field( wp_unslash( $_POST['link_reference'] ) ) : null;
212
+ $linkParameters = array_key_exists('link_parameters', $_POST) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['link_parameters'] ) ) : null;
213
+ $response = new Response();
214
+ $response->url = $this->request_single_sign_on_url_internal($linkReference, $linkParameters);
215
+
216
+ wp_send_json_success($response);
217
+ }
218
+
219
+ /**
220
+ * Deactivates the survey.
221
+ *
222
+ * @return void
223
+ */
224
+ public function deactivate_survey_post(): void {
225
+ // Check for nonce security.
226
+ $this->check_nonce();
227
+
228
+ $instance_id = OptionsHelper::get_instance_id();
229
+ $instance_api_key = OptionsHelper::get_instance_api_key();
230
+ $connected_account_id = OptionsHelper::get_connected_account_id();
231
+
232
+ if ( isset($_POST['data']) ) {
233
+ parse_str(sanitize_text_field(wp_unslash($_POST['data'])), $post_data);
234
+ }
235
+
236
+ $survey_value = $post_data['ce4wp_deactivation_option'];
237
+
238
+ if ( is_null($survey_value) ) {
239
+ wp_send_json_success();
240
+ }
241
+
242
+ $arguments = array(
243
+ 'method' => 'POST',
244
+ 'headers' => array(
245
+ 'x-api-key' => $instance_api_key,
246
+ 'x-account-id' => $connected_account_id,
247
+ 'content-type' => 'application/json',
248
+ ),
249
+ 'body' => wp_json_encode(
250
+ array(
251
+ 'instance_id' => $instance_id,
252
+ 'survey_id' => 1,
253
+ 'value' => $survey_value,
254
+ 'message' => $post_data['other'],
255
+ )
256
+ ),
257
+ );
258
+
259
+ wp_remote_post(EnvironmentHelper::get_app_gateway_url('wordpress/v1.0/survey'), $arguments);
260
+ wp_send_json_success();
261
+ }
262
+
263
+ /**
264
+ * Verifies if it can show the deactivation modal when required.
265
+ *
266
+ * @return bool
267
+ */
268
+ private function should_show_deactivation_modal(): bool {
269
+ if ( ! function_exists('get_current_screen') ) {
270
+ return false;
271
+ }
272
+ $screen = get_current_screen();
273
+ if ( is_null($screen) ) {
274
+ return false;
275
+ }
276
+ return ( in_array($screen->id, array( 'plugins', 'plugins-network' ), true) );
277
+ }
278
+
279
+ /**
280
+ * Add the deactivation modal JS if not added before.
281
+ *
282
+ * @return void
283
+ */
284
+ public function deactivation_modal_js(): void {
285
+ if ( ! $this->should_show_deactivation_modal() ) {
286
+ return;
287
+ }
288
+
289
+ wp_enqueue_script('ce4wp_deactivate_survey', CE4WP_PLUGIN_URL . 'assets/js/deactivation.js', array(), CE4WP_PLUGIN_VERSION, true);
290
+ wp_localize_script('ce4wp_deactivate_survey', self::ADMIN_CE4WP_DATA_VAR, array(
291
+ 'url' => admin_url('admin-ajax.php'),
292
+ 'nonce' => $this->create_nonce(),
293
+ ));
294
+ }
295
+
296
+ /**
297
+ * Returns the deactivation modal CSS.
298
+ *
299
+ * @return void
300
+ */
301
+ public function deactivation_modal_css(): void {
302
+ if ( ! $this->should_show_deactivation_modal() ) {
303
+ return;
304
+ }
305
+
306
+ wp_enqueue_style('ce4wp_deactivate_survey', CE4WP_PLUGIN_URL . 'assets/css/deactivation.css', array(), CE4WP_PLUGIN_VERSION, '');
307
+ }
308
+
309
+ /**
310
+ * Returns the deactivation modal HTML.
311
+ *
312
+ * @return void
313
+ */
314
+ public function show_deactivation_modal(): void {
315
+ if ( ! $this->should_show_deactivation_modal() ) {
316
+ return;
317
+ }
318
+
319
+ printf('<div class="ce4wp-deactivate-survey-modal" id="ce4wp-deactivate-survey">
320
  <div class="ce4wp-deactivate-survey-wrap">
321
  <div class="ce4wp-deactivate-survey">
322
  <h2>%s</h2>
339
  </div>
340
  </div>
341
  </div>',
342
+ esc_html__('Sadness... why leave so soon?', self::DOMAIN_CE4WP),
343
+ esc_html__('I’m not sending email campaigns right now', self::DOMAIN_CE4WP),
344
+ esc_html__('It didn’t have the features I want', self::DOMAIN_CE4WP),
345
+ esc_html__('I didn’t like the email editor', self::DOMAIN_CE4WP),
346
+ esc_html__('It was too confusing', self::DOMAIN_CE4WP),
347
+ esc_html__('There were technical issues', self::DOMAIN_CE4WP),
348
+ esc_html__('I don’t have enough email contacts', self::DOMAIN_CE4WP),
349
+ esc_html__('It’s a temporary deactivation', self::DOMAIN_CE4WP),
350
+ esc_html__('Other', self::DOMAIN_CE4WP),
351
+ esc_html__('Thank you', self::DOMAIN_CE4WP),
352
+ esc_html__('Close this window and deactivate Creative Mail', self::DOMAIN_CE4WP)
353
+ );
354
+ }
355
+
356
+ /**
357
+ * Adds the admin notice review.
358
+ *
359
+ * @return false|void
360
+ */
361
+ public function add_admin_notice_review() {
362
+ $install_date = get_option('ce4wp_install_date');
363
+
364
+ if ( ! $install_date ) {
365
+ return false;
366
+ }
367
+
368
+ $install_date = date_create($install_date);
369
+ $date_now = date_create(gmdate('Y-m-d G:i:s'));
370
+ // @phpstan-ignore-next-line
371
+ $date_diff = date_diff($install_date, $date_now);
372
+
373
+ if ( $date_diff->format('%d') < 7 ) {
374
+ return false;
375
+ }
376
+
377
+ if ( ! get_option('ce4wp_ignore_review_notice') ) {
378
+ include_once CE4WP_PLUGIN_DIR . 'src/views/admin-feedback-notice/after-week-notice.php';
379
+ }
380
+ }
381
+
382
+ /**
383
+ * Updates the value that checks the review notice.
384
+ *
385
+ * @return void
386
+ */
387
+ public function ignore_review_notice(): void {
388
+ if ( isset($_GET['ce4wp-ignore-notice']) && '0' == $_GET['ce4wp-ignore-notice'] ) {
389
+ update_option('ce4wp_ignore_review_notice', 'true');
390
+ }
391
+ }
392
+
393
+ /**
394
+ * Marks the plugin as rated if clicked the footer rating text.
395
+ *
396
+ * @return void
397
+ */
398
+ public function mark_as_rated(): void {
399
+ update_option('ce4wp_admin_footer_text_rated', 1);
400
+ wp_send_json_success();
401
+ }
402
+
403
+ /**
404
+ * Changes the admin footer text on admin pages.
405
+ *
406
+ * @param string $footer_text The existing footer text.
407
+ *
408
+ * @return string
409
+ */
410
+ public function admin_footer_text( string $footer_text ): string {
411
+ if ( $this->is_cm_screen_and_show_footer() ) {
412
+ $footer_text = sprintf(
413
+ // translators: text.
414
+ esc_html__('If you like %1$s please leave us a %2$s rating. A huge thanks in advance!', self::DOMAIN_CE4WP),
415
+ sprintf('<strong>%s</strong>', esc_html__('Creative Mail', self::DOMAIN_CE4WP)),
416
+ '<a href="https://wordpress.org/plugins/creative-mail-by-constant-contact/#reviews?rate=5#new-post" target="_blank" class="ce4wp-rating-link" data-rated="' . esc_attr__('Thank You', self::DOMAIN_CE4WP) . '">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
417
+ );
418
+ }
419
+
420
+ return $footer_text;
421
+ }
422
+
423
+ /**
424
+ * Checks if the current screen is a Creative Mail screen and if the footer should be shown.
425
+ *
426
+ * @return bool
427
+ */
428
+ private function is_cm_screen_and_show_footer(): bool {
429
+ $screen = get_current_screen();
430
+
431
+ if ( ! empty($screen)
432
+ && ( 'toplevel_page_creativemail' === $screen->id || 'creative-mail_page_creativemail_settings' === $screen->id )
433
+ && ! get_option('ce4wp_admin_footer_text_rated')
434
+ ) {
435
+ return true;
436
+ }
437
+ return false;
438
+ }
439
+
440
+ /**
441
+ * Call for the activation redirect.
442
+ *
443
+ * @return void
444
+ */
445
+ public function activation_redirect(): void {
446
+ if ( intval(get_option('ce4wp_activation_redirect', false)) === wp_get_current_user()->ID ) {
447
+ // Make sure we don't redirect again after this one.
448
+ delete_option('ce4wp_activation_redirect');
449
+
450
+ // Don't do the redirect while activating the plugin through the rest request.
451
+ if ( ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) {
452
+ return;
453
+ }
454
+
455
+ // The woocommerce onboarding wizard will have a profile.
456
+ $onboarding_profile = get_option('woocommerce_onboarding_profile');
457
+ // If the onboarding profile has business extensions.
458
+ if ( is_array($onboarding_profile) && array_key_exists('business_extensions', $onboarding_profile) ) {
459
+ // If the business extensions contains our plugin, we just skip this.
460
+ if ( is_array($onboarding_profile['business_extensions']) && in_array('creative-mail-by-constant-contact', $onboarding_profile['business_extensions'], true) ) {
461
+ return;
462
+ }
463
+ }
464
+ // Only do this for single site installs.
465
+ if ( isset( $_GET['activate-multi'] ) || is_network_admin() ) {
466
+ return;
467
+ }
468
+
469
+ wp_safe_redirect(admin_url('admin.php?page=creativemail'));
470
+ exit;
471
+ }
472
+ }
473
+
474
+ /**
475
+ * Add the required assets.
476
+ *
477
+ * @return void
478
+ */
479
+ public function add_assets(): void {
480
+ wp_register_style('ce4wp_admin', CE4WP_PLUGIN_URL . 'assets/css/admin.css', array(), CE4WP_PLUGIN_VERSION);
481
+ wp_enqueue_style('ce4wp_admin');
482
+ wp_enqueue_style('ce4wp-font-poppins', 'https://fonts.googleapis.com/css?family=Poppins:400,500', array(), CE4WP_PLUGIN_VERSION);
483
+ wp_enqueue_script('wp-api');
484
+
485
+ $this->enqueue_dashboard_js();
486
+
487
+ if ( $this->is_cm_screen_and_show_footer() ) {
488
+ wp_enqueue_script('ce4wp_admin_footer_rating', CE4WP_PLUGIN_URL . 'assets/js/footer_rating.js', array( 'wp-api' ), CE4WP_PLUGIN_VERSION, true);
489
+ }
490
+ }
491
+
492
+ /**
493
+ * Will build the menu for WP-Admin.
494
+ *
495
+ * @return void
496
+ */
497
+ public function build_menu() {
498
+ $hasConnectedAccount = OptionsHelper::get_instance_id() !== null;
499
+ // Did the user complete the entire setup?
500
+ $main_action = $hasConnectedAccount
501
+ ? array( $this, 'show_dashboard' )
502
+ : array( $this, 'show_setup' );
503
+
504
+ // Create the root menu item.
505
+ $icon = (string) file_get_contents(CE4WP_PLUGIN_DIR . 'assets/images/icon.svg');
506
+ // Filter to change the menu position if there is any conflict.
507
+ $position = apply_filters( 'ce4wp_menu_position', '35.5' );
508
+ // @phpstan-ignore-next-line
509
+ add_menu_page(
510
+ 'Creative Mail',
511
+ esc_html__('Creative Mail', self::DOMAIN_CE4WP),
512
+ 'manage_options',
513
+ 'creativemail',
514
+ $main_action,
515
+ 'data:image/svg+xml;base64,' . base64_encode($icon),
516
+ $position
517
+ );
518
+
519
+ $sub_actions = array();
520
+
521
+ if ( $hasConnectedAccount ) {
522
+ $sub_actions[] = array(
523
+ 'title' => esc_html__('Campaigns', self::DOMAIN_CE4WP),
524
+ 'text' => '<span id="ce4wp-menu-campaigns" data-link_reference="5166faec-1dbb-4434-bad0-bb2f75898f92">' . __('Campaigns', self::DOMAIN_CE4WP) . '</span>',
525
+ 'slug' => 'creativemail_campaigns',
526
+ 'callback' => null,
527
+ );
528
+ $sub_actions[] = array(
529
+ 'title' => esc_html__('Contacts', self::DOMAIN_CE4WP),
530
+ 'text' => '<span id="ce4wp-menu-contacts" data-link_reference="836b20fc-9ff1-41b2-912b-a8646caf05a4">' . __('Contacts', self::DOMAIN_CE4WP) . '</span>',
531
+ 'slug' => 'creativemail_contacts',
532
+ 'callback' => null,
533
+ );
534
+ $sub_actions[] = array(
535
+ 'title' => esc_html__('WooCommerce', self::DOMAIN_CE4WP),
536
+ 'text' => '<span id="ce4wp-menu-woocommerce" data-link_reference="1fabdbe2-95ed-4e1e-a2f3-ba0278f5096f">' . __('WooCommerce', self::DOMAIN_CE4WP) . '</span>',
537
+ 'slug' => 'creativemail_woocommerce',
538
+ 'callback' => null,
539
+ );
540
+ $sub_actions[] = array(
541
+ 'title' => esc_html__('Automation', self::DOMAIN_CE4WP),
542
+ 'text' => '<span id="ce4wp-menu-automation" data-link_reference="d5baea05-c603-4cca-852e-f8e82414f6b0">' . __('Automation', self::DOMAIN_CE4WP) . '</span>',
543
+ 'slug' => 'creativemail_automation',
544
+ 'callback' => null,
545
+ );
546
+ }
547
+ $sub_actions[] = array(
548
+ 'title' => esc_html__('Settings', self::DOMAIN_CE4WP),
549
+ 'text' => __('Settings', self::DOMAIN_CE4WP),
550
+ 'slug' => 'creativemail_settings',
551
+ 'callback' => array( $this, 'show_settings_page' ),
552
+ );
553
+
554
+ foreach ( $sub_actions as $sub_action ) {
555
+ add_submenu_page(
556
+ 'creativemail',
557
+ 'Creative Mail - ' . $sub_action['title'],
558
+ $sub_action['text'],
559
+ 'manage_options',
560
+ $sub_action['slug'],
561
+ // @phpstan-ignore-next-line
562
+ $sub_action['callback']
563
+ );
564
+ }
565
+
566
+ // Add woocommerce sub-menu page.
567
+ add_submenu_page(
568
+ self::ADMIN_WOOCOMMERCE,
569
+ esc_html__('Creative Mail', self::DOMAIN_CE4WP),
570
+ esc_html__('Creative Mail', self::DOMAIN_CE4WP),
571
+ 'manage_woocommerce',
572
+ 'ce4wp-woo-settings',
573
+ // @phpstan-ignore-next-line
574
+ $main_action
575
+ );
576
+ }
577
+
578
+ /**
579
+ * Adds the Admin Notice Permalink on Creative Mail
580
+ *
581
+ * @return void
582
+ */
583
+ public function add_admin_notice_permalink(): void {
584
+ if ( CreativeMail::get_instance()->get_integration_manager()->is_plugin_active(self::ADMIN_WOOCOMMERCE) ) {
585
+ if ( ! CreativeMail::get_instance()->get_integration_manager()->get_permalinks_enabled() ) {
586
+ print( '<div class="notice notice-error is-dismissible"><p>' . esc_html__('Ohoh, pretty permalinks are disabled. To enable the CreativeMail WooCommerce integration', self::DOMAIN_CE4WP) . ' <a href="/wp-admin/options-permalink.php">' . esc_html__('please update your permalink settings', self::DOMAIN_CE4WP) . '</a>.</p></div>' );
587
+ return;
588
+ }
589
+ }
590
+ }
591
+
592
+ public function add_admin_notice_password_protected(): void {
593
+ print( '<div class="notice notice-error is-dismissible"><p>' . esc_html__('We see that you have the Password Protected plugin installed and activated on your WordPress site. While this plugin is active, CreativeMail wont be able to complete the setup since the Password Protected plugin is prohibiting us from interacting with your WordPress site.', self::DOMAIN_CE4WP) . ' ' . esc_html__('Please disable this plugin to start using CreativeMail.', self::DOMAIN_CE4WP) . '</p></div>' );
594
+ return;
595
+ }
596
+
597
+ public function add_admin_get_started_banner(): void {
598
+ $ce_has_account = OptionsHelper::get_instance_id() != null;
599
+ $ce_hide_banner = OptionsHelper::get_hide_banner('get_started');
600
+
601
+ global $pagenow;
602
+
603
+ if ( 'plugins.php' == $pagenow && ! $ce_has_account && ! $ce_hide_banner ) {
604
+ $ce_hide_banner_url = get_rest_url( null, 'creativemail/v1/hide_banner?banner=get_started' );
605
+ include CE4WP_PLUGIN_DIR . 'src/views/admin-get-started-banner.php';
606
+ }
607
+ }
608
+
609
+ public function add_admin_feedback_notice(): void {
610
+ global $pagenow;
611
+ global $post_type;
612
+
613
+ if ( 'edit.php' == $pagenow && 'feedback' == $post_type ) {
614
+ $feedback_notice_module = new FeedbackNoticeModule();
615
+ $feedback_notice_module->display();
616
+ }
617
+ }
618
+
619
+ public function add_admin_dashboard_widget(): void {
620
+ $widget_title = wp_kses(
621
+ /* translators: Placeholder is a CreativeMail logo. */
622
+ __( 'Email Marketing <span class="floater">By<div class="ce4wp_dashboard_icon"></div></span>', self::DOMAIN_CE4WP),
623
+ array(
624
+ 'span' => array( 'class' => array() ),
625
+ 'div' => array( 'class' => array() ),
626
+ )
627
+ );
628
+
629
+ add_meta_box(
630
+ 'ce4wp_admin_dashboard_widget',
631
+ $widget_title,
632
+ array( $this, 'show_ce4wp_admin_dashboard_widget' ),
633
+ 'dashboard',
634
+ 'normal',
635
+ 'high'
636
+ );
637
+ }
638
+
639
+ public function show_ce4wp_admin_dashboard_widget(): void {
640
+ $dashboard_widget_module = new DashboardWidgetModule();
641
+ $dashboard_widget_module->show();
642
+ }
643
+
644
+ /**
645
+ * Renders the onboarding flow.
646
+ *
647
+ * @return void
648
+ */
649
+ public function show_setup(): void {
650
+ include CE4WP_PLUGIN_DIR . 'src/views/onboarding.php';
651
+ }
652
+
653
+ /**
654
+ * Renders the Creative Mail dashboard when the site is connected to an account.
655
+ *
656
+ * @return void
657
+ */
658
+ public function show_dashboard(): void {
659
+ include CE4WP_PLUGIN_DIR . 'src/views/dashboard.php';
660
+ }
661
+
662
+ private function enqueue_dashboard_js(): void {
663
+ wp_enqueue_script('ce4wp_dashboard', CE4WP_PLUGIN_URL . 'assets/js/dashboard.js', array( 'jquery' ), CE4WP_PLUGIN_VERSION, true);
664
+ wp_localize_script('ce4wp_dashboard', self::ADMIN_CE4WP_DATA_VAR, array(
665
+ 'url' => admin_url('admin-ajax.php'),
666
+ 'nonce' => $this->create_nonce(),
667
+ ));
668
+ }
669
+
670
+ /**
671
+ * Generates an SSO link for the current user.
672
+ *
673
+ * @param string|null $linkReference The link reference.
674
+ * @param array|null $linkParameters The link parameters.
675
+ *
676
+ * @return string|null
677
+ * @since 1.1.5
678
+ */
679
+ public function get_sso_link( ?string $linkReference = null, ?array $linkParameters = null ): ?string {
680
+ // Only if you are running in wp-admin.
681
+ if ( ! current_user_can('administrator') ) {
682
+ return null;
683
+ }
684
+
685
+ // If all the three values are available, we can use the SSO flow.
686
+ $instance_id = OptionsHelper::get_instance_id();
687
+ $instance_api_key = OptionsHelper::get_instance_api_key();
688
+ $connected_account_id = OptionsHelper::get_connected_account_id();
689
+
690
+ if ( isset($instance_id) && ! empty($instance_api_key) && isset($connected_account_id) ) {
691
+ try {
692
+ return SsoHelper::generate_sso_link($instance_id, $instance_api_key, $connected_account_id, $linkReference, $linkParameters);
693
+ } catch ( Exception $ex ) {
694
+ RaygunManager::get_instance()->exception_handler($ex);
695
+ }
696
+ }
697
+
698
+ return null;
699
+ }
700
+
701
+ /**
702
+ * Renders the settings page for this plugin.
703
+ *
704
+ * @return void
705
+ */
706
+ public function show_settings_page(): void {
707
+ include CE4WP_PLUGIN_DIR . 'src/views/settings.php';
708
+ }
709
  }
src/Managers/ApiManager.php CHANGED
@@ -24,778 +24,792 @@ use WP_REST_Response;
24
  *
25
  * @package CreativeMail\Managers
26
  */
27
- class ApiManager
28
- {
29
- const API_NAMESPACE = "creativemail/v1";
30
- const ROUTE_METHODS = 'methods';
31
- const ROUTE_PATH = 'path';
32
- const ROUTE_CALLBACK = 'callback';
33
- const ROUTE_PERMISSION_CALLBACK = 'permission_callback';
34
- const ROUTE_REQUIRES_WP_ADMIN = [
35
- '/sso'
36
- ];
37
- const HTTP_STATUS = 'status';
38
- private $api_background_process;
39
-
40
- function __construct()
41
- {
42
- $this->api_background_process = new ApiBackgroundProcess();
43
- }
44
-
45
- public function get_api_background_process()
46
- {
47
- return $this->api_background_process;
48
- }
49
-
50
- /**
51
- * Will add all the hooks that are required to setup our plugin API.
52
- */
53
- public function add_hooks()
54
- {
55
- add_action('rest_api_init', array($this, 'add_rest_endpoints'));
56
- }
57
-
58
- public function validate_wp_admin()
59
- {
60
- if(!current_user_can('administrator')) {
61
- return new WP_Error('rest_forbidden', __('Sorry, you are not allowed to do that.','ce4wp'), array( self::HTTP_STATUS => 401 ));
62
- }
63
-
64
- return true;
65
- }
66
-
67
- public function validate_api_key()
68
- {
69
- //never cache our rest endpoints
70
- nocache_headers();
71
-
72
- if (! array_key_exists("HTTP_X_API_KEY", $_SERVER) ) {
73
- return new WP_Error('rest_forbidden', __('Sorry, you are not allowed to do that.','ce4wp'), array( self::HTTP_STATUS => 401 ));
74
- }
75
-
76
- $key = OptionsHelper::get_instance_api_key();
77
- $apiKey = $_SERVER["HTTP_X_API_KEY"];
78
- // verify that api key is valid
79
- if ($apiKey === $key ) {
80
- return true;
81
- }
82
-
83
- return new WP_Error('rest_forbidden', __('Sorry, you are not allowed to do that.','ce4wp'), array( self::HTTP_STATUS => 401 ));
84
- }
85
-
86
- public function validate_callback()
87
- {
88
- //never cache our rest endpoints.
89
- nocache_headers();
90
-
91
- if (! array_key_exists("HTTP_X_API_KEY", $_SERVER) ) {
92
- return new WP_Error('rest_forbidden', __('Sorry, you are not allowed to do that.','ce4wp'), array( self::HTTP_STATUS => 401 ));
93
- }
94
-
95
- $apiKey = $_SERVER["HTTP_X_API_KEY"];
96
- // Verify handshake expiration.
97
- $expiration = OptionsHelper::get_handshake_expiration();
98
- if ($expiration === null || $expiration < time() ) {
99
- return new WP_Error('rest_unauthorized', 'Unauthorized', array( self::HTTP_STATUS => 401 ));
100
- }
101
-
102
- // Verify handshake.
103
- if ($apiKey === OptionsHelper::get_handshake_token() ) {
104
- return true;
105
- }
106
-
107
- return new WP_Error('rest_unauthorized', 'Unauthorized', array( self::HTTP_STATUS => 401 ));
108
- }
109
-
110
- public function add_rest_endpoints()
111
- {
112
- // Add the endpoint to handle the callback.
113
- $routes = array (
114
- array (
115
- self::ROUTE_PATH => '/callback',
116
- self::ROUTE_METHODS => 'POST',
117
- self::ROUTE_CALLBACK => array(CreativeMail::get_instance()->get_instance_manager(), 'handle_callback'),
118
- self::ROUTE_PERMISSION_CALLBACK => function () {
119
- return $this->validate_callback();
120
- }
121
- ),
122
- array (
123
- self::ROUTE_PATH => '/available_plugins',
124
- self::ROUTE_METHODS => 'GET',
125
- self::ROUTE_CALLBACK => function () {
126
- return $this->modify_response($this->get_plugin_info(true));
127
- }
128
- ),
129
- array (
130
- self::ROUTE_PATH => '/available_plugins',
131
- self::ROUTE_METHODS => 'POST',
132
- self::ROUTE_CALLBACK => function ($request) {
133
- CreativeMail::get_instance()->get_integration_manager()->set_activated_plugins(json_decode($request->get_body()));
134
- }
135
- ),
136
- array (
137
- self::ROUTE_PATH => '/plugins',
138
- self::ROUTE_METHODS => 'GET',
139
- self::ROUTE_CALLBACK => function () {
140
- return $this->modify_response($this->get_plugin_info(false));
141
- }
142
- ),
143
- array (
144
- self::ROUTE_PATH => '/managed_email_notifications',
145
- self::ROUTE_METHODS => 'GET',
146
- self::ROUTE_CALLBACK => function () {
147
- $result = CreativeMail::get_instance()->get_email_manager()->get_managed_email_notifications();
148
- return $this->modify_response(new WP_REST_Response($result, 200));
149
- }
150
- ),
151
- array (
152
- self::ROUTE_PATH => '/managed_email_notifications',
153
- self::ROUTE_METHODS => 'POST',
154
- self::ROUTE_CALLBACK => function ($request) {
155
- return $this->get_managed_email_notifications($request);
156
- }
157
- ),
158
- array (
159
- self::ROUTE_PATH => '/abandoned_checkout',
160
- self::ROUTE_METHODS => 'GET',
161
- self::ROUTE_CALLBACK => function ($request) {
162
- return $this->modify_response($this->get_ce_checkout($request->get_param('uuid')));
163
- }
164
- ),
165
- array (
166
- self::ROUTE_PATH => '/wc_key',
167
- self::ROUTE_METHODS => 'GET',
168
- self::ROUTE_CALLBACK => function () {
169
- return $this->modify_response($this->get_wc_keys());
170
- }
171
- ),
172
- array (
173
- self::ROUTE_PATH => '/synchronize',
174
- self::ROUTE_METHODS => 'POST',
175
- self::ROUTE_CALLBACK => function () {
176
- do_action(CE4WP_SYNCHRONIZE_ACTION);
177
- return $this->modify_response(new WP_REST_Response(null, 200));
178
- }
179
- ),
180
- array (
181
- self::ROUTE_PATH => '/wc_information',
182
- self::ROUTE_METHODS => 'GET',
183
- self::ROUTE_CALLBACK => function () {
184
- return $this->modify_response(new WP_REST_Response(new WCInformationModel(), 200));
185
- }
186
- ),
187
- array (
188
- self::ROUTE_PATH => '/wc_products',
189
- self::ROUTE_METHODS => 'GET',
190
- self::ROUTE_CALLBACK => function ($request) {
191
- return $this->get_wc_products($request);
192
- }
193
- ),
194
- array (
195
- self::ROUTE_PATH => '/blog_information',
196
- self::ROUTE_METHODS => 'GET',
197
- self::ROUTE_CALLBACK => function () {
198
- return $this->modify_response(new WP_REST_Response(new BlogInformation(), 200));
199
- }
200
- ),
201
- array (
202
- self::ROUTE_PATH => '/wp_posts',
203
- self::ROUTE_METHODS => 'GET',
204
- self::ROUTE_CALLBACK => function ($request) {
205
- return $this->get_wp_posts($request);
206
- }
207
- ),
208
- array (
209
- self::ROUTE_PATH => '/images',
210
- self::ROUTE_METHODS => 'GET',
211
- self::ROUTE_CALLBACK => function () {
212
- return $this->get_images();
213
- }
214
- ),
215
- array (
216
- self::ROUTE_PATH => '/hide_banner',
217
- self::ROUTE_METHODS => 'POST',
218
- self::ROUTE_CALLBACK => function ($request) {
219
- return $this->hide_banner($request);
220
- },
221
- self::ROUTE_PERMISSION_CALLBACK => function () {
222
- return true;
223
- }
224
- ),
225
- array (
226
- self::ROUTE_PATH => '/get_pages_with_ce_forms',
227
- self::ROUTE_METHODS => 'GET',
228
- self::ROUTE_CALLBACK => function () {
229
- return $this->get_pages_with_ce_forms();
230
- },
231
- ),
232
- array (
233
- self::ROUTE_PATH => '/check_if_previously_purchased',
234
- self::ROUTE_METHODS => 'GET',
235
- self::ROUTE_CALLBACK => function ($request) {
236
- return $this->check_if_previously_purchased($request);
237
- },
238
- )
239
- );
240
-
241
- foreach ($routes as $route) {
242
- $this->register_route($route);
243
- }
244
- }
245
-
246
- private function find_pages_by_content_tag( $tag ){
247
- $pagesWithTag = array();
248
- $pages = get_pages(); // Defaults are type=page, status=published.
249
- if (empty($pages)){
250
- return null;
251
- }
252
-
253
- foreach ($pages as $page) {
254
- if (! is_int ($page) ) {
255
- $post_content = $page->post_content;
256
- if (strpos($post_content, $tag) !== false){
257
- $pagesWithTag[] = ['page_id' => $page->ID, 'post_title' => $page->post_title, 'post_status' => $page->post_status];
258
- }
259
- }
260
- }
261
- return $pagesWithTag;
262
- }
263
-
264
- private function get_plugin_info($onlyActivePlugins)
265
- {
266
- $result = array();
267
- $activePlugins = CreativeMail::get_instance()->get_integration_manager()->get_active_plugins();
268
- if ($onlyActivePlugins === true ) {
269
- foreach ( $activePlugins as $activePlugin ) {
270
- array_push(
271
- $result, array(
272
- 'name' => $activePlugin->get_name(),
273
- 'slug' => $activePlugin->get_slug()
274
- )
275
- );
276
- }
277
- } else {
278
- $allPlugins = CreativeMail::get_instance()->get_integration_manager()->get_supported_integrations();
279
- $activatedPlugins = CreativeMail::get_instance()->get_integration_manager()->get_activated_plugins();
280
- foreach ( $allPlugins as $plugin ) {
281
- if ($plugin->is_hidden_from_suggestions()) {
282
- continue;
283
- }
284
- array_push(
285
- $result, array(
286
- 'name' => $plugin->get_name(),
287
- 'slug' => $plugin->get_slug(),
288
- 'installed' => in_array($plugin, $activePlugins, true) !== false,
289
- 'activated' => array_search($plugin->get_slug(), $activatedPlugins, true) !== false,
290
- )
291
- );
292
- }
293
- }
294
-
295
- return new WP_REST_Response($result, 200);
296
- }
297
-
298
- /**
299
- * Modifies the response to disable caching
300
- *
301
- * @param WP_REST_Response $response The endpoint its response
302
- *
303
- * @return WP_REST_Response
304
- */
305
- private function modify_response($response)
306
- {
307
- return $response;
308
- }
309
-
310
- private function get_ce_checkout($checkout_uuid) {
311
- if (empty($checkout_uuid)) {
312
- return new WP_REST_Response("No uuid provided", 400);
313
- }
314
-
315
- $checkout = CreativeMail::get_instance()->get_database_manager()->get_checkout_data( 'user_id,user_email,checkout_contents,checkout_updated,checkout_created,checkout_recovered,checkout_uuid',
316
- 'checkout_uuid = %s', [ $checkout_uuid ] );
317
- if (empty($checkout)) {
318
- return new WP_REST_Response($checkout, 404);
319
- }
320
-
321
- return new WP_REST_Response($checkout, 200);
322
- }
323
-
324
- private function get_wc_keys()
325
- {
326
- $wcKey = CreativeMail::get_instance()->get_api_manager()->get_or_generate_key();
327
- $key = sha1(OptionsHelper::get_instance_api_key() . OptionsHelper::get_instance_uuid());
328
- $salt = (string) openssl_random_pseudo_bytes((int) openssl_cipher_iv_length('aes-256-cbc'));
329
- $salted = '';
330
- $dx = '';
331
- while ( strlen($salted) < 48 ) {
332
- $dx = md5($dx . $key . $salt, true);
333
- $salted .= $dx;
334
- }
335
- $key = substr($salted, 0, 32);
336
- $iv = substr($salted, 32, 16);
337
- $cs = (string) openssl_encrypt($wcKey->consumer_secret, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
338
- $ck = (string) openssl_encrypt($wcKey->consumer_key, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
339
-
340
- $result = new HashSchema();
341
- $result->salt = bin2hex($salt);
342
- $result->secret = base64_encode($cs);
343
- $result->key = base64_encode($ck);
344
- $result->version = '1';
345
-
346
- return new WP_REST_Response($result, 200);
347
- }
348
-
349
- /**
350
- * Registers a route to the WP Rest endpoints for this plugin.
351
- *
352
- * @param array $route
353
- */
354
- private function register_route(array $route)
355
- {
356
-
357
- // Make sure the route is valid
358
- $path = $route[self::ROUTE_PATH];
359
- $methods = $route[self::ROUTE_METHODS];
360
- $callback = $route[self::ROUTE_CALLBACK];
361
-
362
- if (array_key_exists(self::ROUTE_PERMISSION_CALLBACK, $route)) {
363
- $permission_callback = $route[self::ROUTE_PERMISSION_CALLBACK];
364
- }
365
- else if(in_array($path, self::ROUTE_REQUIRES_WP_ADMIN)) {
366
- $permission_callback = array( $this, 'validate_wp_admin' );
367
- }
368
- else {
369
- $permission_callback = array($this, 'validate_api_key' );
370
- }
371
-
372
- // Make sure we at least have a path
373
- if (empty($path)) { return;
374
- }
375
-
376
- // If we don't have a method, assume it is GET
377
- if(empty($methods)) {
378
- $methods = 'GET';
379
- }
380
-
381
- $arguments = array(
382
- self::ROUTE_METHODS => $methods,
383
- self::ROUTE_CALLBACK => $callback,
384
- self::ROUTE_PERMISSION_CALLBACK => $permission_callback
385
- );
386
-
387
- register_rest_route(self::API_NAMESPACE, $path, $arguments);
388
- }
389
-
390
- /**
391
- * Refreshes the WC REST API key.
392
- *
393
- * @param int $user_id WordPress user ID
394
- *
395
- * @return object|bool
396
- *
397
- * @throws Exception
398
- *
399
- * @since 1.1.0
400
- */
401
- public function refresh_key( $user_id = null )
402
- {
403
-
404
- $this->revoke_key();
405
-
406
- return $this->create_key($user_id);
407
- }
408
-
409
-
410
- /**
411
- * Generates a WC REST API key for Jilt to use.
412
- *
413
- * @param int $user_id WordPress user ID
414
- *
415
- * @return object
416
- *
417
- * @throws Exception
418
- *
419
- * @since 1.1.0
420
- */
421
- public function create_key( $user_id = null )
422
- {
423
- global $wpdb;
424
-
425
- // if no user is specified, try the current user or find an eligible admin
426
- if (! $user_id ) {
427
-
428
- $user_id = get_current_user_id();
429
-
430
- // if the current user can't manage WC, try and get the first admin
431
- if (! user_can($user_id, 'manage_woocommerce') ) {
432
-
433
- $user_id = null;
434
-
435
- $administrator_ids = get_users(
436
- array(
437
- 'role' => 'administrator',
438
- 'fields' => 'ID',
439
- )
440
- );
441
-
442
- foreach ( $administrator_ids as $administrator_id ) {
443
-
444
- if (user_can($administrator_id, 'manage_woocommerce') ) {
445
-
446
- $user_id = $administrator_id;
447
- break;
448
- }
449
- }
450
-
451
- if (! $user_id ) {
452
- throw new Exception('No eligible users could be found');
453
- }
454
- }
455
-
456
- // otherwise, check the user that's specified
457
- } elseif (! user_can($user_id, 'manage_woocommerce') ) {
458
-
459
- throw new Exception("User {$user_id} does not have permission");
460
- }
461
-
462
- $user = get_userdata($user_id);
463
-
464
- if (! $user ) {
465
- throw new Exception('Invalid user');
466
- }
467
-
468
- $consumer_key = 'ck_' . wc_rand_hash();
469
- $consumer_secret = 'cs_' . wc_rand_hash();
470
-
471
- $result = $wpdb->insert(
472
- $wpdb->prefix . 'woocommerce_api_keys',
473
- array(
474
- 'user_id' => $user->ID,
475
- 'description' => 'CreativeMail',
476
- 'permissions' => 'read_write',
477
- 'consumer_key' => wc_api_hash($consumer_key),
478
- 'consumer_secret' => $consumer_secret,
479
- 'truncated_key' => substr($consumer_key, -7),
480
- ),
481
- array(
482
- '%d',
483
- '%s',
484
- '%s',
485
- '%s',
486
- '%s',
487
- '%s',
488
- )
489
- );
490
-
491
- if (! $result ) {
492
- throw new Exception('The key could not be saved');
493
- }
494
-
495
- $key = new ApiSchema();
496
-
497
- $key->key_id = $wpdb->insert_id;
498
- $key->user_id = $user->ID;
499
- $key->consumer_key = $consumer_key;
500
- $key->consumer_secret = $consumer_secret;
501
-
502
- // store the new key ID
503
- $this->set_key_id($key->key_id);
504
- $this->set_consumer_key($consumer_key);
505
-
506
- return $key;
507
- }
508
-
509
-
510
- /**
511
- * Revokes the configured WC REST API key.
512
- *
513
- * @since 1.1.0
514
- */
515
- public function revoke_key()
516
- {
517
- global $wpdb;
518
-
519
- if ($key_id = $this->get_key_id() ) {
520
- $wpdb->delete($wpdb->prefix . 'woocommerce_api_keys', array( 'key_id' => $key_id ), array( '%d' ));
521
- }
522
-
523
- OptionsHelper::delete_wc_api_key_id();
524
- OptionsHelper::delete_wc_consumer_key();
525
- }
526
-
527
-
528
- /**
529
- * Gets the configured WC REST API key.
530
- *
531
- * @since 1.1.0
532
- *
533
- * @return object|null
534
- */
535
- public function get_key()
536
- {
537
- global $wpdb;
538
-
539
- $key = null;
540
-
541
- if ($id = $this->get_key_id() ) {
542
- $key = $wpdb->get_row(
543
- $wpdb->prepare(
544
- "
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
545
  SELECT key_id, user_id, permissions, consumer_secret
546
  FROM {$wpdb->prefix}woocommerce_api_keys
547
  WHERE key_id = %d
548
  ", $id
549
- )
550
- );
551
-
552
- if (isset($key) ) {
553
- $key->consumer_key = $this->get_consumer_key();
554
- }
555
- }
556
-
557
- return $key;
558
- }
559
-
560
- /**
561
- * Gets or generate the configured WC REST API key.
562
- *
563
- * @return object|bool
564
- * @throws Exception
565
- * @since 1.1.0
566
- */
567
- public function get_or_generate_key()
568
- {
569
- $key = $this->get_key();
570
-
571
- if ($key == null) {
572
- $key = $this->refresh_key();
573
- }
574
-
575
- return $key;
576
- }
577
-
578
- /**
579
- * Gets the configured WC REST API key ID.
580
- *
581
- * @since 1.1.0
582
- *
583
- * @return int
584
- */
585
- public function get_key_id()
586
- {
587
- $wc_api_key = OptionsHelper::get_wc_api_key_id();
588
- return is_int($wc_api_key) ? $wc_api_key : 0;
589
- }
590
-
591
- public function get_consumer_key()
592
- {
593
- return OptionsHelper::get_wc_consumer_key();
594
- }
595
-
596
- /**
597
- * Sets a WC REST API key ID.
598
- *
599
- * @param int $id key ID
600
- *
601
- * @since 1.1.0
602
- */
603
- public function set_key_id( $id )
604
- {
605
- OptionsHelper::set_wc_api_key_id($id);
606
- }
607
-
608
- public function set_consumer_key( $key )
609
- {
610
- OptionsHelper::set_wc_consumer_key($key);
611
- }
612
-
613
- private function get_managed_email_notifications($request)
614
- {
615
- if(!CreativeMail::get_instance()->get_integration_manager()->get_permalinks_enabled()) {
616
- return $this->modify_response(new WP_REST_Response(array( 'message' => 'Please enable pretty permalinks in the WordPress settings.'), 400));
617
- }
618
-
619
- $result = CreativeMail::get_instance()->get_email_manager()->set_managed_email_notifications(json_decode($request->get_body()));
620
- return $this->modify_response(new WP_REST_Response($result, 200));
621
- }
622
-
623
- private function get_wc_products($request)
624
- {
625
- $productData = array();
626
- $products = array();
627
- $active_plugins = apply_filters('active_plugins', get_option('active_plugins'));
628
-
629
- if (in_array('woocommerce/woocommerce.php', $active_plugins)) {
630
- $page = 1;
631
- $limit = 25;
632
- $pageFromRequest = $request->get_param('page');
633
- $pageLimitFromRequest = $request->get_param('limit');
634
-
635
- if(!empty($pageFromRequest) && $pageFromRequest != '{page}') {
636
- $page = $pageFromRequest;
637
- }
638
- if(!empty($pageLimitFromRequest) && $pageLimitFromRequest != '{limit}') {
639
- $limit = $pageLimitFromRequest;
640
- }
641
-
642
- $types = array_merge( array_keys( wc_get_product_types() ) );
643
-
644
- if (in_array('woocommerce-bookings/woocommerce-bookings.php', $active_plugins)) {
645
- array_push($types, 'booking');
646
- }
647
-
648
- // Get 25 most recent products.
649
- $products = wc_get_products(
650
- array(
651
- 'limit' => $limit,
652
- 'paginate' => true,
653
- 'paged' => $page,
654
- 'type' => $types
655
- )
656
- );
657
-
658
- if (!is_array ($products)) {
659
- foreach ($products->products as $product) {
660
- array_push($productData, new WCProductModel($product->get_data()));
661
- }
662
- }
663
- }
664
- $response = new WP_REST_Response($productData, 200);
665
- if (!is_array ($products)) {
666
- $response->header('X-WP-Total', $products->total);
667
- $response->header('X-WP-TotalPages', $products->max_num_pages);
668
- }
669
- return $this->modify_response($response);
670
- }
671
-
672
- private function get_wp_posts($request)
673
- {
674
- $page = 1;
675
- $postData = array();
676
-
677
- if (property_exists($request,'page')) {
678
- $page = (int)$request['page'];
679
- }
680
-
681
- $posts = get_posts(
682
- array(
683
- 'posts_per_page' => 10,
684
- 'paged' => $page,
685
- 'post_type' => 'post'
686
- )
687
- );
688
-
689
- foreach ($posts as $post) {
690
- array_push($postData, new BlogPost($post));
691
- }
692
-
693
- return $this->modify_response(new WP_REST_Response($postData, 200));
694
- }
695
-
696
- private function get_images()
697
- {
698
- $attachmentData = array();
699
- $attachments = get_posts(
700
- array(
701
- 'post_type' => 'attachment',
702
- 'post_mime_type' => 'image',
703
- 'post_status' => 'inherit',
704
- 'posts_per_page' => -1
705
- )
706
- );
707
-
708
- foreach ($attachments as $attachment) {
709
- array_push($attachmentData, new BlogAttachment($attachment));
710
- }
711
-
712
- return $this->modify_response(new WP_REST_Response($attachmentData, 200));
713
- }
714
-
715
- private function hide_banner($request)
716
- {
717
- $banner = $request->get_param('banner');
718
- if (empty($banner)) {
719
- return $this->modify_response(new WP_REST_Response('Missing banner param', 400));
720
- }
721
-
722
- OptionsHelper::set_hide_banner($banner, true);
723
- return $this->modify_response(new WP_REST_Response(null, 204));
724
- }
725
-
726
- private function get_pages_with_ce_forms()
727
- {
728
- if (version_compare($GLOBALS['wp_version'], '5.5', '<')) {
729
- // This is to prevent CE from making the Gutenberg recommendation when Gutenberg isn't supported.
730
- return $this->modify_response(
731
- new WP_REST_Response(
732
- array(array( 'page_id' => 1, 'post_title' => '', 'post_status' => 'published' )),
733
- 200
734
- )
735
- );
736
- }
737
-
738
- $blocks = $this->find_pages_by_content_tag("wp:ce4wp/subscribe");
739
- return $this->modify_response(new WP_REST_Response($blocks, 200));
740
- }
741
-
742
- private function check_if_previously_purchased($request)
743
- {
744
- $active_plugins = apply_filters('active_plugins', get_option('active_plugins'));
745
- $exists = false;
746
-
747
- if (in_array('woocommerce/woocommerce.php', $active_plugins)) {
748
- $product_ID = $request->get_param('product');
749
- $email = $request->get_param('email');
750
- $daysPassedFloat = 86400 * $request->get_param('daysPassed');
751
- $daysPassed = round($daysPassedFloat);
752
-
753
- $currentDay = new DateTime();
754
- $currentDate = $currentDay->format('Y-m-d H:i:s');
755
- $currentTime = strtotime($currentDate);
756
-
757
- $date = new DateTime();
758
- $date->sub(new DateInterval("PT{$daysPassed}S"));
759
- $initial_date = $date->format('Y-m-d H:i:s');
760
- $initialTime = strtotime($initial_date);
761
-
762
- $order = wc_get_orders( array(
763
- 'billing_email' => $email,
764
- 'date_created' => "$initialTime...$currentTime",
765
- 'status' => array('wc-completed')
766
- ));
767
-
768
- if (!empty($product_ID)) {
769
- if (is_array($order)){
770
- $exists = $this->check_if_product_exists_by_product_id($order, $product_ID);
771
- }
772
- } else {
773
- if(!empty($order)) {
774
- $exists = true;
775
- }
776
- }
777
- }
778
- return $this->modify_response(new WP_REST_Response($exists, 200));
779
- }
780
-
781
- private function check_if_product_exists_by_product_id(array $order, $product_ID)
782
- {
783
- $exists = false;
784
-
785
- foreach ($order as $itemsKey => $item) {
786
- $orderData = $item->get_data();
787
- foreach($orderData['line_items'] as $lineItem) {
788
- $product = $lineItem->get_product()->get_data();
789
- foreach($product_ID as $p_ID) {
790
- if($p_ID == $product['id']) {
791
- $exists = true;
792
- }
793
- }
794
- }
795
- if($exists) {
796
- break;
797
- }
798
- }
799
- return $exists;
800
- }
801
  }
24
  *
25
  * @package CreativeMail\Managers
26
  */
27
+ final class ApiManager {
28
+
29
+ const API_NAMESPACE = 'creativemail/v1';
30
+ const ROUTE_METHODS = 'methods';
31
+ const ROUTE_PATH = 'path';
32
+ const ROUTE_CALLBACK = 'callback';
33
+ const ROUTE_PERMISSION_CALLBACK = 'permission_callback';
34
+ const ROUTE_REQUIRES_WP_ADMIN = array(
35
+ '/sso',
36
+ );
37
+ const HTTP_STATUS = 'status';
38
+
39
+ /**
40
+ * Constructor for the ApiManager class.
41
+ *
42
+ * @var ApiBackgroundProcess
43
+ */
44
+ private $api_background_process;
45
+
46
+ public function __construct() {
47
+ $this->api_background_process = new ApiBackgroundProcess();
48
+ }
49
+
50
+ /**
51
+ * Returns the API Background Process.
52
+ *
53
+ * @return ApiBackgroundProcess
54
+ */
55
+ public function get_api_background_process(): ApiBackgroundProcess {
56
+ return $this->api_background_process;
57
+ }
58
+
59
+ /**
60
+ * Will add all the hooks that are required to set up our plugin API.
61
+ *
62
+ * @return void
63
+ */
64
+ public function add_hooks(): void {
65
+ add_action('rest_api_init', array( $this, 'add_rest_endpoints' ));
66
+ }
67
+
68
+ /**
69
+ * Validates if the current user has the admin required permissions to access the API.
70
+ *
71
+ * @return bool|WP_Error
72
+ */
73
+ public function validate_wp_admin() {
74
+ if ( ! current_user_can('administrator') ) {
75
+ return new WP_Error(
76
+ 'rest_forbidden',
77
+ __('Sorry, you are not allowed to do that.', 'creative-mail-by-constant-contact'),
78
+ array( self::HTTP_STATUS => 401 )
79
+ );
80
+ }
81
+
82
+ return true;
83
+ }
84
+
85
+ /**
86
+ * Validates the API Key.
87
+ *
88
+ * @return bool|WP_Error
89
+ */
90
+ public function validate_api_key() {
91
+ // Never cache our rest endpoints.
92
+ nocache_headers();
93
+
94
+ if ( ! array_key_exists('HTTP_X_API_KEY', $_SERVER) ) {
95
+ return new WP_Error(
96
+ 'rest_forbidden',
97
+ __('Sorry, you are not allowed to do that.', 'creative-mail-by-constant-contact'),
98
+ array( self::HTTP_STATUS => 401 )
99
+ );
100
+ }
101
+
102
+ $key = OptionsHelper::get_instance_api_key();
103
+ $apiKey = sanitize_text_field( wp_unslash ( $_SERVER['HTTP_X_API_KEY'] ) );
104
+ // Verify that api key is valid.
105
+ if ( $apiKey === $key ) {
106
+ return true;
107
+ }
108
+
109
+ return new WP_Error(
110
+ 'rest_forbidden',
111
+ __('Sorry, you are not allowed to do that.', 'creative-mail-by-constant-contact'),
112
+ array( self::HTTP_STATUS => 401 )
113
+ );
114
+ }
115
+
116
+ public function validate_callback() {
117
+ // Never cache our rest endpoints.
118
+ nocache_headers();
119
+
120
+ if ( ! array_key_exists('HTTP_X_API_KEY', $_SERVER) ) {
121
+ return new WP_Error('rest_forbidden', __('Sorry, you are not allowed to do that.', 'creative-mail-by-constant-contact'), array( self::HTTP_STATUS => 401 ));
122
+ }
123
+
124
+ $apiKey = sanitize_text_field( wp_unslash ( $_SERVER['HTTP_X_API_KEY'] ) );
125
+ // Verify handshake expiration.
126
+ $expiration = OptionsHelper::get_handshake_expiration();
127
+ if ( null === $expiration || $expiration < time() ) {
128
+ return new WP_Error('rest_unauthorized', 'Unauthorized', array( self::HTTP_STATUS => 401 ));
129
+ }
130
+
131
+ // Verify handshake.
132
+ if ( OptionsHelper::get_handshake_token() === $apiKey ) {
133
+ return true;
134
+ }
135
+
136
+ return new WP_Error('rest_unauthorized', 'Unauthorized', array( self::HTTP_STATUS => 401 ));
137
+ }
138
+
139
+ public function add_rest_endpoints() {
140
+ // Add the endpoint to handle the callback.
141
+ $routes = array(
142
+ array(
143
+ self::ROUTE_PATH => '/callback',
144
+ self::ROUTE_METHODS => 'POST',
145
+ self::ROUTE_CALLBACK => array( CreativeMail::get_instance()->get_instance_manager(), 'handle_callback' ),
146
+ self::ROUTE_PERMISSION_CALLBACK => function () {
147
+ return $this->validate_callback();
148
+ },
149
+ ),
150
+ array(
151
+ self::ROUTE_PATH => '/available_plugins',
152
+ self::ROUTE_METHODS => 'GET',
153
+ self::ROUTE_CALLBACK => function () {
154
+ return $this->modify_response($this->get_plugin_info(true));
155
+ },
156
+ ),
157
+ array(
158
+ self::ROUTE_PATH => '/available_plugins',
159
+ self::ROUTE_METHODS => 'POST',
160
+ self::ROUTE_CALLBACK => function ( $request ) {
161
+ CreativeMail::get_instance()->get_integration_manager()->set_activated_plugins(json_decode($request->get_body()));
162
+ },
163
+ ),
164
+ array(
165
+ self::ROUTE_PATH => '/plugins',
166
+ self::ROUTE_METHODS => 'GET',
167
+ self::ROUTE_CALLBACK => function () {
168
+ return $this->modify_response($this->get_plugin_info(false));
169
+ },
170
+ ),
171
+ array(
172
+ self::ROUTE_PATH => '/managed_email_notifications',
173
+ self::ROUTE_METHODS => 'GET',
174
+ self::ROUTE_CALLBACK => function () {
175
+ $result = CreativeMail::get_instance()->get_email_manager()->get_managed_email_notifications();
176
+ return $this->modify_response(new WP_REST_Response($result, 200));
177
+ },
178
+ ),
179
+ array(
180
+ self::ROUTE_PATH => '/managed_email_notifications',
181
+ self::ROUTE_METHODS => 'POST',
182
+ self::ROUTE_CALLBACK => function ( $request ) {
183
+ return $this->get_managed_email_notifications($request);
184
+ },
185
+ ),
186
+ array(
187
+ self::ROUTE_PATH => '/abandoned_checkout',
188
+ self::ROUTE_METHODS => 'GET',
189
+ self::ROUTE_CALLBACK => function ( $request ) {
190
+ return $this->modify_response($this->get_ce_checkout($request->get_param('uuid')));
191
+ },
192
+ ),
193
+ array(
194
+ self::ROUTE_PATH => '/wc_key',
195
+ self::ROUTE_METHODS => 'GET',
196
+ self::ROUTE_CALLBACK => function () {
197
+ return $this->modify_response($this->get_wc_keys());
198
+ },
199
+ ),
200
+ array(
201
+ self::ROUTE_PATH => '/synchronize',
202
+ self::ROUTE_METHODS => 'POST',
203
+ self::ROUTE_CALLBACK => function () {
204
+ do_action(CE4WP_SYNCHRONIZE_ACTION);
205
+ return $this->modify_response(new WP_REST_Response(null, 200));
206
+ },
207
+ ),
208
+ array(
209
+ self::ROUTE_PATH => '/wc_information',
210
+ self::ROUTE_METHODS => 'GET',
211
+ self::ROUTE_CALLBACK => function () {
212
+ return $this->modify_response(new WP_REST_Response(new WCInformationModel(), 200));
213
+ },
214
+ ),
215
+ array(
216
+ self::ROUTE_PATH => '/wc_products',
217
+ self::ROUTE_METHODS => 'GET',
218
+ self::ROUTE_CALLBACK => function ( $request ) {
219
+ return $this->get_wc_products($request);
220
+ },
221
+ ),
222
+ array(
223
+ self::ROUTE_PATH => '/blog_information',
224
+ self::ROUTE_METHODS => 'GET',
225
+ self::ROUTE_CALLBACK => function () {
226
+ return $this->modify_response(new WP_REST_Response(new BlogInformation(), 200));
227
+ },
228
+ ),
229
+ array(
230
+ self::ROUTE_PATH => '/wp_posts',
231
+ self::ROUTE_METHODS => 'GET',
232
+ self::ROUTE_CALLBACK => function ( $request ) {
233
+ return $this->get_wp_posts($request);
234
+ },
235
+ ),
236
+ array(
237
+ self::ROUTE_PATH => '/images',
238
+ self::ROUTE_METHODS => 'GET',
239
+ self::ROUTE_CALLBACK => function () {
240
+ return $this->get_images();
241
+ },
242
+ ),
243
+ array(
244
+ self::ROUTE_PATH => '/hide_banner',
245
+ self::ROUTE_METHODS => 'POST',
246
+ self::ROUTE_CALLBACK => function ( $request ) {
247
+ return $this->hide_banner($request);
248
+ },
249
+ self::ROUTE_PERMISSION_CALLBACK => function () {
250
+ return true;
251
+ },
252
+ ),
253
+ array(
254
+ self::ROUTE_PATH => '/get_pages_with_ce_forms',
255
+ self::ROUTE_METHODS => 'GET',
256
+ self::ROUTE_CALLBACK => function () {
257
+ return $this->get_pages_with_ce_forms();
258
+ },
259
+ ),
260
+ array(
261
+ self::ROUTE_PATH => '/check_if_previously_purchased',
262
+ self::ROUTE_METHODS => 'GET',
263
+ self::ROUTE_CALLBACK => function ( $request ) {
264
+ return $this->check_if_previously_purchased($request);
265
+ },
266
+ ),
267
+ );
268
+
269
+ foreach ( $routes as $route ) {
270
+ $this->register_route($route);
271
+ }
272
+ }
273
+
274
+ private function find_pages_by_content_tag( $tag ) {
275
+ $pagesWithTag = array();
276
+ $pages = get_pages(); // Defaults are type=page, status=published.
277
+ if ( empty($pages) ) {
278
+ return null;
279
+ }
280
+
281
+ foreach ( $pages as $page ) {
282
+ if ( ! is_int ($page) ) {
283
+ $post_content = $page->post_content;
284
+ if ( strpos($post_content, $tag) !== false ) {
285
+ $pagesWithTag[] = array(
286
+ 'page_id' => $page->ID,
287
+ 'post_title' => $page->post_title,
288
+ 'post_status' => $page->post_status,
289
+ );
290
+ }
291
+ }
292
+ }
293
+ return $pagesWithTag;
294
+ }
295
+
296
+ private function get_plugin_info( $onlyActivePlugins ) {
297
+ $result = array();
298
+ $activePlugins = CreativeMail::get_instance()->get_integration_manager()->get_active_plugins();
299
+ if ( true === $onlyActivePlugins ) {
300
+ foreach ( $activePlugins as $activePlugin ) {
301
+ array_push(
302
+ $result, array(
303
+ 'name' => $activePlugin->get_name(),
304
+ 'slug' => $activePlugin->get_slug(),
305
+ )
306
+ );
307
+ }
308
+ } else {
309
+ $allPlugins = CreativeMail::get_instance()->get_integration_manager()->get_supported_integrations();
310
+ $activatedPlugins = CreativeMail::get_instance()->get_integration_manager()->get_activated_plugins();
311
+ foreach ( $allPlugins as $plugin ) {
312
+ if ( $plugin->is_hidden_from_suggestions() ) {
313
+ continue;
314
+ }
315
+ array_push(
316
+ $result, array(
317
+ 'name' => $plugin->get_name(),
318
+ 'slug' => $plugin->get_slug(),
319
+ 'installed' => in_array($plugin, $activePlugins, true) !== false,
320
+ 'activated' => array_search($plugin->get_slug(), $activatedPlugins, true) !== false,
321
+ )
322
+ );
323
+ }
324
+ }
325
+
326
+ return new WP_REST_Response($result, 200);
327
+ }
328
+
329
+ /**
330
+ * Modifies the response to disable caching.
331
+ *
332
+ * @param WP_REST_Response $response The endpoint its response.
333
+ *
334
+ * @return WP_REST_Response
335
+ */
336
+ private function modify_response( $response ) {
337
+ return $response;
338
+ }
339
+
340
+ private function get_ce_checkout( $checkout_uuid ) {
341
+ if ( empty($checkout_uuid) ) {
342
+ return new WP_REST_Response('No uuid provided', 400);
343
+ }
344
+
345
+ $checkout = CreativeMail::get_instance()->get_database_manager()->get_checkout_data( 'user_id,user_email,checkout_contents,checkout_updated,checkout_created,checkout_recovered,checkout_uuid',
346
+ 'checkout_uuid = %s', array( $checkout_uuid ) );
347
+ if ( empty($checkout) ) {
348
+ return new WP_REST_Response($checkout, 404);
349
+ }
350
+
351
+ return new WP_REST_Response($checkout, 200);
352
+ }
353
+
354
+ private function get_wc_keys() {
355
+ $wcKey = CreativeMail::get_instance()->get_api_manager()->get_or_generate_key();
356
+ $key = sha1(OptionsHelper::get_instance_api_key() . OptionsHelper::get_instance_uuid());
357
+ $salt = (string) openssl_random_pseudo_bytes( (int) openssl_cipher_iv_length('aes-256-cbc'));
358
+ $salted = '';
359
+ $dx = '';
360
+ $salted_length = strlen($salted);
361
+
362
+ while ( $salted_length < 48 ) {
363
+ $dx = md5($dx . $key . $salt, true);
364
+ $salted .= $dx;
365
+ $salted_length = strlen($salted);
366
+ }
367
+ $key = substr($salted, 0, 32);
368
+ $iv = substr($salted, 32, 16);
369
+ $cs = (string) openssl_encrypt($wcKey->consumer_secret, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
370
+ $ck = (string) openssl_encrypt($wcKey->consumer_key, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
371
+
372
+ $result = new HashSchema();
373
+ $result->salt = bin2hex($salt);
374
+ $result->secret = base64_encode($cs);
375
+ $result->key = base64_encode($ck);
376
+ $result->version = '1';
377
+
378
+ return new WP_REST_Response($result, 200);
379
+ }
380
+
381
+ /**
382
+ * Registers a route to the WP Rest endpoints for this plugin.
383
+ *
384
+ * @param array $route The route to register.
385
+ */
386
+ private function register_route( array $route ) {
387
+ // Make sure the route is valid.
388
+ $path = $route[ self::ROUTE_PATH ];
389
+ $methods = $route[ self::ROUTE_METHODS ];
390
+ $callback = $route[ self::ROUTE_CALLBACK ];
391
+
392
+ if ( array_key_exists(self::ROUTE_PERMISSION_CALLBACK, $route) ) {
393
+ $permission_callback = $route[ self::ROUTE_PERMISSION_CALLBACK ];
394
+ } elseif ( in_array($path, self::ROUTE_REQUIRES_WP_ADMIN, true) ) {
395
+ $permission_callback = array( $this, 'validate_wp_admin' );
396
+ } else {
397
+ $permission_callback = array( $this, 'validate_api_key' );
398
+ }
399
+
400
+ // Make sure we at least have a path.
401
+ if ( empty($path) ) {
402
+ return;
403
+ }
404
+ // If we don't have a method, assume it is GET.
405
+ if ( empty($methods) ) {
406
+ $methods = 'GET';
407
+ }
408
+
409
+ $arguments = array(
410
+ self::ROUTE_METHODS => $methods,
411
+ self::ROUTE_CALLBACK => $callback,
412
+ self::ROUTE_PERMISSION_CALLBACK => $permission_callback,
413
+ );
414
+
415
+ register_rest_route(self::API_NAMESPACE, $path, $arguments);
416
+ }
417
+
418
+ /**
419
+ * Refreshes the WC REST API key.
420
+ *
421
+ * @param int $user_id WordPress' user ID.
422
+ *
423
+ * @return ApiSchema|object
424
+ *
425
+ * @throws Exception
426
+ *
427
+ * @since 1.1.0
428
+ */
429
+ public function refresh_key( $user_id = null ) {
430
+
431
+ $this->revoke_key();
432
+
433
+ return $this->create_key($user_id);
434
+ }
435
+
436
+
437
+ /**
438
+ * Generates a WC REST API key for Jilt to use.
439
+ *
440
+ * @param int $user_id WordPress' user ID.
441
+ *
442
+ * @return object
443
+ *
444
+ * @throws Exception
445
+ *
446
+ * @since 1.1.0
447
+ */
448
+ public function create_key( $user_id = null ) {
449
+ global $wpdb;
450
+
451
+ // If no user is specified, try the current user or find an eligible admin.
452
+ if ( ! $user_id ) {
453
+ $user_id = get_current_user_id();
454
+ // If the current user can't manage WC, try and get the first admin.
455
+ if ( ! user_can($user_id, 'manage_woocommerce') ) {
456
+ $user_id = null;
457
+ $administrator_ids = get_users(
458
+ array(
459
+ 'role' => 'administrator',
460
+ 'fields' => 'ID',
461
+ )
462
+ );
463
+
464
+ foreach ( $administrator_ids as $administrator_id ) {
465
+ if ( user_can($administrator_id, 'manage_woocommerce') ) {
466
+ $user_id = $administrator_id;
467
+ break;
468
+ }
469
+ }
470
+
471
+ if ( ! $user_id ) {
472
+ throw new Exception('No eligible users could be found');
473
+ }
474
+ }
475
+
476
+ // Otherwise, check the user that's specified.
477
+ } elseif ( ! user_can($user_id, 'manage_woocommerce') ) {
478
+ throw new Exception("User {$user_id} does not have permission");
479
+ }
480
+
481
+ $user = get_userdata($user_id);
482
+
483
+ if ( ! $user ) {
484
+ throw new Exception('Invalid user');
485
+ }
486
+
487
+ $consumer_key = 'ck_' . wc_rand_hash();
488
+ $consumer_secret = 'cs_' . wc_rand_hash();
489
+
490
+ $result = $wpdb->insert(
491
+ $wpdb->prefix . 'woocommerce_api_keys',
492
+ array(
493
+ 'user_id' => $user->ID,
494
+ 'description' => 'CreativeMail',
495
+ 'permissions' => 'read_write',
496
+ 'consumer_key' => wc_api_hash($consumer_key),
497
+ 'consumer_secret' => $consumer_secret,
498
+ 'truncated_key' => substr($consumer_key, -7),
499
+ ),
500
+ array(
501
+ '%d',
502
+ '%s',
503
+ '%s',
504
+ '%s',
505
+ '%s',
506
+ '%s',
507
+ )
508
+ );
509
+
510
+ if ( ! $result ) {
511
+ throw new Exception('The key could not be saved');
512
+ }
513
+
514
+ $key = new ApiSchema();
515
+
516
+ $key->key_id = $wpdb->insert_id;
517
+ $key->user_id = $user->ID;
518
+ $key->consumer_key = $consumer_key;
519
+ $key->consumer_secret = $consumer_secret;
520
+
521
+ // Store the new key ID.
522
+ $this->set_key_id($key->key_id);
523
+ $this->set_consumer_key($consumer_key);
524
+
525
+ return $key;
526
+ }
527
+
528
+
529
+ /**
530
+ * Revokes the configured WC REST API key.
531
+ *
532
+ * @since 1.1.0
533
+ */
534
+ public function revoke_key() {
535
+ global $wpdb;
536
+ $key_id = $this->get_key_id();
537
+
538
+ if ( $key_id ) {
539
+ $wpdb->delete($wpdb->prefix . 'woocommerce_api_keys', array( 'key_id' => $key_id ), array( '%d' ));
540
+ }
541
+
542
+ OptionsHelper::delete_wc_api_key_id();
543
+ OptionsHelper::delete_wc_consumer_key();
544
+ }
545
+
546
+
547
+ /**
548
+ * Gets the configured WC REST API key.
549
+ *
550
+ * @since 1.1.0
551
+ *
552
+ * @return object|null
553
+ */
554
+ public function get_key() {
555
+ global $wpdb;
556
+
557
+ $key = null;
558
+ $id = $this->get_key_id();
559
+
560
+ if ( $id ) {
561
+ $key = $wpdb->get_row(
562
+ $wpdb->prepare(
563
+ "
564
  SELECT key_id, user_id, permissions, consumer_secret
565
  FROM {$wpdb->prefix}woocommerce_api_keys
566
  WHERE key_id = %d
567
  ", $id
568
+ )
569
+ );
570
+
571
+ if ( isset($key) ) {
572
+ $key->consumer_key = $this->get_consumer_key();
573
+ }
574
+ }
575
+
576
+ return $key;
577
+ }
578
+
579
+ /**
580
+ * Gets or generate the configured WC REST API key.
581
+ *
582
+ * @return ApiSchema|object|null
583
+ *
584
+ * @throws Exception
585
+ *
586
+ * @since 1.1.0
587
+ */
588
+ public function get_or_generate_key() {
589
+ $key = $this->get_key();
590
+
591
+ if ( null == $key ) {
592
+ $key = $this->refresh_key();
593
+ }
594
+
595
+ return $key;
596
+ }
597
+
598
+ /**
599
+ * Gets the configured WC REST API key ID.
600
+ *
601
+ * @since 1.1.0
602
+ *
603
+ * @return int
604
+ */
605
+ public function get_key_id() {
606
+ $wc_api_key = OptionsHelper::get_wc_api_key_id();
607
+ return is_int($wc_api_key) ? $wc_api_key : 0;
608
+ }
609
+
610
+ public function get_consumer_key() {
611
+ return OptionsHelper::get_wc_consumer_key();
612
+ }
613
+
614
+ /**
615
+ * Sets a WC REST API key ID.
616
+ *
617
+ * @param int $id Key ID.
618
+ *
619
+ * @since 1.1.0
620
+ */
621
+ public function set_key_id( $id ) {
622
+ OptionsHelper::set_wc_api_key_id($id);
623
+ }
624
+
625
+ public function set_consumer_key( $key ) {
626
+ OptionsHelper::set_wc_consumer_key($key);
627
+ }
628
+
629
+ private function get_managed_email_notifications( $request ) {
630
+ if ( ! CreativeMail::get_instance()->get_integration_manager()->get_permalinks_enabled() ) {
631
+ return $this->modify_response(new WP_REST_Response(array( 'message' => 'Please enable pretty permalinks in the WordPress settings.' ), 400));
632
+ }
633
+
634
+ $result = CreativeMail::get_instance()->get_email_manager()->set_managed_email_notifications(json_decode($request->get_body()));
635
+ return $this->modify_response(new WP_REST_Response($result, 200));
636
+ }
637
+
638
+ private function get_wc_products( $request ) {
639
+ $productData = array();
640
+ $products = array();
641
+ $active_plugins = apply_filters('active_plugins', get_option('active_plugins'));
642
+
643
+ if ( in_array('woocommerce/woocommerce.php', $active_plugins, true) ) {
644
+ $page = 1;
645
+ $limit = 25;
646
+ $pageFromRequest = $request->get_param('page');
647
+ $pageLimitFromRequest = $request->get_param('limit');
648
+
649
+ if ( ! empty($pageFromRequest) && '{page}' != $pageFromRequest ) {
650
+ $page = $pageFromRequest;
651
+ }
652
+ if ( ! empty($pageLimitFromRequest) && '{limit}' != $pageLimitFromRequest ) {
653
+ $limit = $pageLimitFromRequest;
654
+ }
655
+
656
+ $types = array_merge( array_keys( wc_get_product_types() ) );
657
+
658
+ if ( in_array('woocommerce-bookings/woocommerce-bookings.php', $active_plugins, true) ) {
659
+ array_push($types, 'booking');
660
+ }
661
+
662
+ // Get 25 most recent products.
663
+ $products = wc_get_products(
664
+ array(
665
+ 'limit' => $limit,
666
+ 'paginate' => true,
667
+ 'paged' => $page,
668
+ 'type' => $types,
669
+ )
670
+ );
671
+
672
+ if ( ! is_array($products) ) {
673
+ foreach ( $products->products as $product ) {
674
+ array_push($productData, new WCProductModel($product->get_data()));
675
+ }
676
+ }
677
+ }
678
+ $response = new WP_REST_Response($productData, 200);
679
+ if ( ! is_array($products) ) {
680
+ $response->header('X-WP-Total', $products->total);
681
+ $response->header('X-WP-TotalPages', $products->max_num_pages);
682
+ }
683
+ return $this->modify_response($response);
684
+ }
685
+
686
+ private function get_wp_posts( $request ) {
687
+ $page = 1;
688
+ $postData = array();
689
+
690
+ if ( property_exists($request, 'page') ) {
691
+ $page = (int) $request['page'];
692
+ }
693
+
694
+ $posts = get_posts(
695
+ array(
696
+ 'posts_per_page' => 10,
697
+ 'paged' => $page,
698
+ 'post_type' => 'post',
699
+ )
700
+ );
701
+
702
+ foreach ( $posts as $post ) {
703
+ array_push($postData, new BlogPost($post));
704
+ }
705
+
706
+ return $this->modify_response(new WP_REST_Response($postData, 200));
707
+ }
708
+
709
+ private function get_images() {
710
+ $attachmentData = array();
711
+ $attachments = get_posts(
712
+ array(
713
+ 'post_type' => 'attachment',
714
+ 'post_mime_type' => 'image',
715
+ 'post_status' => 'inherit',
716
+ 'posts_per_page' => -1,
717
+ )
718
+ );
719
+
720
+ foreach ( $attachments as $attachment ) {
721
+ array_push($attachmentData, new BlogAttachment($attachment));
722
+ }
723
+
724
+ return $this->modify_response(new WP_REST_Response($attachmentData, 200));
725
+ }
726
+
727
+ private function hide_banner( $request ) {
728
+ $banner = $request->get_param('banner');
729
+ if ( empty($banner) ) {
730
+ return $this->modify_response(new WP_REST_Response('Missing banner param', 400));
731
+ }
732
+
733
+ OptionsHelper::set_hide_banner($banner, true);
734
+ return $this->modify_response(new WP_REST_Response(null, 204));
735
+ }
736
+
737
+ private function get_pages_with_ce_forms() {
738
+ if ( version_compare($GLOBALS['wp_version'], '5.5', '<') ) {
739
+ // This is to prevent CE from making the Gutenberg recommendation when Gutenberg isn't supported.
740
+ return $this->modify_response(
741
+ new WP_REST_Response(
742
+ array(
743
+ array(
744
+ 'page_id' => 1,
745
+ 'post_title' => '',
746
+ 'post_status' => 'published',
747
+ ),
748
+ ),
749
+ 200
750
+ )
751
+ );
752
+ }
753
+
754
+ $blocks = $this->find_pages_by_content_tag('wp:ce4wp/subscribe');
755
+ return $this->modify_response(new WP_REST_Response($blocks, 200));
756
+ }
757
+
758
+ private function check_if_previously_purchased( $request ) {
759
+ $active_plugins = apply_filters('active_plugins', get_option('active_plugins'));
760
+ $exists = false;
761
+
762
+ if ( in_array('woocommerce/woocommerce.php', $active_plugins, true) ) {
763
+ $product_ID = $request->get_param('product');
764
+ $email = $request->get_param('email');
765
+ $daysPassedFloat = 86400 * $request->get_param('daysPassed');
766
+ $daysPassed = round($daysPassedFloat);
767
+
768
+ $currentDay = new DateTime();
769
+ $currentDate = $currentDay->format('Y-m-d H:i:s');
770
+ $currentTime = strtotime($currentDate);
771
+
772
+ $date = new DateTime();
773
+ $date->sub(new DateInterval("PT{$daysPassed}S"));
774
+ $initial_date = $date->format('Y-m-d H:i:s');
775
+ $initialTime = strtotime($initial_date);
776
+
777
+ $order = wc_get_orders( array(
778
+ 'billing_email' => $email,
779
+ 'date_created' => "$initialTime...$currentTime",
780
+ 'status' => array( 'wc-completed' ),
781
+ ));
782
+
783
+ if ( ! empty($product_ID) ) {
784
+ if ( is_array($order) ) {
785
+ $exists = $this->check_if_product_exists_by_product_id($order, $product_ID);
786
+ }
787
+ } else {
788
+ if ( ! empty($order) ) {
789
+ $exists = true;
790
+ }
791
+ }
792
+ }
793
+ return $this->modify_response(new WP_REST_Response($exists, 200));
794
+ }
795
+
796
+ private function check_if_product_exists_by_product_id( array $order, $product_ID ) {
797
+ $exists = false;
798
+
799
+ foreach ( $order as $itemsKey => $item ) {
800
+ $orderData = $item->get_data();
801
+ foreach ( $orderData['line_items'] as $lineItem ) {
802
+ $product = $lineItem->get_product()->get_data();
803
+ foreach ( $product_ID as $p_ID ) {
804
+ if ( $p_ID == $product['id'] ) {
805
+ $exists = true;
806
+ }
807
+ }
808
+ }
809
+ if ( $exists ) {
810
+ break;
811
+ }
812
+ }
813
+ return $exists;
814
+ }
 
 
 
 
 
815
  }
src/Managers/CheckoutManager.php CHANGED
@@ -1,6 +1,5 @@
1
  <?php
2
 
3
-
4
  namespace CreativeMail\Managers;
5
 
6
  use CreativeMail\CreativeMail;
@@ -9,6 +8,9 @@ use CreativeMail\Helpers\OptionsHelper;
9
  use CreativeMail\Models\CartData;
10
  use CreativeMail\Models\Checkout;
11
  use CreativeMail\Models\CheckoutSave;
 
 
 
12
  use CreativeMail\Models\User;
13
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
14
  use CreativeMail\Models\Order;
@@ -17,975 +19,1030 @@ use CreativeMail\Models\RequestItem;
17
  use Exception;
18
  use WC_Coupon;
19
  use WC_Order;
 
20
 
21
  /**
22
  * Class CheckoutManager
23
  *
24
  * @package CreativeMail\Managers
25
  */
26
- class CheckoutManager
27
- {
28
- /**
29
- * Current checkout UUID.
30
- *
31
- * @var string
32
- * @since 1.3.0
33
- */
34
- protected $checkout_uuid = '';
35
- protected $return_to_shop = false;
36
-
37
- const UPDATE_CHECKOUT_DATA = 'update_checkout_data';
38
- const META_CHECKOUT_UUID = 'ce4wp_checkout_uuid';
39
- const META_CHECKOUT_RECOVERED = 'ce4wp_checkout_recovered';
40
- const CHECKOUT_UUID = 'checkout_uuid';
41
- const NONCE = 'nonce';
42
- const EMAIL = 'email';
43
- const CHECKED = 'checked';
44
- const DOMAIN = 'ce4wp';
45
- const BILLING_EMAIL = 'billing_email';
46
- const BILLING_EMAIL_NOTICE = 'billing_email_notice';
47
- const BILLING_EMAIL_NO_CONSENT = 'billing_email_no_consent';
48
- const CHECKOUT_UUID_PARAM = 'checkout_uuid = %s';
49
- const COUPONS = 'coupons';
50
- const SHIPPING_TOTAL = 'shipping_total';
51
- const SHIPPING_TAXES = 'shipping_taxes';
52
- const PRODUCT_ID = 'product_id';
53
- const VARIATION_ID = 'variation_id';
54
- const QUANTITY = 'quantity';
55
- const VARIATION = 'variation';
56
- const USER_EMAIL = 'user_email';
57
- const PRODUCTS = 'products';
58
- const CUSTOMER = 'customer';
59
- const DATETIME_ZERO = "0000-00-00 00:00:00";
60
-
61
- /**
62
- * Add hooks
63
- *
64
- * @since 1.3.0
65
- */
66
- public function add_hooks()
67
- {
68
- // check if woocommerce is active
69
- if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
70
- add_action('woocommerce_before_checkout_form', array($this, 'enqueue_scripts'));
71
- // add checkout notice field
72
- add_filter('woocommerce_form_field_ce4wp_notice', array($this, 'add_email_usage_notice_field'), 10, 4);
73
- add_filter('woocommerce_checkout_fields', array($this, 'ce4wp_filter_checkout_fields'));
74
-
75
- add_action('woocommerce_after_template_part', array($this, 'save_or_clear_checkout_data'), 10, 1);
76
- add_action('woocommerce_add_to_cart', array($this, self::UPDATE_CHECKOUT_DATA));
77
- add_action('woocommerce_cart_item_removed', array($this, self::UPDATE_CHECKOUT_DATA), 30, 0);
78
- add_action('woocommerce_cart_item_restored', array($this, self::UPDATE_CHECKOUT_DATA), 30, 0);
79
- add_action('woocommerce_cart_item_set_quantity', array($this, self::UPDATE_CHECKOUT_DATA), 20, 0);
80
-
81
- add_action('wp_ajax_ce4wp_abandoned_checkouts_capture_guest_checkout', array($this, 'maybe_capture_guest_checkout'));
82
- add_action('wp_ajax_nopriv_ce4wp_abandoned_checkouts_capture_guest_checkout', array($this, 'maybe_capture_guest_checkout'));
83
-
84
- add_action('wp_ajax_ce4wp_abandoned_checkouts_no_consent_checkout', array($this, 'no_consent_checkout'));
85
- add_action('wp_ajax_nopriv_ce4wp_abandoned_checkouts_no_consent_checkout', array($this, 'no_consent_checkout'));
86
-
87
- add_action('woocommerce_checkout_create_order', array($this, 'clear_purchased_data'), 10, 1);
88
- add_action('woocommerce_checkout_order_processed', array($this, 'order_processed'), 10, 1);
89
- add_action('woocommerce_order_status_completed', array($this, 'order_completed'), 10, 1);
90
-
91
- // Sanitize checkout UUID.
92
- $this->checkout_uuid = filter_input(INPUT_GET, 'ce4wp-recover', FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
93
- $this->return_to_shop = filter_input (INPUT_GET, 'ce4wp-return-to-shop', FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
94
-
95
- if (empty($this->checkout_uuid) && empty($this->return_to_shop)) {
96
- return;
97
- }
98
-
99
- if (!empty($this->checkout_uuid)) {
100
- add_action('wp_loaded', array($this, 'recover_checkout'));
101
- }
102
-
103
- if (!empty($this->return_to_shop)) {
104
- add_action('wp_loaded', array($this, 'return_to_shop'));
105
- }
106
- }
107
- }
108
-
109
- /**
110
- * Add custom field under billing_email
111
- *
112
- * @since 1.3.0
113
- */
114
- public function ce4wp_filter_checkout_fields( $fields ) {
115
- $fields['billing'][self::BILLING_EMAIL_NOTICE] = array(
116
- 'type' => 'ce4wp_notice',
117
- 'required' => false,
118
- 'class' => array( 'form-row-wide' ),
119
- 'clear' => true,
120
- 'priority' => $fields['billing']['billing_email']['priority'] + 0.5
121
- );
122
- return $fields;
123
- }
124
-
125
- /**
126
- * Add logic for ce4wp_notice field type
127
- *
128
- * @since 1.3.0
129
- */
130
- public function add_email_usage_notice_field( $field, $key, $args, $value )
131
- {
132
- $field_html = '<label style="font-weight:400;">' . __( 'Your email and cart are saved so we can send you email reminders about this order.', self::DOMAIN ) .' <a href="#" id="ce4wp_no_consent">'. __( 'No thanks', self::DOMAIN ).'</a></label>';
133
-
134
- $container_class = esc_attr( implode( ' ', $args['class'] ) );
135
- $container_id = esc_attr( $args['id'] ) . '_field';
136
-
137
- $after = ! empty( $args['clear'] ) ? '<div class="clear"></div>' : '';
138
-
139
- $field_container = '<p class="form-row %1$s" id="%2$s">%3$s</p>';
140
-
141
- return sprintf( $field_container, $container_class, $container_id, $field_html ) . $after;
142
- }
143
-
144
- /**
145
- * Order has been completed
146
- *
147
- * @param int $order_id The order id.
148
- *
149
- * @since 1.3.0
150
- *
151
- * @return void
152
- */
153
- public function order_completed( $order_id )
154
- {
155
- $this->update_checkout( $order_id, '/v1.0/checkout/order_completed' );
156
- $this->cleanup_old_checkouts( $order_id );
157
- }
158
-
159
- /**
160
- * Order has been created and is processed
161
- *
162
- * @param int $order_id Newly created order id.
163
- *
164
- * @since 1.3.0
165
- *
166
- * @return void
167
- */
168
- public function order_processed( $order_id ) {
169
- $this->update_checkout( $order_id, '/v1.0/checkout/order_created' );
170
- }
171
-
172
- /**
173
- * Cleanup previous checkouts in case old is still marked as abandoned
174
- *
175
- * @param int $order_id Woocommerce order id.
176
- *
177
- * @since 1.3.3
178
- *
179
- * @return void
180
- */
181
- private function cleanup_old_checkouts( $order_id )
182
- {
183
- $order = wc_get_order($order_id);
184
- if ( empty( $order ) ) {
185
- return;
186
- }
187
- try
188
- {
189
- $data = array();
190
- if (! is_bool($order) && is_a( $order, 'WC_Order' )) {
191
- $data = $this->get_checkout_uuid_by_email($order->get_billing_email());
192
- }
193
- foreach ($data as $checkout_data)
194
- {
195
- $endpoint = EnvironmentHelper::get_app_gateway_url( 'wordpress' ) . '/v1.0/checkout/' . $checkout_data->checkout_uuid;
196
- $this->ce4wp_remote_delete($endpoint);
197
- CreativeMail::get_instance()->get_database_manager()->remove_checkout_data($checkout_data->checkout_uuid);
198
- }
199
- }
200
- catch (Exception $e)
201
- {
202
- RaygunManager::get_instance()->exception_handler($e);
203
- }
204
- }
205
-
206
- /**
207
- * Update of checkout data in the external service
208
- *
209
- * @param int $order_id The order id.
210
- * @param string $endpoint Endpoint to call
211
- *
212
- * @since 1.3.0
213
- */
214
- private function update_checkout( $order_id, $endpoint ) {
215
- $requestItem = new Checkout();
216
- $order = wc_get_order( $order_id );
217
-
218
- if ( empty( $order ) ) {
219
- return;
220
- }
221
-
222
- if (! is_bool($order) ) {
223
- // Check if order had checkout uuid.
224
- $uuid = $order->get_meta(self::META_CHECKOUT_UUID, true);
225
- // Check if order is created with checkout meta.
226
- if (empty($uuid)) {
227
- return;
228
- }
229
-
230
- // Try to find recovery date from order metadata.
231
- $recovery_date = $order->get_meta(self::META_CHECKOUT_RECOVERED, true);
232
- // Remote post to CE4WP marking checkout as completed/created.
233
- $requestItem->uuid = $uuid;
234
- $requestItem->order_id = $order->get_id();
235
- $requestItem->order_total = $order->get_total();
236
- $requestItem->order_currency = $order->get_currency();
237
- $requestItem->recovery_date = (empty($recovery_date) || $recovery_date === self::DATETIME_ZERO) ? null : $recovery_date;
238
- }
239
-
240
- $endpoint = EnvironmentHelper::get_app_gateway_url( 'wordpress' ) . $endpoint;
241
- // Call remote endpoint to update.
242
- $this->ce4wp_remote_post( $requestItem, $endpoint );
243
- }
244
-
245
- /**
246
- * Enqueue abandoned cart javascript files
247
- *
248
- * @since 1.3.0
249
- */
250
- public function enqueue_scripts() {
251
- wp_enqueue_script( 'ce4wp-consent-checkout', CE4WP_PLUGIN_URL . 'assets/js/consent_checkout.js', [ 'wp-util' ], CE4WP_PLUGIN_VERSION, false );
252
-
253
- if ( is_user_logged_in() ) {
254
- return;
255
- }
256
-
257
- wp_enqueue_script( 'ce4wp-guest-checkout', CE4WP_PLUGIN_URL . 'assets/js/guest_checkout.js', [ 'wp-util' ], CE4WP_PLUGIN_VERSION, false );
258
- }
259
-
260
- /**
261
- * AJAX handler for attempting to capture guest checkouts.
262
- *
263
- * @since 1.3.0
264
- */
265
- public function maybe_capture_guest_checkout() {
266
- $email = null;
267
- $data = filter_input_array( INPUT_POST, [
268
- self::NONCE => FILTER_SANITIZE_STRING,
269
- self::EMAIL => FILTER_SANITIZE_EMAIL
270
- ] );
271
-
272
- if (!is_bool($data)) {
273
- if ( empty( $data[self::NONCE] ) || ! wp_verify_nonce( $data[self::NONCE], 'woocommerce-process_checkout' ) ) {
274
- wp_send_json_error( esc_html__( 'Invalid nonce.', self::DOMAIN ) );
275
- }
276
- $email = filter_var( $data[self::EMAIL], FILTER_VALIDATE_EMAIL );
277
- }
278
-
279
- if ( ! $email ) {
280
- wp_send_json_error( esc_html__( 'Invalid email.', self::DOMAIN ) );
281
- }
282
-
283
- WC()->session->set( self::BILLING_EMAIL, $email );
284
- $this->save_checkout_data( $email, true);
285
-
286
- wp_send_json_success();
287
- }
288
-
289
- /**
290
- * AJAX handler for opt out on abandoned cart.
291
- *
292
- * @since 1.3.0
293
- */
294
- public function no_consent_checkout()
295
- {
296
- $data = filter_input_array(INPUT_POST, [
297
- self::NONCE => FILTER_SANITIZE_STRING
298
- ]);
299
-
300
- if (!is_bool($data)) {
301
- if (empty($data[self::NONCE]) || !wp_verify_nonce($data[self::NONCE], 'woocommerce-process_checkout')) {
302
- wp_send_json_error(esc_html__('Invalid nonce.', self::DOMAIN));
303
- }
304
- }
305
-
306
- // Save no consent on session.
307
- WC()->session->set( self::BILLING_EMAIL_NO_CONSENT, true);
308
-
309
- $checkout_id = WC()->session->get( self::CHECKOUT_UUID );
310
- if (empty($checkout_id)) {
311
- wp_send_json_success();
312
- }
313
-
314
- $endpoint = EnvironmentHelper::get_app_gateway_url('wordpress') . '/v1.0/checkout/' . (! is_array($checkout_id) ? $checkout_id : '');
315
- $this->ce4wp_remote_delete( $endpoint );
316
- CreativeMail::get_instance()->get_database_manager()->change_checkout_consent( $checkout_id, false );
317
-
318
- wp_send_json_success();
319
- }
320
-
321
- /**
322
- * Either call an update of checkout data which will be saved or remove checkout data based on what template we arrive at.
323
- *
324
- * @param string $template_name Current template file name.
325
- *
326
- * @since 1.3.0
327
- */
328
- public function save_or_clear_checkout_data( $template_name ) {
329
-
330
- // If checkout page displayed, save checkout data.
331
- if ( 'checkout/form-checkout.php' === $template_name ) {
332
- $this->save_checkout_data();
333
- }
334
- }
335
-
336
- /**
337
- * Helper function to update current checkout session data in db.
338
- *
339
- * Used to strip unneeded params from callbacks.
340
- *
341
- * @since 1.3.0
342
- */
343
- public function update_checkout_data() {
344
- $this->save_checkout_data();
345
- }
346
-
347
- /**
348
- * Helper function to retrieve checkout contents based on checkout UUID.
349
- *
350
- * @param string $uuid Checkout UUID.
351
- *
352
- * @since 1.3.0
353
- *
354
- * @return array Checkout contents.
355
- */
356
- private function get_checkout_contents( $uuid ) {
357
- $checkout = CreativeMail::get_instance()->get_database_manager()->get_checkout_data( 'checkout_contents', self::CHECKOUT_UUID_PARAM, [ $uuid ] );
358
-
359
- if ( empty( $checkout ) ) {
360
- return [];
361
- }
362
-
363
- return maybe_unserialize( array_shift( $checkout )->checkout_contents );
364
- }
365
-
366
- /**
367
- * Helper function to retrieve checkout recovery date based on checkout UUID.
368
- *
369
- * @param string $uuid Checkout UUID.
370
- *
371
- * @since 1.3.0
372
- *
373
- * @return string|null Checkout recovery date if exists, else null.
374
- */
375
- private function get_checkout_recovery_date( $uuid ) {
376
- $checkout = CreativeMail::get_instance()->get_database_manager()->get_checkout_data( 'checkout_recovered', self::CHECKOUT_UUID_PARAM, [ $uuid ] );
377
-
378
- return ( empty( $checkout ) ? null : array_shift( $checkout )->checkout_recovered );
379
- }
380
-
381
- /**
382
- * Helper function to retrieve checkout UUID for current user.
383
- *
384
- * @since 1.3.0
385
- *
386
- * @return string Checkout UUID if exists, else empty string.
387
- */
388
- private function get_checkout_uuid_by_user() {
389
- $checkout = CreativeMail::get_instance()->get_database_manager()->get_checkout_data( self::CHECKOUT_UUID, 'user_id = %d', [ get_current_user_id() ] );
390
-
391
- return ( empty( $checkout ) ? '' : array_shift( $checkout )->checkout_uuid );
392
- }
393
-
394
- /**
395
- * Helper function to retrieve checkout UUID for email address.
396
- *
397
- * @since 1.3.3
398
- *
399
- * @return array List of checkout UUIDs if exists, else empty string.
400
- */
401
- private function get_checkout_uuid_by_email($email_address) {
402
- return CreativeMail::get_instance()->get_database_manager()->get_checkout_data( self::CHECKOUT_UUID, 'user_email = %s', [ $email_address ] );
403
- }
404
-
405
- /**
406
- * Save current checkout data to db.
407
- *
408
- * @param string $billing_email Manually set customer billing email if provided.
409
- * @param boolean $is_checkout Manually mark current page as checkout if necessary (e.g., coming from ajax callback).
410
- *
411
- * @since 1.3.0
412
- *
413
- * @return void
414
- */
415
- protected function save_checkout_data( string $billing_email = '', bool $is_checkout = false) {
416
- // Get current user email.
417
- $session_customer = WC()->session->get( self::CUSTOMER );
418
- $session_billing_email = is_array( $session_customer ) && key_exists( self::EMAIL, $session_customer ) ? $session_customer[self::EMAIL] : '';
419
-
420
- if (empty($billing_email)) {
421
- $billing_email = $session_billing_email;
422
- if (empty($billing_email)) {
423
- $billing_email = WC()->checkout()->get_value( self::BILLING_EMAIL );
424
- if (empty($billing_email)) {
425
- $billing_email = WC()->session->get( self::BILLING_EMAIL );
426
- }
427
- }
428
- }
429
- $is_checkout = $is_checkout ?: is_checkout();
430
- $uuid = WC()->session->get( self::CHECKOUT_UUID );
431
-
432
- if ( empty( $billing_email ) ) {
433
- return;
434
- }
435
-
436
- $has_no_consent = (bool) WC()->session->get( self::BILLING_EMAIL_NO_CONSENT );
437
- if ( $has_no_consent === true ) {
438
- return;
439
- }
440
-
441
- // Check for existing checkout session.
442
- if ( ! $uuid ) {
443
- // Only create session if cart is not empty.
444
- // This is to avoid re-creating checkout UUID during checkout process.
445
- if ( $is_checkout && empty( WC()->cart->get_cart() ) ) {
446
- return;
447
- }
448
- // Retrieve existing checkout UUID for registered users only.
449
- if ( is_user_logged_in() ) {
450
- $existing_uuid = $this->get_checkout_uuid_by_user();
451
- }
452
- // Only create session if currently on checkout page or if current user has an existing session saved.
453
- if ( ! $is_checkout && empty( $existing_uuid ) ) {
454
- return;
455
- }
456
-
457
- $uuid = isset( $existing_uuid ) && ! empty( $existing_uuid ) ? $existing_uuid : wp_generate_uuid4();
458
- WC()->session->set( 'checkout_uuid', $uuid );
459
- }
460
-
461
- $current_time = current_time( 'mysql', 1 );
462
- $user_id = get_current_user_id();
463
-
464
- $cart_products = WC()->cart->get_cart();
465
- $cart_coupons = WC()->cart->get_applied_coupons();
466
- $shipping_total = WC()->cart->get_shipping_total();
467
- $shipping_taxes = WC()->cart->get_shipping_taxes();
468
-
469
- $checkout_content = [
470
- self::PRODUCTS => array_values( $cart_products ),
471
- self::COUPONS => $cart_coupons,
472
- self::SHIPPING_TOTAL => $shipping_total,
473
- self::SHIPPING_TAXES => $shipping_taxes
474
- ];
475
-
476
- CreativeMail::get_instance()->get_database_manager()->upsert_checkout( $uuid, $user_id, $billing_email, $checkout_content, $current_time );
477
-
478
- // Remote post to CE4WP create or update cart if email is provided.
479
- $requestItem = new CheckoutSave();
480
- $requestItem->data = wp_json_encode($this->get_cart_data_for_endpoint( $cart_products, $cart_coupons, $shipping_total, $shipping_taxes ) );
481
- $requestItem->uuid = ! is_array($uuid) ? $uuid : '';
482
- $requestItem->user_id = $user_id;
483
- $requestItem->billing_email = $billing_email;
484
- $requestItem->timestamp = (string) strtotime( $current_time );
485
- $endpoint = EnvironmentHelper::get_app_gateway_url( 'wordpress' ) . '/v1.0/checkout/upsert';
486
-
487
- $consent = CreativeMail::get_instance()->get_database_manager()->has_checkout_consent( $uuid );
488
- if ( $consent ) {
489
- $this->ce4wp_remote_post($requestItem, $endpoint);
490
- }
491
- }
492
-
493
- /**
494
- * Get cart object with data for each product and coupon
495
- *
496
- * @since 1.3.0
497
- */
498
- private function get_cart_data_for_endpoint( $cart_products, $cart_coupons, $shipping_total=0.00, $shipping_taxes=array() ) {
499
- $decimal_point = 2;
500
- $data = new CartData();
501
- $data->products = array();
502
- $data->coupons = array();
503
- $data->currency_symbol = get_woocommerce_currency_symbol();
504
- $data->currency = get_woocommerce_currency();
505
- $data->shipping_total = $shipping_total;
506
- $data->shipping_taxes = $shipping_taxes;
507
-
508
- $data->user = new User();
509
- try
510
- {
511
- // Get user first and last name of available.
512
- $current_user = wp_get_current_user();
513
- if ( $current_user->exists() ) {
514
- $data->user->id = $current_user->ID;
515
- $data->user->username = $current_user->user_login;
516
- $data->user->display_name = $current_user->display_name;
517
- $data->user->first_name = $current_user->user_firstname;
518
- $data->user->last_name = $current_user->user_lastname;
519
- $data->user->email = $current_user->user_email;
520
- }
521
-
522
- foreach ( $cart_products as $value )
523
- {
524
- $product = array_key_exists( 'data', $value ) ? $value['data'] : wc_get_product( $value[self::PRODUCT_ID] );
525
- $product_id = $product->get_id();
526
- $product_data = array(
527
- 'images' => array()
528
- );
529
- $attachment_ids = $product->get_gallery_image_ids();
530
- foreach ( $attachment_ids as $attachment_id ) {
531
- $product_data[ 'images' ][] = wp_get_attachment_url( $attachment_id );
532
- }
533
-
534
- $product_data[ "on_sale" ] = $product->is_on_sale();
535
- $product_data[ "sale_price" ] = $product->get_sale_price();
536
- $product_data[ "regular_price" ] = $product->get_regular_price();
537
- $src = wc_placeholder_img_src();
538
- if ( $image_id = $product->get_image_id() ) {
539
- $image_src = wp_get_attachment_image_src( $image_id, 'full' );
540
- list( $src ) = (! is_bool($image_src) ? $image_src : array('') );
541
- }
542
-
543
- $line_subtotal = empty( $value['line_subtotal'] ) ? 0: $value[ 'line_subtotal' ];
544
- $line_subtotal_tax =empty( $value[ 'line_subtotal_tax' ] ) ? 0: $value[ 'line_subtotal_tax' ];
545
- $line_total = empty( $value[ 'line_total' ] ) ? 0: $value[ 'line_total' ];
546
- $line_tax = empty( $value[ 'line_tax' ] ) ? 0: $value[ 'line_tax' ];
547
-
548
- $data->products[] = array(
549
- 'name' => $product->get_name(),
550
- 'product_id' => $product_id,
551
- 'product_image' => $src,
552
- 'product_data' => $product_data,
553
- 'sku' => (!is_bool($product) && !empty($product) ? $product->get_sku() : null),
554
- 'product_url' => get_the_permalink( $product_id ),
555
- 'variation_id' => $value[ self::VARIATION_ID ],
556
- 'subtotal' => wc_format_decimal( $line_subtotal, $decimal_point ),
557
- 'subtotal_tax' => wc_format_decimal( $line_subtotal_tax, $decimal_point ),
558
- 'total' => wc_format_decimal( $line_total, $decimal_point ),
559
- 'total_tax' => wc_format_decimal( $line_tax, $decimal_point ),
560
- 'price' => wc_format_decimal( $line_subtotal, $decimal_point ),
561
- 'quantity' => $value[ self::QUANTITY ]
562
- );
563
- }
564
-
565
- foreach ( $cart_coupons as $coupon_code )
566
- {
567
- $coupon_id = wc_get_coupon_id_by_code( $coupon_code );
568
- if ( $coupon_id )
569
- {
570
- $coupon = new WC_Coupon( $coupon_id );
571
- $data->coupons[] = array(
572
- 'code' => $coupon->get_code(),
573
- 'amount' => $coupon->get_amount(),
574
- 'discount_type' => $coupon->get_discount_type(),
575
- 'description' => $coupon->get_description(),
576
- 'free_shipping' => $coupon->get_free_shipping()
577
- );
578
- }
579
- }
580
- }
581
- catch (Exception $e)
582
- {
583
- RaygunManager::get_instance()->exception_handler( $e );
584
- }
585
-
586
- return $data;
587
- }
588
-
589
- /**
590
- * Remove current checkout session data from db upon successful order submission.
591
- *
592
- * @param WC_Order $order Newly created order object.
593
- *
594
- * @since 1.3.0
595
- *
596
- * @return void
597
- */
598
- public function clear_purchased_data( $order ) {
599
- $checkout_id = WC()->session->get( self::CHECKOUT_UUID );
600
- if ( empty( $checkout_id ) ) {
601
- return;
602
- }
603
-
604
- $order->update_meta_data( self::META_CHECKOUT_UUID, $checkout_id );
605
-
606
- // get the recovery date if recovered
607
- $recovery_date = $this->get_checkout_recovery_date( ! is_array($checkout_id) ? $checkout_id : '' );
608
- if ( !empty( $recovery_date ) && $recovery_date !== self::DATETIME_ZERO )
609
- {
610
- $order->update_meta_data( self::META_CHECKOUT_RECOVERED, $recovery_date );
611
- }
612
- CreativeMail::get_instance()->get_database_manager()->remove_checkout_data( $checkout_id );
613
- WC()->session->__unset( self::CHECKOUT_UUID );
614
- }
615
-
616
- /**
617
- * Recovery saved checkout from UUID.
618
- *
619
- * @since 1.3.0
620
- *
621
- * @return void
622
- */
623
- public function recover_checkout() {
624
-
625
- // Set checkout session UUID.
626
- WC()->session->set( self::CHECKOUT_UUID, $this->checkout_uuid );
627
-
628
- // Clear current checkout contents.
629
- WC()->cart->empty_cart();
630
-
631
- // Get saved checkout contents.
632
- $checkout_contents = $this->get_checkout_contents( $this->checkout_uuid );
633
-
634
- if ( empty( $checkout_contents ) ) {
635
- return;
636
- }
637
-
638
- // Mark checkout as recovered
639
- CreativeMail::get_instance()->get_database_manager()->mark_checkout_recovered( $this->checkout_uuid );
640
-
641
- // Recover saved products.
642
- $this->recover_products( $checkout_contents[ self::PRODUCTS ] );
643
-
644
- // Apply coupons.
645
- foreach ( $checkout_contents[ self::COUPONS ] as $coupon ) {
646
- WC()->cart->apply_coupon( $coupon );
647
- }
648
-
649
- // Maybe recover checkout email.
650
- $this->maybe_recover_checkout_email();
651
-
652
- // Update totals.
653
- WC()->cart->calculate_totals();
654
-
655
- // Redirect to check out page.
656
- wp_safe_redirect( wc_get_page_permalink( 'cart' ) );
657
-
658
- exit();
659
- }
660
-
661
- public function return_to_shop() {
662
- wp_safe_redirect( wc_get_page_permalink( 'shop' ) );
663
-
664
- exit();
665
- }
666
-
667
-
668
- /**
669
- * Recover checkout email address if guest user and no email is set.
670
- *
671
- * @since 1.3.0
672
- *
673
- * @return void
674
- */
675
- protected function maybe_recover_checkout_email() : void {
676
- $checkout_email = CreativeMail::get_instance()->get_database_manager()->get_checkout_data( self::USER_EMAIL, self::CHECKOUT_UUID_PARAM, [ $this->checkout_uuid ] );
677
- $checkout_email = empty( $checkout_email ) ? '' : array_shift( $checkout_email )->user_email;
678
-
679
- if ( is_user_logged_in() || ! empty( WC()->session->get( self::BILLING_EMAIL ) ) || empty( $checkout_email ) ) {
680
- return;
681
- }
682
-
683
- WC()->session->set( self::BILLING_EMAIL, $checkout_email );
684
- WC()->customer->set_billing_email( $checkout_email );
685
- }
686
-
687
- /**
688
- * Recover products from saved checkout data.
689
- *
690
- * @param array $products Array of product data.
691
- *
692
- * @since 1.3.0
693
- */
694
- protected function recover_products( $products ) {
695
- if ( empty( $products ) ) {
696
- return;
697
- }
698
- // Programmatically add each product to cart.
699
- $products_added = [];
700
- foreach ( $products as $product ) {
701
- $added = WC()->cart->add_to_cart(
702
- $product[ self::PRODUCT_ID ],
703
- $product[ self::QUANTITY ],
704
- empty( $product[ self::VARIATION_ID ] ) ? 0 : $product[ self::VARIATION_ID ],
705
- empty( $product[ self::VARIATION ] ) ? array() : $product[ self::VARIATION ]
706
- );
707
- if ( false !== $added ) {
708
- $products_added[ ( empty( $product[ self::VARIATION_ID ] ) ? $product[ self::PRODUCT_ID ] : $product[ self::VARIATION_ID ] ) ] = $product[ self::QUANTITY ];
709
- }
710
- }
711
-
712
- // Add product notices.
713
- if ( 0 < count( $products_added ) ) {
714
- wc_add_to_cart_message( $products_added );
715
- }
716
- if ( count( $products ) > count( $products_added ) ) {
717
- wc_add_notice(
718
- sprintf(
719
- /* translators: %d item count */
720
- _n(
721
- '%d item from your previous order is currently unavailable and could not be added to your cart.',
722
- '%d items from your previous order are currently unavailable and could not be added to your cart.',
723
- ( count( $products ) - count( $products_added ) ),
724
- self::DOMAIN
725
- ),
726
- ( count( $products ) - count( $products_added ) )
727
- ),
728
- 'error'
729
- );
730
- }
731
- }
732
-
733
- private function ce4wp_remote_post( $requestItem, $endpoint ) {
734
- try
735
- {
736
- // Check if abandoned cart email is managed by creative mail.
737
- $enabled = CreativeMail::get_instance()->get_email_manager()->is_email_managed( 'cart_abandoned_ce4wp' );
738
- if( $enabled ) {
739
- wp_remote_post(
740
- $endpoint, array(
741
- 'method' => 'POST',
742
- 'timeout' => 10,
743
- 'headers' => array(
744
- 'x-account-id' => OptionsHelper::get_connected_account_id(),
745
- 'x-api-key' => OptionsHelper::get_instance_api_key(),
746
- 'content-type' => 'application/json'
747
- ),
748
- 'body' => wp_json_encode( $requestItem )
749
- )
750
- );
751
- }
752
- } catch ( Exception $e ) {
753
- RaygunManager::get_instance()->exception_handler( $e );
754
- }
755
- }
756
-
757
- private function ce4wp_remote_delete( $endpoint ) {
758
- try {
759
- wp_remote_request( $endpoint,
760
- array(
761
- 'method' => 'DELETE',
762
- 'headers' => array(
763
- 'x-account-id' => OptionsHelper::get_connected_account_id(),
764
- 'x-api-key' => OptionsHelper::get_instance_api_key()
765
- )
766
- )
767
- );
768
- } catch ( Exception $e ) {
769
- RaygunManager::get_instance()->exception_handler( $e );
770
- }
771
- }
772
-
773
- private function get_opt_action_by( $products_detail ) {
774
- return OptActionBy::Visitor;
775
- }
776
-
777
- private function get_opt_in_checkbox_value( $products_detail ) {
778
- if ( !empty( $products_detail[ "ce4wp_checkout_consent" ] ) ) {
779
- return $products_detail[ "ce4wp_checkout_consent" ][ 0 ]; //this value appears to be in array;
780
- }
781
-
782
- return null;
783
- }
784
-
785
- private function get_opt_in( $products_detail ) {
786
- $checkbox_value = $this->get_opt_in_checkbox_value( $products_detail );
787
- if ( $checkbox_value == true ) {
788
- return true;
789
- }
790
- return null;
791
- }
792
-
793
- private function get_opt_out( $products_detail ) {
794
- $checkbox_value = $this->get_opt_in_checkbox_value( $products_detail );
795
- if ( $checkbox_value == false ) {
796
- return true;
797
- }
798
- return null;
799
- }
800
-
801
- public function add_order_completed_wc_hooks() {
802
- add_action( 'woocommerce_order_status_completed', array( $this, 'order_completed_trigger_wc_hook' ), 10, 1 );
803
- }
804
-
805
- public function order_completed_trigger_wc_hook( $order_id ) {
806
- $order = wc_get_order( $order_id );
807
- if ( empty( $order ) ) {
808
- return;
809
- }
810
- $endpoint = '/v1.0/wc/order_completed';
811
- $decimal_point = 2;
812
- $products_detail = get_post_meta($order_id);
813
- $all_orders = wc_get_orders( array( 'email' => (is_object($order) && is_a($order, 'WC_Order') ? $order->get_billing_email() : '' ) ) );
814
-
815
- // General Info.
816
- $requestItem = new RequestItem();
817
- $order_model = new Order();
818
- $order_billing = new OrderBilling();
819
-
820
- if (! is_bool($order) && is_a( $order, 'WC_Order' )) {
821
- $requestItem->order_id = $order->get_id();
822
- $requestItem->order_number = $order->get_order_number();
823
- $requestItem->date_created = $order->get_date_created();
824
- $requestItem->date_modified = $order->get_date_modified();
825
- $requestItem->date_completed = $order->get_date_completed();
826
- $requestItem->status = $order->get_status();
827
- $requestItem->order_url = $order->get_checkout_order_received_url();
828
- $requestItem->note = $order->get_customer_note();
829
- $requestItem->customer_ip = $order->get_customer_ip_address();
830
- $requestItem->customer_user_agent = $order->get_customer_user_agent();
831
- $requestItem->customer_id = $order->get_user_id();
832
-
833
- // Order Billing.
834
- $order_billing->email = $order->get_billing_email();
835
- $order_billing->opt_action_by = $this->get_opt_action_by( $products_detail );
836
- $order_billing->opt_in = $this->get_opt_in( $products_detail );
837
- $order_billing->opt_out = $this->get_opt_out( $products_detail );
838
-
839
- $order_billing->first_name = $order->get_billing_first_name();
840
- $order_billing->last_name = $order->get_billing_last_name();
841
- $order_billing->is_first_time_buyer = count( is_array($all_orders) ? $all_orders : [''] ) <= 1;
842
- $order_billing->company = $order->get_billing_company();
843
- $order_billing->address_1 = $order->get_billing_address_1();
844
- $order_billing->address_2 = $order->get_billing_address_2();
845
- $order_billing->city = $order->get_billing_city();
846
- $order_billing->state = $order->get_billing_state();
847
- $order_billing->postcode = $order->get_billing_postcode();
848
- $order_billing->country = $order->get_billing_country();
849
- $order_billing->email = $order->get_billing_email();
850
- $order_billing->phone = $order->get_billing_phone();
851
- $order_billing->shipping = array(
852
- 'first_name' => $order->get_shipping_first_name(),
853
- 'last_name' => $order->get_shipping_last_name(),
854
- 'company' => $order->get_shipping_company(),
855
- 'address_1' => $order->get_shipping_address_1(),
856
- 'address_2' => $order->get_shipping_address_2(),
857
- 'city' => $order->get_shipping_city(),
858
- 'state' => $order->get_shipping_state(),
859
- 'postcode' => $order->get_shipping_postcode(),
860
- 'country' => $order->get_shipping_country(),
861
- 'shipping_methods' => $order->get_shipping_method()
862
- );
863
- $order_billing->payment_details = array(
864
- 'method_id' => $order->get_payment_method(),
865
- 'method_title' => $order->get_payment_method_title(),
866
- 'paid' => !is_null($order->get_date_paid()),
867
- );
868
-
869
- // Order Currency and Total Info.
870
- $requestItem->total = wc_format_decimal( $order->get_total(), $decimal_point );
871
- $requestItem->subtotal = wc_format_decimal( $order->get_subtotal(), $decimal_point );
872
- $requestItem->total_tax = wc_format_decimal( $order->get_total_tax(), $decimal_point );
873
- $requestItem->shipping_total = wc_format_decimal( $order->get_shipping_total(), $decimal_point );
874
- $requestItem->cart_tax = (float) wc_format_decimal( $order->get_cart_tax(), $decimal_point );
875
- $requestItem->shipping_tax = wc_format_decimal( $order->get_shipping_tax(), $decimal_point );
876
- $requestItem->discount_total = wc_format_decimal( $order->get_total_discount(), $decimal_point );
877
- $order_model->currency_symbol = get_woocommerce_currency_symbol();
878
- $order_model->currency = $order->get_currency();
879
-
880
- // Order Products Info.
881
- $order_model->total_line_items_quantity = $order->get_item_count();
882
-
883
- // Line Items / Products array for the expected endpoint.
884
- foreach ( $order->get_items() as $itemsKey => $item ) {
885
- // @phpstan-ignore-next-line
886
- $product = $item->get_product();
887
-
888
- if ( empty( $product ) ) {
889
- continue;
890
- }
891
-
892
- $item_meta = $item->get_formatted_meta_data();
893
-
894
- foreach ( $item_meta as $key => $values ) {
895
- $item_meta[ $key ]->label = $values->display_key;
896
- unset( $item_meta[ $key ]->display_key );
897
- unset( $item_meta[ $key ]->display_value );
898
- }
899
-
900
- try {
901
- $product_data = array(
902
- 'images' => array(),
903
- 'downloads' => array()
904
- );
905
- $attachment_ids = $product->get_gallery_image_ids();
906
- foreach ( $attachment_ids as $attachment_id ) {
907
- $product_data[ 'images' ][] = wp_get_attachment_url( $attachment_id );
908
- }
909
-
910
- $product_data[ "on_sale" ] = $product->is_on_sale();
911
- $product_data[ "sale_price" ] = $product->get_sale_price();
912
- $product_data[ "regular_price" ] = $product->get_regular_price();
913
-
914
- if ( $product->is_downloadable() ) {
915
- // @phpstan-ignore-next-line
916
- $item_downloads = $item->get_item_downloads();
917
- foreach ( $item_downloads as $item_download )
918
- {
919
- $product_data[ "downloads" ][] = array(
920
- 'line_item_id' => $item->get_id(),
921
- // @phpstan-ignore-next-line
922
- 'product_id' => $item->get_product_id(),
923
- 'download_url' => $item_download[ "download_url" ],
924
- 'download_file' => $item_download[ "file" ],
925
- 'download_name' => $item_download[ "name" ],
926
- 'download_id' => $item_download[ "id" ],
927
- 'downloads_remaining' => $item_download[ "downloads_remaining" ],
928
- 'download_access_expires' => wc_format_datetime( $item_download[ "access_expires" ], 'U' ),
929
- 'download_limit' => $product->get_download_limit(),
930
- 'download_expiry' => $product->get_download_expiry(),
931
- );
932
- }
933
- }
934
- } catch ( Exception $ex ) {
935
- RaygunManager::get_instance()->exception_handler( $ex );
936
- }
937
-
938
- $src = wc_placeholder_img_src();
939
- if ( $image_id = $product->get_image_id() ) {
940
- $image_src = wp_get_attachment_image_src( $image_id, 'full' );
941
- list( $src ) = is_array($image_src) ? $image_src : array('');
942
- }
943
-
944
- $order_model->line_items[] = array(
945
- // @phpstan-ignore-next-line
946
- 'product_id' => $item->get_product_id(),
947
- 'item_meta' => $item->get_formatted_meta_data(),
948
- 'subtotal' => wc_format_decimal($order->get_line_subtotal( $item, false, false), $decimal_point ),
949
- // @phpstan-ignore-next-line
950
- 'subtotal_tax' => wc_format_decimal( $item->get_subtotal_tax(), $decimal_point ),
951
- 'total' => wc_format_decimal( $order->get_line_total($item, false, false), $decimal_point ),
952
- // @phpstan-ignore-next-line
953
- 'total_tax' => wc_format_decimal( $item->get_total_tax(), $decimal_point ),
954
- 'price' => wc_format_decimal( $order->get_item_total($item, false, false), $decimal_point ),
955
- 'quantity' => $item->get_quantity(),
956
- 'tax_class' => $item->get_tax_class(),
957
- 'name' => $item->get_name(),
958
- 'product_image' => $src,
959
- 'product_data' => $product_data,
960
- 'sku' => is_a($product, 'WC_Product') ? $product->get_sku() : null,
961
- 'meta' => array_values( $item_meta ),
962
- // @phpstan-ignore-next-line
963
- 'product_url' => get_the_permalink( $item->get_product_id() ),
964
- // @phpstan-ignore-next-line
965
- 'variation_id' => $item->get_variation_id()
966
- );
967
- }
968
- }
969
- $order_model->billing = $order_billing;
970
- $requestItem->order = $order_model;
971
-
972
- $endpoint = EnvironmentHelper::get_app_gateway_url( 'wordpress' ) . $endpoint;
973
- try
974
- {
975
- wp_remote_post(
976
- $endpoint, array(
977
- 'method' => 'POST',
978
- 'timeout' => 10,
979
- 'headers' => array(
980
- 'x-account-id' => OptionsHelper::get_connected_account_id(),
981
- 'x-api-key' => OptionsHelper::get_instance_api_key(),
982
- 'content-type' => 'application/json'
983
- ),
984
- 'body' => wp_json_encode( $requestItem )
985
- )
986
- );
987
- } catch ( Exception $e ) {
988
- RaygunManager::get_instance()->exception_handler( $e );
989
- }
990
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
991
  }
1
  <?php
2
 
 
3
  namespace CreativeMail\Managers;
4
 
5
  use CreativeMail\CreativeMail;
8
  use CreativeMail\Models\CartData;
9
  use CreativeMail\Models\Checkout;
10
  use CreativeMail\Models\CheckoutSave;
11
+ use CreativeMail\Models\Coupon;
12
+ use CreativeMail\Models\OrderBillingPaymentDetails;
13
+ use CreativeMail\Models\OrderLineItem;
14
  use CreativeMail\Models\User;
15
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
16
  use CreativeMail\Models\Order;
19
  use Exception;
20
  use WC_Coupon;
21
  use WC_Order;
22
+ use WC_Order_Refund;
23
 
24
  /**
25
  * Class CheckoutManager
26
  *
27
  * @package CreativeMail\Managers
28
  */
29
+ final class CheckoutManager {
30
+
31
+ /**
32
+ * Current checkout UUID.
33
+ *
34
+ * @var string
35
+ * @since 1.3.0
36
+ */
37
+ protected $checkout_uuid = '';
38
+
39
+ /**
40
+ * Check if the checkout needs to return to the shop or not.
41
+ *
42
+ * @var bool
43
+ */
44
+ protected $return_to_shop = false;
45
+
46
+ const UPDATE_CHECKOUT_DATA = 'update_checkout_data';
47
+ const META_CHECKOUT_UUID = 'ce4wp_checkout_uuid';
48
+ const META_CHECKOUT_RECOVERED = 'ce4wp_checkout_recovered';
49
+ const CHECKOUT_UUID = 'checkout_uuid';
50
+ const NONCE = 'nonce';
51
+ const EMAIL = 'email';
52
+ const CHECKED = 'checked';
53
+ const DOMAIN = 'creative-mail-by-constant-contact';
54
+ const BILLING_EMAIL = 'billing_email';
55
+ const BILLING_EMAIL_NOTICE = 'billing_email_notice';
56
+ const BILLING_EMAIL_NO_CONSENT = 'billing_email_no_consent';
57
+ const CHECKOUT_UUID_PARAM = 'checkout_uuid = %s';
58
+ const COUPONS = 'coupons';
59
+ const SHIPPING_TOTAL = 'shipping_total';
60
+ const SHIPPING_TAXES = 'shipping_taxes';
61
+ const PRODUCT_ID = 'product_id';
62
+ const VARIATION_ID = 'variation_id';
63
+ const QUANTITY = 'quantity';
64
+ const VARIATION = 'variation';
65
+ const USER_EMAIL = 'user_email';
66
+ const PRODUCTS = 'products';
67
+ const CUSTOMER = 'customer';
68
+ const DATETIME_ZERO = '0000-00-00 00:00:00';
69
+
70
+ /**
71
+ * Add hooks
72
+ *
73
+ * @since 1.3.0
74
+ */
75
+ public function add_hooks(): void {
76
+ // Check if woocommerce is active.
77
+ if ( in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')), true) ) {
78
+ add_action('woocommerce_before_checkout_form', array( $this, 'enqueue_scripts' ));
79
+ // Add checkout notice field.
80
+ add_filter('woocommerce_form_field_ce4wp_notice', array( $this, 'add_email_usage_notice_field' ), 10, 4);
81
+ add_filter('woocommerce_checkout_fields', array( $this, 'ce4wp_filter_checkout_fields' ));
82
+
83
+ add_action('woocommerce_after_template_part', array( $this, 'save_or_clear_checkout_data' ), 10, 1);
84
+ add_action('woocommerce_add_to_cart', array( $this, self::UPDATE_CHECKOUT_DATA ));
85
+ add_action('woocommerce_cart_item_removed', array( $this, self::UPDATE_CHECKOUT_DATA ), 30, 0);
86
+ add_action('woocommerce_cart_item_restored', array( $this, self::UPDATE_CHECKOUT_DATA ), 30, 0);
87
+ add_action('woocommerce_cart_item_set_quantity', array( $this, self::UPDATE_CHECKOUT_DATA ), 20, 0);
88
+
89
+ add_action('wp_ajax_ce4wp_abandoned_checkouts_capture_guest_checkout', array( $this, 'maybe_capture_guest_checkout' ));
90
+ add_action('wp_ajax_nopriv_ce4wp_abandoned_checkouts_capture_guest_checkout', array( $this, 'maybe_capture_guest_checkout' ));
91
+
92
+ add_action('wp_ajax_ce4wp_abandoned_checkouts_no_consent_checkout', array( $this, 'no_consent_checkout' ));
93
+ add_action('wp_ajax_nopriv_ce4wp_abandoned_checkouts_no_consent_checkout', array( $this, 'no_consent_checkout' ));
94
+
95
+ add_action('woocommerce_checkout_create_order', array( $this, 'clear_purchased_data' ), 10, 1);
96
+ add_action('woocommerce_checkout_order_processed', array( $this, 'order_processed' ), 10, 1);
97
+ add_action('woocommerce_order_status_completed', array( $this, 'order_completed' ), 10, 1);
98
+
99
+ // Sanitize checkout UUID.
100
+ $this->checkout_uuid = filter_input(INPUT_GET, 'ce4wp-recover', FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
101
+ $this->return_to_shop = filter_input (INPUT_GET, 'ce4wp-return-to-shop', FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
102
+
103
+ if ( empty($this->checkout_uuid) && empty($this->return_to_shop) ) {
104
+ return;
105
+ }
106
+
107
+ if ( ! empty($this->checkout_uuid) ) {
108
+ add_action('wp_loaded', array( $this, 'recover_checkout' ));
109
+ }
110
+
111
+ if ( ! empty($this->return_to_shop) ) {
112
+ add_action('wp_loaded', array( $this, 'return_to_shop' ));
113
+ }
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Add custom field under billing_email.
119
+ *
120
+ * @param array $fields Checkout fields.
121
+ *
122
+ * @return array
123
+ *
124
+ * @since 1.3.0
125
+ */
126
+ public function ce4wp_filter_checkout_fields( array $fields ): array {
127
+ $fields['billing'][ self::BILLING_EMAIL_NOTICE ] = array(
128
+ 'type' => 'ce4wp_notice',
129
+ 'required' => false,
130
+ 'class' => array( 'form-row-wide' ),
131
+ 'clear' => true,
132
+ 'priority' => $fields['billing']['billing_email']['priority'] + 0.5,
133
+ );
134
+
135
+ return $fields;
136
+ }
137
+
138
+ /**
139
+ * Add logic for ce4wp_notice field type
140
+ *
141
+ * @param string $field Field name.
142
+ * @param string $key Field key.
143
+ * @param array $args Field arguments.
144
+ * @param string $value Field value.
145
+ *
146
+ * @return string
147
+ *
148
+ * @since 1.3.0
149
+ */
150
+ public function add_email_usage_notice_field( $field, $key, $args, $value ): string {
151
+ $field_html = '<label style="font-weight:400;">' . __( 'Your email and cart are saved so we can send you email reminders about this order.', self::DOMAIN ) . ' <a href="#" id="ce4wp_no_consent">' . __( 'No thanks', self::DOMAIN ) . '</a></label>';
152
+
153
+ $container_class = esc_attr( implode( ' ', $args['class'] ) );
154
+ $container_id = esc_attr( $args['id'] ) . '_field';
155
+
156
+ $after = ! empty( $args['clear'] ) ? '<div class="clear"></div>' : '';
157
+
158
+ $field_container = '<p class="form-row %1$s" id="%2$s">%3$s</p>';
159
+
160
+ return sprintf( $field_container, $container_class, $container_id, $field_html ) . $after;
161
+ }
162
+
163
+ /**
164
+ * Order has been completed
165
+ *
166
+ * @param int $order_id The order id.
167
+ *
168
+ * @return void
169
+ * @since 1.3.0
170
+ */
171
+ public function order_completed( int $order_id ): void {
172
+ $this->update_checkout( $order_id, '/v1.0/checkout/order_completed' );
173
+ $this->cleanup_old_checkouts( $order_id );
174
+ }
175
+
176
+ /**
177
+ * Order has been created and is processed
178
+ *
179
+ * @param int $order_id Newly created order id.
180
+ *
181
+ * @return void
182
+ * @since 1.3.0
183
+ */
184
+ public function order_processed( int $order_id ): void {
185
+ $this->update_checkout( $order_id, '/v1.0/checkout/order_created' );
186
+ }
187
+
188
+ /**
189
+ * Cleanup previous checkouts in case old is still marked as abandoned.
190
+ *
191
+ * @param int $order_id Woocommerce order id.
192
+ *
193
+ * @return void
194
+ * @since 1.3.3
195
+ */
196
+ private function cleanup_old_checkouts( int $order_id ): void {
197
+ $order = wc_get_order($order_id);
198
+
199
+ if ( empty( $order ) ) {
200
+ return;
201
+ }
202
+
203
+ try {
204
+ $data = array();
205
+ if ( ! is_bool($order) && is_a( $order, 'WC_Order' ) ) {
206
+ $data = $this->get_checkout_uuid_by_email($order->get_billing_email());
207
+ }
208
+ foreach ( $data as $checkout_data ) {
209
+ $endpoint = EnvironmentHelper::get_app_gateway_url( 'wordpress/v1.0/checkout/' ) . $checkout_data->checkout_uuid;
210
+ $this->ce4wp_remote_delete($endpoint);
211
+ CreativeMail::get_instance()->get_database_manager()->remove_checkout_data($checkout_data->checkout_uuid);
212
+ }
213
+ } catch ( Exception $e ) {
214
+ RaygunManager::get_instance()->exception_handler($e);
215
+ }
216
+ }
217
+
218
+ /**
219
+ * Update of checkout data in the external service.
220
+ *
221
+ * @param int $order_id The order id.
222
+ * @param string $endpoint Endpoint to call.
223
+ *
224
+ * @since 1.3.0
225
+ */
226
+ private function update_checkout( int $order_id, string $endpoint ): void {
227
+ $requestItem = new Checkout();
228
+ $order = wc_get_order( $order_id );
229
+
230
+ if ( empty( $order ) ) {
231
+ return;
232
+ }
233
+
234
+ if ( ! is_bool($order) ) {
235
+ // Check if order had checkout uuid.
236
+ $uuid = $order->get_meta(self::META_CHECKOUT_UUID, true);
237
+ // Check if order is created with checkout meta.
238
+ if ( empty($uuid) ) {
239
+ return;
240
+ }
241
+
242
+ // Try to find recovery date from order metadata.
243
+ $recovery_date = $order->get_meta(self::META_CHECKOUT_RECOVERED, true);
244
+ // Remote post to CE4WP marking checkout as completed/created.
245
+ $requestItem->uuid = $uuid;
246
+ $requestItem->order_id = $order->get_id();
247
+ $requestItem->order_total = $order->get_total();
248
+ $requestItem->order_currency = $order->get_currency();
249
+ $requestItem->recovery_date = ( empty($recovery_date) || self::DATETIME_ZERO === $recovery_date ) ? null : $recovery_date;
250
+ }
251
+
252
+ $endpoint = EnvironmentHelper::get_app_gateway_url( 'wordpress' ) . $endpoint;
253
+ // Call remote endpoint to update.
254
+ $this->ce4wp_remote_post( $requestItem, $endpoint );
255
+ }
256
+
257
+ /**
258
+ * Enqueue abandoned cart javascript files.
259
+ *
260
+ * @since 1.3.0
261
+ */
262
+ public function enqueue_scripts(): void {
263
+ wp_enqueue_script( 'ce4wp-consent-checkout', CE4WP_PLUGIN_URL . 'assets/js/consent_checkout.js', array( 'wp-util' ), CE4WP_PLUGIN_VERSION, false );
264
+
265
+ if ( is_user_logged_in() ) {
266
+ return;
267
+ }
268
+
269
+ wp_enqueue_script( 'ce4wp-guest-checkout', CE4WP_PLUGIN_URL . 'assets/js/guest_checkout.js', array( 'wp-util' ), CE4WP_PLUGIN_VERSION, false );
270
+ }
271
+
272
+ /**
273
+ * AJAX handler for attempting to capture guest checkouts.
274
+ *
275
+ * @since 1.3.0
276
+ */
277
+ public function maybe_capture_guest_checkout(): void {
278
+ $email = null;
279
+ $data = filter_input_array( INPUT_POST, array(
280
+ self::NONCE => FILTER_SANITIZE_STRING,
281
+ self::EMAIL => FILTER_SANITIZE_EMAIL,
282
+ ) );
283
+
284
+ if ( ! is_bool($data) ) {
285
+ if ( empty( $data[ self::NONCE ] ) || ! wp_verify_nonce( $data[ self::NONCE ], 'woocommerce-process_checkout' ) ) {
286
+ wp_send_json_error( esc_html__( 'Invalid nonce.', self::DOMAIN ) );
287
+ }
288
+ $email = filter_var( $data[ self::EMAIL ], FILTER_VALIDATE_EMAIL );
289
+ }
290
+
291
+ if ( ! $email ) {
292
+ wp_send_json_error( esc_html__( 'Invalid email.', self::DOMAIN ) );
293
+ }
294
+
295
+ WC()->session->set( self::BILLING_EMAIL, $email );
296
+ $this->save_checkout_data( $email, true);
297
+
298
+ wp_send_json_success();
299
+ }
300
+
301
+ /**
302
+ * AJAX handler for opt out on abandoned cart.
303
+ *
304
+ * @since 1.3.0
305
+ */
306
+ public function no_consent_checkout(): void {
307
+ $data = filter_input_array(INPUT_POST, array(
308
+ self::NONCE => FILTER_SANITIZE_STRING,
309
+ ));
310
+
311
+ if ( ! is_bool($data) ) {
312
+ if ( empty($data[ self::NONCE ]) || ! wp_verify_nonce($data[ self::NONCE ], 'woocommerce-process_checkout') ) {
313
+ wp_send_json_error(esc_html__('Invalid nonce.', self::DOMAIN));
314
+ }
315
+ }
316
+
317
+ // Save no consent on session.
318
+ WC()->session->set( self::BILLING_EMAIL_NO_CONSENT, true);
319
+
320
+ $checkout_id = WC()->session->get( self::CHECKOUT_UUID );
321
+ if ( empty($checkout_id) ) {
322
+ wp_send_json_success();
323
+ }
324
+
325
+ $endpoint = EnvironmentHelper::get_app_gateway_url('wordpress/v1.0/checkout/') . ( ! is_array($checkout_id) ? $checkout_id : '' );
326
+ $this->ce4wp_remote_delete( $endpoint );
327
+ CreativeMail::get_instance()->get_database_manager()->change_checkout_consent( $checkout_id, false );
328
+
329
+ wp_send_json_success();
330
+ }
331
+
332
+ /**
333
+ * Either call an update of checkout data which will be saved or remove checkout data based on what template we arrive at.
334
+ *
335
+ * @param string $template_name Current template file name.
336
+ *
337
+ * @since 1.3.0
338
+ */
339
+ public function save_or_clear_checkout_data( string $template_name ): void {
340
+
341
+ // If checkout page displayed, save checkout data.
342
+ if ( 'checkout/form-checkout.php' === $template_name ) {
343
+ $this->save_checkout_data();
344
+ }
345
+ }
346
+
347
+ /**
348
+ * Helper function to update current checkout session data in db.
349
+ *
350
+ * Used to strip unneeded params from callbacks.
351
+ *
352
+ * @since 1.3.0
353
+ */
354
+ public function update_checkout_data(): void {
355
+ $this->save_checkout_data();
356
+ }
357
+
358
+ /**
359
+ * Helper function to retrieve checkout contents based on checkout UUID.
360
+ *
361
+ * @param string $uuid Checkout UUID.
362
+ *
363
+ * @return mixed Checkout contents.
364
+ *
365
+ * @since 1.3.0
366
+ */
367
+ private function get_checkout_contents( string $uuid ) {
368
+ $checkout = CreativeMail::get_instance()->get_database_manager()->get_checkout_data( 'checkout_contents', self::CHECKOUT_UUID_PARAM, array( $uuid ) );
369
+
370
+ if ( empty( $checkout ) ) {
371
+ return array();
372
+ }
373
+
374
+ return maybe_unserialize( array_shift( $checkout )->checkout_contents );
375
+ }
376
+
377
+ /**
378
+ * Helper function to retrieve checkout recovery date based on checkout UUID.
379
+ *
380
+ * @param string $uuid Checkout UUID.
381
+ *
382
+ * @return string|null Checkout recovery date if exists, else null.
383
+ *
384
+ * @since 1.3.0
385
+ */
386
+ private function get_checkout_recovery_date( string $uuid ): ?string {
387
+ $checkout = CreativeMail::get_instance()->get_database_manager()->get_checkout_data( 'checkout_recovered', self::CHECKOUT_UUID_PARAM, array( $uuid ) );
388
+
389
+ return ( empty( $checkout ) ? null : array_shift( $checkout )->checkout_recovered );
390
+ }
391
+
392
+ /**
393
+ * Helper function to retrieve checkout UUID for current user.
394
+ *
395
+ * @since 1.3.0
396
+ *
397
+ * @return string Checkout UUID if exists, else empty string.
398
+ */
399
+ private function get_checkout_uuid_by_user(): string {
400
+ $checkout = CreativeMail::get_instance()->get_database_manager()->get_checkout_data( self::CHECKOUT_UUID, 'user_id = %d', array( get_current_user_id() ) );
401
+ return ( empty( $checkout ) ? '' : array_shift( $checkout )->checkout_uuid );
402
+ }
403
+
404
+ /**
405
+ * Helper function to retrieve checkout UUID for email address.
406
+ *
407
+ * @param ?string $email_address Email address to retrieve checkout UUID for.
408
+ *
409
+ * @since 1.3.3
410
+ *
411
+ * @return array List of checkout UUIDs if exists, else empty string.
412
+ */
413
+ private function get_checkout_uuid_by_email( $email_address ): array {
414
+ return CreativeMail::get_instance()->get_database_manager()->get_checkout_data( self::CHECKOUT_UUID, 'user_email = %s', array( $email_address ) );
415
+ }
416
+
417
+ /**
418
+ * Save current checkout data to db.
419
+ *
420
+ * @param string $billing_email Manually set customer billing email if provided.
421
+ * @param boolean $is_checkout Manually mark current page as checkout if necessary (e.g., coming from ajax callback).
422
+ *
423
+ * @since 1.3.0
424
+ *
425
+ * @return void
426
+ */
427
+ protected function save_checkout_data( string $billing_email = '', bool $is_checkout = false ): void {
428
+ // Get current user email.
429
+ $session_customer = WC()->session->get( self::CUSTOMER );
430
+ $session_billing_email = is_array( $session_customer ) && key_exists( self::EMAIL, $session_customer ) ? $session_customer[ self::EMAIL ] : '';
431
+
432
+ if ( empty($billing_email) ) {
433
+ $billing_email = $session_billing_email;
434
+ if ( empty($billing_email) ) {
435
+ $billing_email = WC()->checkout()->get_value( self::BILLING_EMAIL );
436
+ if ( empty($billing_email) ) {
437
+ $billing_email = WC()->session->get( self::BILLING_EMAIL );
438
+ }
439
+ }
440
+ }
441
+
442
+ if ( ! $is_checkout ) {
443
+ $is_checkout = is_checkout();
444
+ }
445
+
446
+ $uuid = WC()->session->get( self::CHECKOUT_UUID );
447
+
448
+ if ( empty( $billing_email ) ) {
449
+ return;
450
+ }
451
+
452
+ $has_no_consent = (bool) WC()->session->get( self::BILLING_EMAIL_NO_CONSENT );
453
+
454
+ if ( true === $has_no_consent ) {
455
+ return;
456
+ }
457
+
458
+ // Check for existing checkout session.
459
+ if ( ! $uuid ) {
460
+ // Only create session if cart is not empty.
461
+ // This is to avoid re-creating checkout UUID during checkout process.
462
+ if ( $is_checkout && empty( WC()->cart->get_cart() ) ) {
463
+ return;
464
+ }
465
+ // Retrieve existing checkout UUID for registered users only.
466
+ if ( is_user_logged_in() ) {
467
+ $existing_uuid = $this->get_checkout_uuid_by_user();
468
+ }
469
+ // Only create session if currently on checkout page or if current user has an existing session saved.
470
+ if ( ! $is_checkout && empty( $existing_uuid ) ) {
471
+ return;
472
+ }
473
+
474
+ $uuid = isset( $existing_uuid ) && ! empty( $existing_uuid ) ? $existing_uuid : wp_generate_uuid4();
475
+ WC()->session->set( 'checkout_uuid', $uuid );
476
+ }
477
+
478
+ $current_time = current_time( 'mysql', 1 );
479
+ $user_id = get_current_user_id();
480
+
481
+ $cart_products = WC()->cart->get_cart();
482
+ $cart_coupons = WC()->cart->get_applied_coupons();
483
+ $shipping_total = WC()->cart->get_shipping_total();
484
+ $shipping_taxes = WC()->cart->get_shipping_taxes();
485
+
486
+ $checkout_content = array(
487
+ self::PRODUCTS => array_values( $cart_products ),
488
+ self::COUPONS => $cart_coupons,
489
+ self::SHIPPING_TOTAL => $shipping_total,
490
+ self::SHIPPING_TAXES => $shipping_taxes,
491
+ );
492
+
493
+ CreativeMail::get_instance()->get_database_manager()->upsert_checkout( $uuid, $user_id, $billing_email, $checkout_content, $current_time );
494
+
495
+ // Remote post to CE4WP create or update cart if email is provided.
496
+ $requestItem = new CheckoutSave();
497
+ $requestItem->data = wp_json_encode($this->get_cart_data_for_endpoint( $cart_products, $cart_coupons, $shipping_total, $shipping_taxes ) );
498
+ $requestItem->uuid = ! is_array($uuid) ? $uuid : '';
499
+ $requestItem->user_id = $user_id;
500
+ $requestItem->billing_email = $billing_email;
501
+ $requestItem->timestamp = (string) strtotime( $current_time );
502
+ $endpoint = EnvironmentHelper::get_app_gateway_url( 'wordpress/v1.0/checkout/upsert' );
503
+
504
+ $consent = CreativeMail::get_instance()->get_database_manager()->has_checkout_consent( $uuid );
505
+ if ( $consent ) {
506
+ $this->ce4wp_remote_post($requestItem, $endpoint);
507
+ }
508
+ }
509
+
510
+ /**
511
+ * Get cart object with data for each product and coupon.
512
+ *
513
+ * @param array<array<string,mixed>> $cart_products List of cart products.
514
+ * @param array<string> $cart_coupons List of cart coupons.
515
+ * @param float $shipping_total Shipping total.
516
+ * @param array $shipping_taxes Shipping taxes.
517
+ *
518
+ * @return CartData
519
+ *
520
+ * @since 1.3.0
521
+ */
522
+ private function get_cart_data_for_endpoint(
523
+ array $cart_products,
524
+ array $cart_coupons,
525
+ float $shipping_total = 0.00,
526
+ array $shipping_taxes = array()
527
+ ): CartData {
528
+ $decimal_point = 2;
529
+ $data = new CartData();
530
+ $data->products = array();
531
+ $data->coupons = array();
532
+ $data->currency_symbol = get_woocommerce_currency_symbol();
533
+ $data->currency = get_woocommerce_currency();
534
+ $data->shipping_total = $shipping_total;
535
+ $data->shipping_taxes = $shipping_taxes;
536
+ $data->user = new User();
537
+
538
+ try {
539
+ // Get user first and last name of available.
540
+ $current_user = wp_get_current_user();
541
+ if ( $current_user->exists() ) {
542
+ $data->user->id = $current_user->ID;
543
+ $data->user->username = $current_user->user_login;
544
+ $data->user->display_name = $current_user->display_name;
545
+ $data->user->first_name = $current_user->user_firstname;
546
+ $data->user->last_name = $current_user->user_lastname;
547
+ $data->user->email = $current_user->user_email;
548
+ }
549
+
550
+ foreach ( $cart_products as $value ) {
551
+ $product = array_key_exists( 'data', $value ) ? $value['data'] : wc_get_product( $value[ self::PRODUCT_ID ] );
552
+ $product_id = $product->get_id();
553
+ $product_data = array(
554
+ 'images' => array(),
555
+ );
556
+ $attachment_ids = $product->get_gallery_image_ids();
557
+ foreach ( $attachment_ids as $attachment_id ) {
558
+ $product_data['images'][] = wp_get_attachment_url( $attachment_id );
559
+ }
560
+
561
+ $product_data['on_sale'] = $product->is_on_sale();
562
+ $product_data['sale_price'] = $product->get_sale_price();
563
+ $product_data['regular_price'] = $product->get_regular_price();
564
+ $src = wc_placeholder_img_src();
565
+ $image_id = $product->get_image_id();
566
+
567
+ if ( $image_id ) {
568
+ $image_src = wp_get_attachment_image_src( $image_id, 'full' );
569
+ list( $src ) = ( ! is_bool($image_src) ? $image_src : array( '' ) );
570
+ }
571
+
572
+ $line_subtotal = empty( $value['line_subtotal'] ) ? 0 : $value['line_subtotal'];
573
+ $line_subtotal_tax = empty( $value['line_subtotal_tax'] ) ? 0 : $value['line_subtotal_tax'];
574
+ $line_total = empty( $value['line_total'] ) ? 0 : $value['line_total'];
575
+ $line_tax = empty( $value['line_tax'] ) ? 0 : $value['line_tax'];
576
+
577
+ $data->products[] = array(
578
+ 'name' => $product->get_name(),
579
+ 'product_id' => $product_id,
580
+ 'product_image' => $src,
581
+ 'product_data' => $product_data,
582
+ 'sku' => ( ! is_bool($product) && ! empty($product) ? $product->get_sku() : null ),
583
+ 'product_url' => get_the_permalink( $product_id ),
584
+ 'variation_id' => $value[ self::VARIATION_ID ],
585
+ 'subtotal' => wc_format_decimal( $line_subtotal, $decimal_point ),
586
+ 'subtotal_tax' => wc_format_decimal( $line_subtotal_tax, $decimal_point ),
587
+ 'total' => wc_format_decimal( $line_total, $decimal_point ),
588
+ 'total_tax' => wc_format_decimal( $line_tax, $decimal_point ),
589
+ 'price' => wc_format_decimal( $line_subtotal, $decimal_point ),
590
+ 'quantity' => $value[ self::QUANTITY ],
591
+ );
592
+ }
593
+
594
+ foreach ( $cart_coupons as $coupon_code ) {
595
+ $coupon_id = wc_get_coupon_id_by_code( $coupon_code );
596
+ if ( $coupon_id ) {
597
+ $wooCommerceCoupon = new WC_Coupon( $coupon_id );
598
+ $data->coupons[] = array(
599
+ new Coupon(
600
+ $wooCommerceCoupon->get_code(),
601
+ $wooCommerceCoupon->get_amount(),
602
+ $wooCommerceCoupon->get_discount_type(),
603
+ $wooCommerceCoupon->get_description(),
604
+ $wooCommerceCoupon->get_free_shipping()
605
+ ),
606
+ );
607
+ }
608
+ }
609
+ } catch ( Exception $e ) {
610
+ RaygunManager::get_instance()->exception_handler( $e );
611
+ }
612
+
613
+ return $data;
614
+ }
615
+
616
+ /**
617
+ * Remove current checkout session data from db upon successful order submission.
618
+ *
619
+ * @param WC_Order $order Newly created order object.
620
+ *
621
+ * @return void
622
+ *
623
+ * @since 1.3.0
624
+ */
625
+ public function clear_purchased_data( WC_Order $order ): void {
626
+ $checkout_id = WC()->session->get( self::CHECKOUT_UUID );
627
+
628
+ if ( empty( $checkout_id ) ) {
629
+ return;
630
+ }
631
+
632
+ $order->update_meta_data( self::META_CHECKOUT_UUID, $checkout_id );
633
+
634
+ // Get the recovery date if recovered.
635
+ $recovery_date = $this->get_checkout_recovery_date( ! is_array($checkout_id) ? $checkout_id : '' );
636
+
637
+ if ( ! empty( $recovery_date ) && self::DATETIME_ZERO !== $recovery_date ) {
638
+ $order->update_meta_data( self::META_CHECKOUT_RECOVERED, $recovery_date );
639
+ }
640
+
641
+ CreativeMail::get_instance()->get_database_manager()->remove_checkout_data( $checkout_id );
642
+ WC()->session->__unset( self::CHECKOUT_UUID );
643
+ }
644
+
645
+ /**
646
+ * Recovery saved checkout from UUID.
647
+ *
648
+ * @since 1.3.0
649
+ *
650
+ * @return void
651
+ */
652
+ public function recover_checkout(): void {
653
+ // Set checkout session UUID.
654
+ WC()->session->set( self::CHECKOUT_UUID, $this->checkout_uuid );
655
+ // Clear current checkout contents.
656
+ WC()->cart->empty_cart();
657
+ // Get saved checkout contents.
658
+ $checkout_contents = $this->get_checkout_contents( $this->checkout_uuid );
659
+
660
+ if ( empty( $checkout_contents ) ) {
661
+ return;
662
+ }
663
+
664
+ // Mark checkout as recovered.
665
+ CreativeMail::get_instance()->get_database_manager()->mark_checkout_recovered( $this->checkout_uuid );
666
+ // Recover saved products.
667
+ $this->recover_products( $checkout_contents[ self::PRODUCTS ] );
668
+ // Apply coupons.
669
+ foreach ( $checkout_contents[ self::COUPONS ] as $coupon ) {
670
+ WC()->cart->apply_coupon( $coupon );
671
+ }
672
+ // Maybe recover checkout email.
673
+ $this->maybe_recover_checkout_email();
674
+ // Update totals.
675
+ WC()->cart->calculate_totals();
676
+ // Redirect to check out page.
677
+ wp_safe_redirect( wc_get_page_permalink( 'cart' ) );
678
+
679
+ exit();
680
+ }
681
+
682
+ public function return_to_shop(): void {
683
+ wp_safe_redirect( wc_get_page_permalink( 'shop' ) );
684
+ exit();
685
+ }
686
+
687
+
688
+ /**
689
+ * Recover checkout email address if guest user and no email is set.
690
+ *
691
+ * @since 1.3.0
692
+ *
693
+ * @return void
694
+ */
695
+ protected function maybe_recover_checkout_email() : void {
696
+ $checkout_email = CreativeMail::get_instance()->get_database_manager()->get_checkout_data( self::USER_EMAIL, self::CHECKOUT_UUID_PARAM, array( $this->checkout_uuid ) );
697
+ $checkout_email = empty( $checkout_email ) ? '' : array_shift( $checkout_email )->user_email;
698
+
699
+ if ( is_user_logged_in() || ! empty( WC()->session->get( self::BILLING_EMAIL ) ) || empty( $checkout_email ) ) {
700
+ return;
701
+ }
702
+
703
+ WC()->session->set( self::BILLING_EMAIL, $checkout_email );
704
+ WC()->customer->set_billing_email( $checkout_email );
705
+ }
706
+
707
+ /**
708
+ * Recover products from saved checkout data.
709
+ *
710
+ * @param array $products Array of product data.
711
+ *
712
+ * @throws Exception
713
+ *
714
+ * @since 1.3.0
715
+ */
716
+ protected function recover_products( array $products ) {
717
+ if ( empty( $products ) ) {
718
+ return;
719
+ }
720
+
721
+ // Programmatically add each product to cart.
722
+ $products_added = array();
723
+ foreach ( $products as $product ) {
724
+ $added = WC()->cart->add_to_cart(
725
+ $product[ self::PRODUCT_ID ],
726
+ $product[ self::QUANTITY ],
727
+ empty( $product[ self::VARIATION_ID ] ) ? 0 : $product[ self::VARIATION_ID ],
728
+ empty( $product[ self::VARIATION ] ) ? array() : $product[ self::VARIATION ]
729
+ );
730
+ if ( false !== $added ) {
731
+ $products_added[ ( empty( $product[ self::VARIATION_ID ] ) ? $product[ self::PRODUCT_ID ] : $product[ self::VARIATION_ID ] ) ] = $product[ self::QUANTITY ];
732
+ }
733
+ }
734
+
735
+ // Add product notices.
736
+ if ( 0 < count( $products_added ) ) {
737
+ wc_add_to_cart_message( $products_added );
738
+ }
739
+ if ( count( $products ) > count( $products_added ) ) {
740
+ wc_add_notice(
741
+ sprintf(
742
+ /* translators: %d item count */
743
+ _n(
744
+ '%d item from your previous order is currently unavailable and could not be added to your cart.',
745
+ '%d items from your previous order are currently unavailable and could not be added to your cart.',
746
+ ( count( $products ) - count( $products_added ) ),
747
+ self::DOMAIN
748
+ ),
749
+ ( count( $products ) - count( $products_added ) )
750
+ ),
751
+ 'error'
752
+ );
753
+ }
754
+ }
755
+
756
+ /**
757
+ * Sends the remote request to the Creative Mail API.
758
+ *
759
+ * @param object $requestItem The request item.
760
+ * @param string $endpoint The endpoint.
761
+ *
762
+ * @return void
763
+ */
764
+ private function ce4wp_remote_post( object $requestItem, string $endpoint ): void {
765
+ try {
766
+ // Check if abandoned cart email is managed by creative mail.
767
+ $enabled = CreativeMail::get_instance()->get_email_manager()->is_email_managed( 'cart_abandoned_ce4wp' );
768
+ if ( $enabled ) {
769
+ wp_remote_post(
770
+ $endpoint, array(
771
+ 'method' => 'POST',
772
+ 'timeout' => 10,
773
+ 'headers' => array(
774
+ 'x-account-id' => OptionsHelper::get_connected_account_id(),
775
+ 'x-api-key' => OptionsHelper::get_instance_api_key(),
776
+ 'content-type' => 'application/json',
777
+ ),
778
+ 'body' => wp_json_encode( $requestItem ),
779
+ )
780
+ );
781
+ }
782
+ } catch ( Exception $e ) {
783
+ RaygunManager::get_instance()->exception_handler( $e );
784
+ }
785
+ }
786
+
787
+ /**
788
+ * Endpoint to delete specific abandoned cart.
789
+ *
790
+ * @param string $endpoint The endpoint.
791
+ *
792
+ * @return void
793
+ */
794
+ private function ce4wp_remote_delete( string $endpoint ): void {
795
+ try {
796
+ wp_remote_request( $endpoint,
797
+ array(
798
+ 'method' => 'DELETE',
799
+ 'headers' => array(
800
+ 'x-account-id' => OptionsHelper::get_connected_account_id(),
801
+ 'x-api-key' => OptionsHelper::get_instance_api_key(),
802
+ ),
803
+ )
804
+ );
805
+ } catch ( Exception $e ) {
806
+ RaygunManager::get_instance()->exception_handler( $e );
807
+ }
808
+ }
809
+
810
+ /**
811
+ * Get the OptActionBy value
812
+ *
813
+ * @param mixed $products_detail The products detail.
814
+ *
815
+ * @return int
816
+ */
817
+ private function get_opt_action_by( $products_detail ) {
818
+ return OptActionBy::VISITOR;
819
+ }
820
+
821
+ /**
822
+ * Get the OptActionIn value from checkbox
823
+ *
824
+ * @param array $products_detail The products detail.
825
+ *
826
+ * @return mixed|null
827
+ */
828
+ private function get_opt_in_checkbox_value( array $products_detail ) {
829
+ if ( ! empty( $products_detail['ce4wp_checkout_consent'] ) ) {
830
+ // This value appears to be in array.
831
+ return $products_detail['ce4wp_checkout_consent'][0];
832
+ }
833
+
834
+ return null;
835
+ }
836
+
837
+ /**
838
+ * Returns the OptActionIn value.
839
+ *
840
+ * @param array $products_detail The products detail.
841
+ *
842
+ * @return bool|null
843
+ */
844
+ private function get_opt_in( $products_detail ) {
845
+ $checkbox_value = $this->get_opt_in_checkbox_value( $products_detail );
846
+
847
+ if ( $checkbox_value ) {
848
+ return true;
849
+ }
850
+
851
+ return null;
852
+ }
853
+
854
+ private function get_opt_out( $products_detail ) {
855
+ $checkbox_value = $this->get_opt_in_checkbox_value( $products_detail );
856
+
857
+ if ( ! $checkbox_value ) {
858
+ return true;
859
+ }
860
+ return null;
861
+ }
862
+
863
+ public function add_order_completed_wc_hooks(): void {
864
+ add_action( 'woocommerce_order_status_completed', array( $this, 'order_completed_trigger_wc_hook' ), 10, 1 );
865
+ }
866
+
867
+ /**
868
+ * Hook to trigger the WC Order Completed event and send the requested data to CE.
869
+ *
870
+ * @param bool|WC_Order|WC_Order_Refund $order_id The order id or instance.
871
+ *
872
+ * @return void
873
+ */
874
+ public function order_completed_trigger_wc_hook( $order_id ): void {
875
+ $order = wc_get_order( $order_id );
876
+
877
+ if ( empty( $order ) ) {
878
+ return;
879
+ }
880
+
881
+ $endpoint = '/v1.0/wc/order_completed';
882
+ $decimal_point = 2;
883
+ $products_detail = get_post_meta($order_id);
884
+ $all_orders = wc_get_orders( array( 'email' => ( is_object($order) && is_a($order, 'WC_Order') ? $order->get_billing_email() : '' ) ) );
885
+
886
+ // General Info.
887
+ $requestItem = new RequestItem();
888
+ $order_model = new Order();
889
+ $order_billing = new OrderBilling();
890
+
891
+ if ( ! is_bool($order) && is_a( $order, 'WC_Order' ) ) {
892
+ $requestItem->order_id = $order->get_id();
893
+ $requestItem->order_number = $order->get_order_number();
894
+ $requestItem->date_created = $order->get_date_created();
895
+ $requestItem->date_modified = $order->get_date_modified();
896
+ $requestItem->date_completed = $order->get_date_completed();
897
+ $requestItem->status = $order->get_status();
898
+ $requestItem->order_url = $order->get_checkout_order_received_url();
899
+ $requestItem->note = $order->get_customer_note();
900
+ $requestItem->customer_ip = $order->get_customer_ip_address();
901
+ $requestItem->customer_user_agent = $order->get_customer_user_agent();
902
+ $requestItem->customer_id = $order->get_user_id();
903
+
904
+ // Order Billing.
905
+ $order_billing->email = $order->get_billing_email();
906
+ $order_billing->opt_action_by = $this->get_opt_action_by( $products_detail );
907
+ $order_billing->opt_in = $this->get_opt_in( $products_detail );
908
+ $order_billing->opt_out = $this->get_opt_out( $products_detail );
909
+
910
+ $order_billing->first_name = $order->get_billing_first_name();
911
+ $order_billing->last_name = $order->get_billing_last_name();
912
+ $order_billing->is_first_time_buyer = count( is_array($all_orders) ? $all_orders : array( '' ) ) <= 1;
913
+ $order_billing->company = $order->get_billing_company();
914
+ $order_billing->address_1 = $order->get_billing_address_1();
915
+ $order_billing->address_2 = $order->get_billing_address_2();
916
+ $order_billing->city = $order->get_billing_city();
917
+ $order_billing->state = $order->get_billing_state();
918
+ $order_billing->postcode = $order->get_billing_postcode();
919
+ $order_billing->country = $order->get_billing_country();
920
+ $order_billing->email = $order->get_billing_email();
921
+ $order_billing->phone = $order->get_billing_phone();
922
+ $order_billing->shipping = array(
923
+ 'first_name' => $order->get_shipping_first_name(),
924
+ 'last_name' => $order->get_shipping_last_name(),
925
+ 'company' => $order->get_shipping_company(),
926
+ 'address_1' => $order->get_shipping_address_1(),
927
+ 'address_2' => $order->get_shipping_address_2(),
928
+ 'city' => $order->get_shipping_city(),
929
+ 'state' => $order->get_shipping_state(),
930
+ 'postcode' => $order->get_shipping_postcode(),
931
+ 'country' => $order->get_shipping_country(),
932
+ 'shipping_methods' => $order->get_shipping_method(),
933
+ );
934
+ $order_billing->payment_details = new OrderBillingPaymentDetails(
935
+ $order->get_payment_method(),
936
+ $order->get_payment_method_title(),
937
+ ! is_null($order->get_date_paid())
938
+ );
939
+
940
+ // Order Currency and Total Info.
941
+ $requestItem->total = wc_format_decimal( $order->get_total(), $decimal_point );
942
+ $requestItem->subtotal = wc_format_decimal( $order->get_subtotal(), $decimal_point );
943
+ $requestItem->total_tax = wc_format_decimal( $order->get_total_tax(), $decimal_point );
944
+ $requestItem->shipping_total = wc_format_decimal( $order->get_shipping_total(), $decimal_point );
945
+ $requestItem->cart_tax = (float) wc_format_decimal( $order->get_cart_tax(), $decimal_point );
946
+ $requestItem->shipping_tax = wc_format_decimal( $order->get_shipping_tax(), $decimal_point );
947
+ $requestItem->discount_total = wc_format_decimal( $order->get_total_discount(), $decimal_point );
948
+ $order_model->currency_symbol = get_woocommerce_currency_symbol();
949
+ $order_model->currency = $order->get_currency();
950
+
951
+ // Order Products Info.
952
+ $order_model->total_line_items_quantity = $order->get_item_count();
953
+
954
+ // Line Items / Products array for the expected endpoint.
955
+ foreach ( $order->get_items() as $itemsKey => $item ) {
956
+ // @phpstan-ignore-next-line
957
+ $product = $item->get_product();
958
+
959
+ if ( empty( $product ) ) {
960
+ continue;
961
+ }
962
+
963
+ $item_meta = $item->get_formatted_meta_data();
964
+
965
+ foreach ( $item_meta as $key => $values ) {
966
+ $item_meta[ $key ]->label = $values->display_key;
967
+ unset( $item_meta[ $key ]->display_key );
968
+ unset( $item_meta[ $key ]->display_value );
969
+ }
970
+
971
+ try {
972
+ $product_data = array(
973
+ 'images' => array(),
974
+ 'downloads' => array(),
975
+ );
976
+ $attachment_ids = $product->get_gallery_image_ids();
977
+ foreach ( $attachment_ids as $attachment_id ) {
978
+ $product_data['images'][] = wp_get_attachment_url( $attachment_id );
979
+ }
980
+
981
+ $product_data['on_sale'] = $product->is_on_sale();
982
+ $product_data['sale_price'] = $product->get_sale_price();
983
+ $product_data['regular_price'] = $product->get_regular_price();
984
+
985
+ if ( $product->is_downloadable() ) {
986
+ // @phpstan-ignore-next-line
987
+ $item_downloads = $item->get_item_downloads();
988
+ foreach ( $item_downloads as $item_download ) {
989
+ $product_data['downloads'][] = array(
990
+ 'line_item_id' => $item->get_id(),
991
+ // @phpstan-ignore-next-line
992
+ 'product_id' => $item->get_product_id(),
993
+ 'download_url' => $item_download['download_url'],
994
+ 'download_file' => $item_download['file'],
995
+ 'download_name' => $item_download['name'],
996
+ 'download_id' => $item_download['id'],
997
+ 'downloads_remaining' => $item_download['downloads_remaining'],
998
+ 'download_access_expires' => wc_format_datetime( $item_download['access_expires'], 'U' ),
999
+ 'download_limit' => $product->get_download_limit(),
1000
+ 'download_expiry' => $product->get_download_expiry(),
1001
+ );
1002
+ }
1003
+ }
1004
+ } catch ( Exception $ex ) {
1005
+ RaygunManager::get_instance()->exception_handler( $ex );
1006
+ }
1007
+
1008
+ $src = wc_placeholder_img_src();
1009
+ $image_id = $product->get_image_id();
1010
+
1011
+ if ( $image_id ) {
1012
+ $image_src = wp_get_attachment_image_src( $image_id, 'full' );
1013
+ list( $src ) = is_array($image_src) ? $image_src : array( '' );
1014
+ }
1015
+
1016
+ $order_model->line_items[] = new OrderLineItem(
1017
+ $item,
1018
+ $decimal_point,
1019
+ $order,
1020
+ $item_meta,
1021
+ $src,
1022
+ $product_data,
1023
+ $product
1024
+ );
1025
+ }
1026
+ }
1027
+ $order_model->billing = $order_billing;
1028
+ $requestItem->order = $order_model;
1029
+
1030
+ $endpoint = EnvironmentHelper::get_app_gateway_url( 'wordpress' ) . $endpoint;
1031
+ try {
1032
+ wp_remote_post(
1033
+ $endpoint, array(
1034
+ 'method' => 'POST',
1035
+ 'timeout' => 10,
1036
+ 'headers' => array(
1037
+ 'x-account-id' => OptionsHelper::get_connected_account_id(),
1038
+ 'x-api-key' => OptionsHelper::get_instance_api_key(),
1039
+ 'content-type' => 'application/json',
1040
+ ),
1041
+ 'body' => wp_json_encode( $requestItem ),
1042
+ )
1043
+ );
1044
+ } catch ( Exception $e ) {
1045
+ RaygunManager::get_instance()->exception_handler( $e );
1046
+ }
1047
+ }
1048
  }
src/Managers/DatabaseManager.php CHANGED
@@ -11,114 +11,112 @@ use DateTime;
11
  *
12
  * @package CreativeMail\Managers
13
  */
14
- class DatabaseManager
15
- {
16
- /**
17
- * Current version of abandoned checkouts table.
18
- *
19
- * @since 1.3.0
20
- */
21
- const ABANDONED_CART_TABLE_VERSION = '1.0';
22
-
23
- /**
24
- * Option name for abandoned checkouts db version.
25
- *
26
- * @since 1.3.0
27
- */
28
- const ABANDONED_CART_TABLE_VERSION_OPTION_NAME = 'ce4wp_abandoned_checkout_db_version';
29
-
30
- const CHECKOUT_UUID = 'checkout_uuid';
31
-
32
- /**
33
- * Abandoned checkouts table name.
34
- *
35
- * @since 1.3.0
36
- */
37
- const ABANDONED_CART_TABLE_NAME = 'ce4wp_abandoned_checkout';
38
-
39
- /**
40
- * Current version of the contacts table.
41
- *
42
- * @since 1.4.0
43
- */
44
- const CONTACTS_TABLE_VERSION = '1.0';
45
-
46
- /**
47
- * Option name for the contacts db version.
48
- *
49
- * @since 1.4.0
50
- */
51
- const CONTACTS_TABLE_VERSION_OPTION_NAME = 'ce4wp_contacts_db_version';
52
-
53
- /**
54
- * Contacts table name.
55
- *
56
- * @since 1.4.0
57
- */
58
- const CONTACTS_TABLE_NAME = 'ce4wp_contacts';
59
-
60
- public function add_hooks()
61
- {
62
- add_action('admin_init', array($this, 'update_database_check'), 10, 2);
63
- }
64
-
65
- /**
66
- * Check if table exists and is up-to-date.
67
- *
68
- * @since 1.3.0
69
- */
70
- public function update_database_check()
71
- {
72
- // check if woocommerce is active
73
- if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
74
- if (!get_site_option(self::ABANDONED_CART_TABLE_VERSION_OPTION_NAME)) {
75
- // Fresh install: create table.
76
- $this->create_abandoned_cart_table();
77
- } else if (current_user_can('administrator')) {
78
- // Cleanup old expired checkouts
79
- $this->delete_expired_checkouts();
80
- }
81
- }
82
- //check if ce4wp_contacts table exists
83
- if (!get_site_option(self::CONTACTS_TABLE_VERSION_OPTION_NAME)) {
84
- // Fresh install: create table.
85
- $this->create_contacts_table();
86
- }
87
- }
88
-
89
- /**
90
- * Helper function to remove checkout session data from db.
91
- *
92
- * @since 1.3.0
93
- */
94
- public function remove_checkout_data($checkout_uuid)
95
- {
96
- global $wpdb;
97
-
98
- // Delete current checkout data.
99
- $wpdb->delete(
100
- DatabaseManager::get_table_name(self::ABANDONED_CART_TABLE_NAME),
101
- [
102
- self::CHECKOUT_UUID => $checkout_uuid,
103
- ],
104
- [
105
- '%s',
106
- ]
107
- );
108
- }
109
-
110
- /**
111
- * Create abandoned checkouts table.
112
- *
113
- * @since 1.3.0
114
- */
115
- public function create_abandoned_cart_table()
116
- {
117
- global $wpdb;
118
-
119
- $table_name = self::get_table_name(self::ABANDONED_CART_TABLE_NAME);
120
-
121
- $sql = "CREATE TABLE {$table_name} (
122
  checkout_id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
123
  user_id bigint(20) unsigned NOT NULL DEFAULT 0,
124
  user_email varchar(200) NOT NULL DEFAULT '',
@@ -135,23 +133,22 @@ class DatabaseManager
135
  UNIQUE KEY checkout_uuid (checkout_uuid)
136
  ) {$wpdb->get_charset_collate()}";
137
 
138
- require_once ABSPATH . 'wp-admin/includes/upgrade.php';
139
- dbDelta($sql);
140
 
141
- add_option(self::ABANDONED_CART_TABLE_VERSION_OPTION_NAME, self::ABANDONED_CART_TABLE_VERSION);
142
- }
143
 
144
- /**
145
- * Create contacts table
146
- */
147
- public function create_contacts_table()
148
- {
149
- global $wpdb;
150
 
151
- $table_name = self::get_table_name(self::CONTACTS_TABLE_NAME);
152
 
153
- //keep column names equal to the form submission names so we don't need additional conversion
154
- $sql = "CREATE TABLE {$table_name} (
155
  contact_id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
156
  email varchar(200) NOT NULL DEFAULT '',
157
  first_name varchar(200) DEFAULT '',
@@ -162,50 +159,54 @@ class DatabaseManager
162
  UNIQUE KEY email (email)
163
  ) {$wpdb->get_charset_collate()}";
164
 
165
- require_once ABSPATH . 'wp-admin/includes/upgrade.php';
166
- dbDelta($sql);
167
 
168
- add_option(self::CONTACTS_TABLE_VERSION_OPTION_NAME, self::CONTACTS_TABLE_VERSION);
169
- }
170
 
171
- /**
172
- * Delete expired checkouts.
173
- *
174
- * @since 1.3.0
175
- */
176
- public function delete_expired_checkouts()
177
- {
178
- global $wpdb;
179
 
180
- // Delete all checkouts at least 30 days old.
181
- $table_name = $this->get_table_name(self::ABANDONED_CART_TABLE_NAME);
182
 
183
- $wpdb->query(
184
- $wpdb->prepare(
185
  // phpcs:disable WordPress.DB.PreparedSQL -- Okay use of unprepared variable for table name in SQL.
186
- "DELETE FROM {$table_name}
187
  WHERE `checkout_updated_ts` <= %s",
188
  // phpcs:enable
189
- (new DateTime())->sub(new DateInterval('P30D'))->format('U')
190
- )
191
- );
192
- }
193
-
194
- /**
195
- * Upsert the checkout content
196
- *
197
- * @since 1.3.0
198
- */
199
- public function upsert_checkout($checkout_uuid, $user_id, $billing_email, $content, $current_time)
200
- {
201
- global $wpdb;
202
-
203
- $table_name = $this->get_table_name(self::ABANDONED_CART_TABLE_NAME);
 
 
 
 
 
204
 
205
  // phpcs:disable WordPress.DB.PreparedSQL -- Okay use of unprepared variable for table name in SQL.
206
- $wpdb->query(
207
- $wpdb->prepare(
208
- "INSERT INTO {$table_name} (
209
  `user_id`,
210
  `user_email`,
211
  `checkout_contents`,
@@ -224,89 +225,90 @@ class DatabaseManager
224
  %d,
225
  %s
226
  ) ON DUPLICATE KEY UPDATE `user_id` = VALUES(`user_id`), `user_email` = VALUES(`user_email`), `checkout_updated` = VALUES(`checkout_updated`), `checkout_updated_ts` = VALUES(`checkout_updated_ts`), `checkout_contents` = VALUES(`checkout_contents`)",
227
- $user_id,
228
- $billing_email,
229
- maybe_serialize($content),
230
- $current_time,
231
- strtotime($current_time),
232
- $current_time,
233
- strtotime($current_time),
234
- $checkout_uuid
235
- )
236
- );
237
  // phpcs:enable
238
- }
239
-
240
- /**
241
- * Update the database record with current time for recovery
242
- *
243
- * @since 1.3.0
244
- */
245
- public function mark_checkout_recovered($checkout_uuid)
246
- {
247
- global $wpdb;
248
-
249
- $table_name = $this->get_table_name(self::ABANDONED_CART_TABLE_NAME);
250
-
251
- $current_time = current_time('mysql', 1);
252
-
253
- $wpdb->update($table_name, array(
254
- 'checkout_recovered' => $current_time,
255
- 'checkout_recovered_ts' => strtotime($current_time)
256
- ), array(self::CHECKOUT_UUID => $checkout_uuid));
257
- }
258
-
259
- /**
260
- * Update the database record with current consent
261
- *
262
- * @since 1.3.0
263
- */
264
- public function change_checkout_consent($checkout_uuid, $consent)
265
- {
266
- global $wpdb;
267
-
268
- $table_name = $this->get_table_name(self::ABANDONED_CART_TABLE_NAME);
269
-
270
- $int_consent = $consent ? 1 : 0;
271
-
272
- $wpdb->update($table_name, array(
273
- 'checkout_consent' => $int_consent
274
- ), array(self::CHECKOUT_UUID => $checkout_uuid));
275
- }
276
-
277
- public function has_checkout_consent($checkout_uuid)
278
- {
279
- global $wpdb;
280
-
281
- $table_name = $this->get_table_name(self::ABANDONED_CART_TABLE_NAME);
282
-
283
- $consent_value = $wpdb->get_var($wpdb->prepare("SELECT `checkout_consent` FROM $table_name WHERE `checkout_uuid` = %s", $checkout_uuid));
284
- return $consent_value === "1";
285
- }
286
-
287
- /**
288
- * Retrieve specific user's checkout data.
289
- *
290
- * @param string $select Field to return.
291
- * @param mixed $where String or array of WHERE clause predicates, using placeholders for values.
292
- * @param array $where_args Array of WHERE clause arguments.
293
- * @param string $order_by Order by column.
294
- * @param string $order Order (ASC/DESC).
295
- * @param string $limit LIMIT clause.
296
- * @param array $limit_args Array of LIMIT clause arguments.
297
- *
298
- * @return mixed Checkout data if exists, else null.
299
- * @since 1.3.0
300
- */
301
- public function get_checkout_data(string $select, $where, array $where_args, string $order_by = 'checkout_updated_ts', string $order = 'DESC', string $limit = '', array $limit_args = [])
302
- {
303
- global $wpdb;
304
-
305
- $table_name = $this->get_table_name(self::ABANDONED_CART_TABLE_NAME);
306
- $where = is_array($where) ? implode(' AND ', $where) : $where;
307
- $where = empty($where) ? 1 : $where;
308
-
309
- // Construct query to return checkout data.
 
310
  // phpcs:disable -- Disabling a number of sniffs that erroneously flag following block of code.
311
  // $where often includes placeholders for replacement via $wpdb->prepare(). $where_values provides those values.
312
  return $wpdb->get_results(
@@ -320,37 +322,35 @@ class DatabaseManager
320
  )
321
  );
322
  // phpcs:enable
323
- }
324
-
325
- /**
326
- * A simple utility for grabbing the full table name, including the WPDB table prefix.
327
- *
328
- * @param string $OptionName
329
- *
330
- * @return string
331
- * @since 1.3.0
332
- */
333
- public static function get_table_name(string $OptionName): string
334
- {
335
- global $wpdb;
336
- $table_name = null;
337
- if ($OptionName == self::ABANDONED_CART_TABLE_NAME) {
338
- $table_name = $wpdb->prefix . self::ABANDONED_CART_TABLE_NAME;
339
- } else if ($OptionName == self::CONTACTS_TABLE_NAME) {
340
- $table_name = $wpdb->prefix . self::CONTACTS_TABLE_NAME;
341
- }
342
- return is_string($table_name)? $table_name : '';
343
- }
344
-
345
- public function insert_contact($data)
346
- {
347
- global $wpdb;
348
-
349
- $table_name = $this->get_table_name(self::CONTACTS_TABLE_NAME);
350
-
351
- $wpdb->query(
352
- $wpdb->prepare(
353
- "INSERT IGNORE INTO {$table_name} (
354
  `email`,
355
  `first_name`,
356
  `last_name`,
@@ -362,13 +362,14 @@ class DatabaseManager
362
  %s,
363
  %s,
364
  %s
365
- )",
366
- $data['email'],
367
- $data['first_name'],
368
- $data['last_name'],
369
- $data['telephone'],
370
- $data['consent']
371
- )
372
- );
373
- }
 
374
  }
11
  *
12
  * @package CreativeMail\Managers
13
  */
14
+ class DatabaseManager {
15
+
16
+ /**
17
+ * Current version of abandoned checkouts table.
18
+ *
19
+ * @since 1.3.0
20
+ */
21
+ const ABANDONED_CART_TABLE_VERSION = '1.0';
22
+
23
+ /**
24
+ * Option name for abandoned checkouts db version.
25
+ *
26
+ * @since 1.3.0
27
+ */
28
+ const ABANDONED_CART_TABLE_VERSION_OPTION_NAME = 'ce4wp_abandoned_checkout_db_version';
29
+
30
+ const CHECKOUT_UUID = 'checkout_uuid';
31
+
32
+ /**
33
+ * Abandoned checkouts table name.
34
+ *
35
+ * @since 1.3.0
36
+ */
37
+ const ABANDONED_CART_TABLE_NAME = 'ce4wp_abandoned_checkout';
38
+
39
+ /**
40
+ * Current version of the contacts table.
41
+ *
42
+ * @since 1.4.0
43
+ */
44
+ const CONTACTS_TABLE_VERSION = '1.0';
45
+
46
+ /**
47
+ * Option name for the contacts db version.
48
+ *
49
+ * @since 1.4.0
50
+ */
51
+ const CONTACTS_TABLE_VERSION_OPTION_NAME = 'ce4wp_contacts_db_version';
52
+
53
+ /**
54
+ * Contacts table name.
55
+ *
56
+ * @since 1.4.0
57
+ */
58
+ const CONTACTS_TABLE_NAME = 'ce4wp_contacts';
59
+
60
+ public function add_hooks() {
61
+ add_action('admin_init', array( $this, 'update_database_check' ), 10, 2);
62
+ }
63
+
64
+ /**
65
+ * Check if table exists and is up-to-date.
66
+ *
67
+ * @since 1.3.0
68
+ */
69
+ public function update_database_check() {
70
+ // Check if woocommerce is active.
71
+ if ( in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')), true) ) {
72
+ if ( ! get_site_option(self::ABANDONED_CART_TABLE_VERSION_OPTION_NAME) ) {
73
+ // Fresh install: create table.
74
+ $this->create_abandoned_cart_table();
75
+ } elseif ( current_user_can('administrator') ) {
76
+ // Cleanup old expired checkouts.
77
+ $this->delete_expired_checkouts();
78
+ }
79
+ }
80
+ // Check if ce4wp_contacts table exists.
81
+ if ( ! get_site_option(self::CONTACTS_TABLE_VERSION_OPTION_NAME) ) {
82
+ // Fresh install: create table.
83
+ $this->create_contacts_table();
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Helper function to remove checkout session data from db.
89
+ *
90
+ * @param string $checkout_uuid The checkout uuid.
91
+ *
92
+ * @since 1.3.0
93
+ */
94
+ public function remove_checkout_data( $checkout_uuid ) {
95
+ global $wpdb;
96
+
97
+ // Delete current checkout data.
98
+ $wpdb->delete(
99
+ self::get_table_name(self::ABANDONED_CART_TABLE_NAME),
100
+ array(
101
+ self::CHECKOUT_UUID => $checkout_uuid,
102
+ ),
103
+ array(
104
+ '%s',
105
+ )
106
+ );
107
+ }
108
+
109
+ /**
110
+ * Create abandoned checkouts table.
111
+ *
112
+ * @since 1.3.0
113
+ */
114
+ public function create_abandoned_cart_table() {
115
+ global $wpdb;
116
+
117
+ $table_name = self::get_table_name(self::ABANDONED_CART_TABLE_NAME);
118
+
119
+ $sql = "CREATE TABLE {$table_name} (
 
 
120
  checkout_id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
121
  user_id bigint(20) unsigned NOT NULL DEFAULT 0,
122
  user_email varchar(200) NOT NULL DEFAULT '',
133
  UNIQUE KEY checkout_uuid (checkout_uuid)
134
  ) {$wpdb->get_charset_collate()}";
135
 
136
+ require_once ABSPATH . 'wp-admin/includes/upgrade.php';
137
+ dbDelta($sql);
138
 
139
+ add_option(self::ABANDONED_CART_TABLE_VERSION_OPTION_NAME, self::ABANDONED_CART_TABLE_VERSION);
140
+ }
141
 
142
+ /**
143
+ * Create contacts table
144
+ */
145
+ public function create_contacts_table() {
146
+ global $wpdb;
 
147
 
148
+ $table_name = self::get_table_name(self::CONTACTS_TABLE_NAME);
149
 
150
+ // keep column names equal to the form submission names so we don't need additional conversion.
151
+ $sql = "CREATE TABLE {$table_name} (
152
  contact_id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
153
  email varchar(200) NOT NULL DEFAULT '',
154
  first_name varchar(200) DEFAULT '',
159
  UNIQUE KEY email (email)
160
  ) {$wpdb->get_charset_collate()}";
161
 
162
+ require_once ABSPATH . 'wp-admin/includes/upgrade.php';
163
+ dbDelta($sql);
164
 
165
+ add_option(self::CONTACTS_TABLE_VERSION_OPTION_NAME, self::CONTACTS_TABLE_VERSION);
166
+ }
167
 
168
+ /**
169
+ * Delete expired checkouts.
170
+ *
171
+ * @since 1.3.0
172
+ */
173
+ public function delete_expired_checkouts() {
174
+ global $wpdb;
 
175
 
176
+ // Delete all checkouts at least 30 days old.
177
+ $table_name = $this->get_table_name(self::ABANDONED_CART_TABLE_NAME);
178
 
179
+ $wpdb->query(
180
+ $wpdb->prepare(
181
  // phpcs:disable WordPress.DB.PreparedSQL -- Okay use of unprepared variable for table name in SQL.
182
+ "DELETE FROM {$table_name}
183
  WHERE `checkout_updated_ts` <= %s",
184
  // phpcs:enable
185
+ ( new DateTime() )->sub(new DateInterval('P30D'))->format('U')
186
+ )
187
+ );
188
+ }
189
+
190
+ /**
191
+ * Upsert the checkout content
192
+ *
193
+ * @param string $checkout_uuid The checkout uuid.
194
+ * @param string $user_id The user id.
195
+ * @param string $billing_email The user email.
196
+ * @param array $content The checkout content.
197
+ * @param int|string $current_time The consent value.
198
+ *
199
+ * @since 1.3.0
200
+ */
201
+ public function upsert_checkout( $checkout_uuid, $user_id, $billing_email, $content, $current_time ) {
202
+ global $wpdb;
203
+
204
+ $table_name = $this->get_table_name(self::ABANDONED_CART_TABLE_NAME);
205
 
206
  // phpcs:disable WordPress.DB.PreparedSQL -- Okay use of unprepared variable for table name in SQL.
207
+ $wpdb->query(
208
+ $wpdb->prepare(
209
+ "INSERT INTO {$table_name} (
210
  `user_id`,
211
  `user_email`,
212
  `checkout_contents`,
225
  %d,
226
  %s
227
  ) ON DUPLICATE KEY UPDATE `user_id` = VALUES(`user_id`), `user_email` = VALUES(`user_email`), `checkout_updated` = VALUES(`checkout_updated`), `checkout_updated_ts` = VALUES(`checkout_updated_ts`), `checkout_contents` = VALUES(`checkout_contents`)",
228
+ $user_id,
229
+ $billing_email,
230
+ maybe_serialize($content),
231
+ $current_time,
232
+ strtotime($current_time),
233
+ $current_time,
234
+ strtotime($current_time),
235
+ $checkout_uuid
236
+ )
237
+ );
238
  // phpcs:enable
239
+ }
240
+
241
+ /**
242
+ * Update the database record with current time for recovery
243
+ *
244
+ * @param string $checkout_uuid The checkout uuid.
245
+ *
246
+ * @since 1.3.0
247
+ */
248
+ public function mark_checkout_recovered( $checkout_uuid ) {
249
+ global $wpdb;
250
+
251
+ $table_name = $this->get_table_name(self::ABANDONED_CART_TABLE_NAME);
252
+
253
+ $current_time = current_time('mysql', 1);
254
+
255
+ $wpdb->update($table_name, array(
256
+ 'checkout_recovered' => $current_time,
257
+ 'checkout_recovered_ts' => strtotime($current_time),
258
+ ), array( self::CHECKOUT_UUID => $checkout_uuid ));
259
+ }
260
+
261
+ /**
262
+ * Update the database record with current consent
263
+ *
264
+ * @param string $checkout_uuid The checkout uuid.
265
+ * @param bool $consent The consent value.
266
+ *
267
+ * @since 1.3.0
268
+ */
269
+ public function change_checkout_consent( $checkout_uuid, $consent ) {
270
+ global $wpdb;
271
+
272
+ $table_name = $this->get_table_name(self::ABANDONED_CART_TABLE_NAME);
273
+
274
+ $int_consent = $consent ? 1 : 0;
275
+
276
+ $wpdb->update($table_name, array(
277
+ 'checkout_consent' => $int_consent,
278
+ ), array( self::CHECKOUT_UUID => $checkout_uuid ));
279
+ }
280
+
281
+ public function has_checkout_consent( $checkout_uuid ) {
282
+ global $wpdb;
283
+
284
+ $table_name = $this->get_table_name(self::ABANDONED_CART_TABLE_NAME);
285
+
286
+ $consent_value = $wpdb->get_var($wpdb->prepare('SELECT `checkout_consent` FROM %s WHERE `checkout_uuid` = %s', $table_name, $checkout_uuid));
287
+ return '1' === $consent_value;
288
+ }
289
+
290
+ /**
291
+ * Retrieve specific user's checkout data.
292
+ *
293
+ * @param string $select Field to return.
294
+ * @param mixed $where String or array of WHERE clause predicates, using placeholders for values.
295
+ * @param array $where_args Array of WHERE clause arguments.
296
+ * @param string $order_by Order by column.
297
+ * @param string $order Order (ASC/DESC).
298
+ * @param string $limit LIMIT clause.
299
+ * @param array $limit_args Array of LIMIT clause arguments.
300
+ *
301
+ * @return mixed Checkout data if exists, else null.
302
+ * @since 1.3.0
303
+ */
304
+ public function get_checkout_data( string $select, $where, array $where_args, string $order_by = 'checkout_updated_ts', string $order = 'DESC', string $limit = '', array $limit_args = array() ) {
305
+ global $wpdb;
306
+
307
+ $table_name = $this->get_table_name(self::ABANDONED_CART_TABLE_NAME);
308
+ $where = is_array($where) ? implode(' AND ', $where) : $where;
309
+ $where = empty($where) ? 1 : $where;
310
+
311
+ // Construct query to return checkout data.
312
  // phpcs:disable -- Disabling a number of sniffs that erroneously flag following block of code.
313
  // $where often includes placeholders for replacement via $wpdb->prepare(). $where_values provides those values.
314
  return $wpdb->get_results(
322
  )
323
  );
324
  // phpcs:enable
325
+ }
326
+
327
+ /**
328
+ * A simple utility for grabbing the full table name, including the WPDB table prefix.
329
+ *
330
+ * @param string $OptionName The name of the option to retrieve.
331
+ *
332
+ * @return string
333
+ * @since 1.3.0
334
+ */
335
+ public static function get_table_name( string $OptionName ): string {
336
+ global $wpdb;
337
+ $table_name = null;
338
+ if ( self::ABANDONED_CART_TABLE_NAME == $OptionName ) {
339
+ $table_name = $wpdb->prefix . self::ABANDONED_CART_TABLE_NAME;
340
+ } elseif ( self::CONTACTS_TABLE_NAME == $OptionName ) {
341
+ $table_name = $wpdb->prefix . self::CONTACTS_TABLE_NAME;
342
+ }
343
+ return is_string($table_name) ? $table_name : '';
344
+ }
345
+
346
+ public function insert_contact( $data ) {
347
+ global $wpdb;
348
+
349
+ $table_name = $this->get_table_name(self::CONTACTS_TABLE_NAME);
350
+
351
+ $wpdb->query(
352
+ $wpdb->prepare(
353
+ 'INSERT IGNORE INTO %s (
 
 
354
  `email`,
355
  `first_name`,
356
  `last_name`,
362
  %s,
363
  %s,
364
  %s
365
+ )',
366
+ $table_name,
367
+ $data['email'],
368
+ $data['first_name'],
369
+ $data['last_name'],
370
+ $data['telephone'],
371
+ $data['consent']
372
+ )
373
+ );
374
+ }
375
  }
src/Managers/EmailManager.php CHANGED
@@ -4,7 +4,6 @@
4
  namespace CreativeMail\Managers;
5
 
6
  use CreativeMail\CreativeMail;
7
- use CreativeMail\Helpers\ValidationHelper;
8
  use CreativeMail\Models\CustomerNewAccount;
9
  use CreativeMail\Models\CustomerNote;
10
  use CreativeMail\Models\CustomerResetPassword;
@@ -22,829 +21,799 @@ use WC_Email;
22
  *
23
  * @package CreativeMail\Managers
24
  */
25
- class EmailManager
26
- {
27
- /**
28
- * Email ids being managed by CreativeMail
29
- *
30
- * @var array
31
- */
32
- protected $managed_email_notifications;
33
-
34
- private $valid_email_notification_names = [
35
- 'customer_completed_order',
36
- 'customer_refunded_order',
37
- 'customer_processing_order',
38
- 'customer_on_hold_order',
39
- 'customer_new_account',
40
- 'customer_reset_password',
41
- 'customer_invoice',
42
- 'customer_note',
43
- 'cart_abandoned_ce4wp'
44
- ];
45
-
46
- const CHECKOUT_CONSENT_CHECKBOX_ID = 'ce4wp_checkout_consent_checkbox';
47
- const CHECKOUT_CONSENT_CHECKBOX_VALUE = 'ce4wp_checkout_consent';
48
-
49
- public function __construct()
50
- {
51
- $this->managed_email_notifications = $this->get_managed_email_notifications();
52
- }
53
-
54
- public function add_hooks()
55
- {
56
- // Check if woocommerce is active.
57
- if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
58
- add_action('init', array($this, 'manage_emails'));
59
-
60
- // Email settings table customizations.
61
- add_filter('woocommerce_email_setting_columns', array($this, 'customize_email_setting_columns'));
62
- add_action('woocommerce_email_setting_column_wc_ce_status', array($this, 'render_email_status_column'));
63
- add_action('woocommerce_email_settings_before', array($this, 'redirect_managed_email_settings_to_creative_mail'));
64
-
65
- // Woocommerce hooks.
66
- add_action('woocommerce_new_order', array($this, 'ce_email_notification_new_order'), 10, 2);
67
- add_action('woocommerce_order_status_cancelled', array($this, 'ce_email_notification_cancelled'), 10, 2);
68
- add_action('woocommerce_order_status_failed', array($this, 'ce_email_notification_failed'), 10, 2);
69
- add_action('woocommerce_order_status_on-hold', array($this, 'ce_email_notification_hold'), 10, 2);
70
- add_action('woocommerce_order_status_processing', array($this, 'ce_email_notification_processing'), 10, 2);
71
- add_action('woocommerce_order_status_completed', array($this, 'ce_email_notification_completed'), 10, 2);
72
- add_action('woocommerce_order_status_refunded', array($this, 'ce_email_notification_refunded'), 10, 2);
73
- add_action('woocommerce_after_resend_order_email', array($this, 'ce_email_notification_invoice'), 10, 2);
74
-
75
- // Payment complete.
76
- add_action('woocommerce_payment_complete', array( $this, 'ce_email_notification_payment_complete'), 10, 1);
77
- // New customer Note.
78
- add_action('woocommerce_new_customer_note', array( $this, 'ce_email_notification_new_customer_note'), 10, 2);
79
- // Password reset.
80
- add_action('woocommerce_reset_password_notification', array( $this, 'ce_email_notification_customer_reset_password' ), 10, 2);
81
- add_action('woocommerce_created_customer', array( $this, 'ce_email_notification_customer_new_account' ), 10, 3);
82
- // Replace WC Email settings.
83
- add_filter('woocommerce_email_settings', array($this, 'replace_wc_email_settings'));
84
- add_action('woocommerce_admin_field_ce_manage_button', array($this, 'print_ce_manage_button'));
85
- // Add checkbox to check out if enabled.
86
- if (OptionsHelper::get_checkout_checkbox_enabled() == '1') {
87
- add_filter('woocommerce_after_order_notes', array($this, 'add_checkout_field'));
88
- add_action('woocommerce_checkout_update_order_meta', array($this, 'ce_checkout_order_meta'));
89
- }
90
- // Modify emails emails.
91
- add_filter( 'woocommerce_email_classes', array( $this, 'add_emails' ), 20 );
92
- }
93
- }
94
-
95
- public function add_emails( $email_classes ) {
96
- // Add fake email.
97
- $email_classes['AbandonedCartEmail'] = new AbandonedCartEmail();
98
- return $email_classes;
99
- }
100
-
101
- public function ce_checkout_order_meta( $order_id )
102
- {
103
- if (isset($_POST[self::CHECKOUT_CONSENT_CHECKBOX_ID])) {
104
- $checkbox_value = esc_attr($_POST[self::CHECKOUT_CONSENT_CHECKBOX_ID]);
105
- } else {
106
- $checkbox_value = "0";
107
- }
108
- update_post_meta($order_id, self::CHECKOUT_CONSENT_CHECKBOX_VALUE, $checkbox_value);
109
- }
110
-
111
- public function add_checkout_field( $checkout)
112
- {
113
- $checked = $checkout->get_value(self::CHECKOUT_CONSENT_CHECKBOX_ID) ? $checkout->get_value(self::CHECKOUT_CONSENT_CHECKBOX_ID) : 0;
114
- $checkbox_text = stripslashes(OptionsHelper::get_checkout_checkbox_text());
115
-
116
- woocommerce_form_field(
117
- self::CHECKOUT_CONSENT_CHECKBOX_ID, array(
118
- 'type' => 'checkbox',
119
- 'class' => array('ce-field form-row-wide'),
120
- 'label' => $checkbox_text,
121
- ), $checked
122
- );
123
- }
124
-
125
- public function replace_wc_email_settings($settings)
126
- {
127
- $default_setting_replacement = array(
128
- 'woocommerce_email_header_image' => 'header_image',
129
- 'woocommerce_email_footer_text' => 'footer_content_text',
130
- 'woocommerce_email_base_color' => null,
131
- 'woocommerce_email_background_color' => 'background_color',
132
- 'woocommerce_email_body_background_color' => 'email_background_color',
133
- 'woocommerce_email_text_color' => 'text_color'
134
- );
135
-
136
- // Define options that need to be replaced.
137
- $replace = array_merge(array_keys($default_setting_replacement), array('email_template_options'));
138
-
139
- // Remove settings.
140
- foreach ($settings as $setting_key => $setting) {
141
- if (isset($setting['id']) && in_array($setting['id'], $replace, true)) {
142
- unset($settings[$setting_key]);
143
- }
144
- }
145
-
146
- $settings[] = array(
147
- 'id' => 'ce_manage',
148
- 'type' => 'title',
149
- 'title' => __('Creative Mail', 'ce4wp'),
150
- );
151
-
152
- $settings[] = array(
153
- 'id' => 'ce_manage_button',
154
- 'type' => 'ce_manage_button',
155
- );
156
-
157
- $settings[] = array(
158
- 'id' => 'ce_manage',
159
- 'type' => 'sectionend',
160
- );
161
- return $settings;
162
- }
163
-
164
- public function print_ce_manage_button($options)
165
- {
166
- ?><tr valign="top">
167
- <th scope="row" class="titledesc"><?php _e('Customize Emails', 'ce4wp'); ?></th>
168
- <td class="forminp forminp-<?php echo sanitize_title($options['type']); ?>">
169
- <a href="<?= esc_url( admin_url( 'admin.php?page=creativemail' ) ); ?>">
170
- <button type="button" class="button button-secondary" value="<?php _e('Manage', 'ce4wp'); ?>"><?php _e('Manage', 'ce4wp'); ?></button>
171
- </a>
172
- <p class="description"><?php _e('Manage all your email settings and templates with Creative Mail', 'ce4wp'); ?></p>
173
- </td>
174
- </tr><?php
175
- }
176
-
177
- public function get_managed_email_notifications()
178
- {
179
- return OptionsHelper::get_managed_email_notifications();
180
- }
181
-
182
- public function set_managed_email_notifications($body)
183
- {
184
- if (empty($body)) {
185
- return null;
186
- }
187
-
188
- if ( property_exists($body, 'name') && in_array( $body->name, $this->valid_email_notification_names ) ) {
189
- OptionsHelper::set_managed_email_notification($body->name, $body->active == true ? 'true' : 'false');
190
- return $body;
191
- }
192
-
193
- return null;
194
- }
195
-
196
- /**
197
- * Renders the custom email status column.
198
- *
199
- * @param WC_Email $email the email
200
- *
201
- * @internal
202
- * @since 1.1.0
203
- */
204
- public function render_email_status_column( WC_Email $email )
205
- {
206
-
207
- echo '<td class="wc-email-settings-table-status">';
208
-
209
- if ($this->is_email_managed($email->id) ) {
210
- echo '<span class="status-creativemail tips" data-tip="' . esc_attr__('Managed by Creative Mail', 'ce4wp') . '">' . esc_html__('Managed by CreativeMail', 'ce4wp') . '</span>';
211
- } elseif($email->id === 'cart_abandoned_ce4wp') {
212
- echo '<span class="status-disabled tips" data-tip="' . esc_attr__('Disabled', 'woocommerce') . '">-</span>';
213
- } elseif ($email->is_manual() ) {
214
- echo '<span class="status-manual tips" data-tip="' . esc_attr__('Manually sent', 'woocommerce') . '">' . esc_html__('Manual', 'woocommerce') . '</span>';
215
- } elseif ($email->is_enabled() ) {
216
- echo '<span class="status-enabled tips" data-tip="' . esc_attr__('Enabled', 'woocommerce') . '">' . esc_html__('Yes', 'woocommerce') . '</span>';
217
- } else {
218
- echo '<span class="status-disabled tips" data-tip="' . esc_attr__('Disabled', 'woocommerce') . '">-</span>';
219
- }
220
-
221
- echo '</td>';
222
- }
223
-
224
- public function customize_email_setting_columns( $columns )
225
- {
226
-
227
- $column_keys = array_keys($columns);
228
-
229
- // replace the status column, or put at the beginning if status isn't found
230
- $status_index = array_search('status', $column_keys, true);
231
- array_splice($column_keys, is_numeric($status_index) ? $status_index : 0, is_numeric($status_index) ? 1 : 0, 'wc_ce_status');
232
-
233
- $new_columns = array();
234
- $columns['wc_ce_status'] = '';
235
-
236
- foreach ( $column_keys as $column_key )
237
- {
238
- if (isset($columns[ $column_key ]) ) {
239
- $new_columns[ $column_key ] = $columns[ $column_key ];
240
- }
241
- }
242
-
243
- return $new_columns;
244
- }
245
-
246
- public function ce_email_notification_new_customer_note($array)
247
- {
248
- $data = new CustomerNote();
249
- $data->order_id = $array[ 'order_id' ];
250
- $data->note = $array[ 'customer_note' ];
251
- $data->order_url = $this->get_view_order_url( $data->order_id, null );
252
-
253
- $this->execute_trigger( "customer_note", $data, wc_get_order( $data->order_id ) );
254
- }
255
-
256
- public function ce_email_notification_customer_new_account( $customer_id, $new_customer_data, $password_generated )
257
- {
258
- $data = new CustomerNewAccount();
259
- $data->customer_id = $customer_id;
260
- $data->account_url = $this->get_my_account_url();
261
- $data->customer = $this->get_customer_data( $customer_id );
262
-
263
- if ( $password_generated && key_exists( "user_pass", $new_customer_data ) ) {
264
- try {
265
- $salted = '';
266
- $dx = '';
267
- $salt = null;
268
-
269
- $generated_password = $new_customer_data[ 'user_pass' ];
270
- $key = sha1( OptionsHelper::get_instance_api_key() . OptionsHelper::get_instance_uuid() );
271
- $openssl_cipher_iv_length = openssl_cipher_iv_length( 'aes-256-cbc' );
272
-
273
- if (! is_bool( $openssl_cipher_iv_length )) {
274
- $salt = openssl_random_pseudo_bytes( $openssl_cipher_iv_length );
275
- }
276
- if (! empty($salt) && is_string( $salt )) {
277
- while ( strlen( $salted ) < 48 ) {
278
- $dx = md5( $dx . $key . $salt, true );
279
- $salted .= $dx;
280
- }
281
- }
282
- $key = substr( $salted, 0, 32 );
283
- $iv = substr( $salted, 32, 16 );
284
- $gp = openssl_encrypt( $generated_password, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv );
285
- $data->salt = bin2hex( is_string($salt) ? $salt : '' );
286
- $data->generated_password = base64_encode( is_string($gp) ? $gp : '' );
287
- } catch ( Exception $ex ) {
288
- RaygunManager::get_instance()->exception_handler( $ex );
289
- }
290
- }
291
-
292
- $this->execute_trigger( "customer_new_account", $data,null, true ) ;
293
- }
294
-
295
- public function ce_email_notification_customer_reset_password( $user_login = '', $reset_key = '' )
296
- {
297
- if ( $user_login && $reset_key ) {
298
- $data = new CustomerResetPassword();
299
- $user = get_user_by( 'login', $user_login );
300
- if (!empty($user)) {
301
- $data->customer_id = $user->ID;
302
- $data->customer = $this->get_customer_data($user->ID);
303
- }
304
- $data->account_url = $this->get_my_account_url();
305
- $data->reset_url = add_query_arg(
306
- array(
307
- 'key' => $reset_key,
308
- 'id' => $data->customer_id
309
- ), wc_get_endpoint_url( 'lost-password', '', $data->account_url )
310
- );
311
-
312
- $this->execute_trigger( "customer_reset_password", $data, null, true );
313
- }
314
- }
315
-
316
- public function ce_email_notification_payment_complete( $order_id )
317
- {
318
- $data = new EmailNotification();
319
- $data->order_id = $order_id;
320
- $data->order_url = $this->get_view_order_url( $order_id, null );
321
-
322
- $this->execute_trigger( "payment_received", $data, wc_get_order( $order_id ) );
323
- }
324
-
325
- public function ce_email_notification_failed( $order_id, $order )
326
- {
327
- $data = new EmailNotification();
328
- $data->order_id = $order_id;
329
- $data->order_url = $this->get_view_order_url( $order_id, $order );
330
-
331
- $this->execute_trigger( "failed_order", $data, $order );
332
- }
333
- public function ce_email_notification_hold( $order_id, $order )
334
- {
335
- $data = new EmailNotification();
336
- $data->order_id = $order_id;
337
- $data->order_url = $this->get_view_order_url( $order_id, $order );
338
-
339
- $this->execute_trigger( "customer_on_hold_order", $data, $order );
340
- }
341
- public function ce_email_notification_processing( $order_id, $order )
342
- {
343
- $data = new EmailNotification();
344
- $data->order_id = $order_id;
345
- $data->order_url = $this->get_view_order_url( $order_id, $order );
346
-
347
- $this->execute_trigger( "customer_processing_order", $data, $order );
348
- }
349
- public function ce_email_notification_completed( $order_id, $order )
350
- {
351
- $data = new EmailNotification();
352
- $data->order_id = $order_id;
353
- $data->order_url = $this->get_view_order_url( $order_id, $order );
354
-
355
- $this->execute_trigger( "customer_completed_order", $data, $order );
356
- }
357
-
358
- public function ce_email_notification_refunded( $order_id, $order )
359
- {
360
- $data = new EmailNotification();
361
- $data->order_id = $order_id;
362
- $data->order_url = $this->get_view_order_url( $order_id, $order );
363
-
364
- $this->execute_trigger( "customer_refunded_order", $data, $order );
365
- }
366
- public function ce_email_notification_cancelled( $order_id, $order )
367
- {
368
- $data = new EmailNotification();
369
- $data->order_id = $order_id;
370
- $data->order_url = $this->get_view_order_url( $order_id, $order );
371
-
372
- $this->execute_trigger( "cancelled_order", $data, $order );
373
- }
374
-
375
- public function ce_email_notification_new_order( $order_id, $order )
376
- {
377
- $data = new EmailNotification();
378
- $data->order_id = $order_id;
379
- $data->order_url = $this->get_view_order_url( $order_id, $order );
380
-
381
- $this->execute_trigger( "new_order", $data, $order );
382
- }
383
-
384
- public function ce_email_notification_invoice( $order, $type )
385
- {
386
- if ( $type === 'new_order' ) {
387
- $this->ce_email_notification_new_order( $order->id, $order );
388
- return;
389
- }
390
-
391
- $data = new EmailNotification();
392
- $data->order_id = $order->get_id();
393
- $data->order_url = $this->get_view_order_url( $order->get_id(), $order );
394
-
395
- $this->execute_trigger( "customer_invoice", $data, $order );
396
- }
397
-
398
- public function execute_trigger( $type, $data, $order = null, $with_data = false )
399
- {
400
- // if not managed do not trigger
401
- if ( !$this->is_email_managed( $type ) ) {
402
- return;
403
- }
404
-
405
- $requestItem = new TriggerExecution();
406
- $requestItem->type = $type;
407
-
408
- if( !is_null( $order ) ) {
409
- try {
410
- $dp = 2; // decimal point
411
- $order_data = array(
412
- 'id' => $order->get_id(),
413
- 'number' => $order->get_order_number(),
414
- 'date_created' => $order->get_date_created() ? $order->get_date_created()->getTimestamp() : 0,
415
- 'date_modified' => $order->get_date_modified() ? $order->get_date_modified()->getTimestamp() : 0,
416
- 'date_completed' => $order->get_date_completed() ? $order->get_date_completed()->getTimestamp() : 0,
417
- 'status' => $order->get_status(),
418
- 'currency' => $order->get_currency(),
419
- 'currency_symbol' => get_woocommerce_currency_symbol( $order->get_currency()),
420
- 'total' => wc_format_decimal( $order->get_total(), $dp ),
421
- 'subtotal' => wc_format_decimal( $order->get_subtotal(), $dp ),
422
- 'total_line_items_quantity' => $order->get_item_count(),
423
- 'total_tax' => wc_format_decimal( $order->get_total_tax(), $dp ),
424
- 'shipping_total' => wc_format_decimal( $order->get_shipping_total(), $dp ),
425
- 'cart_tax' => wc_format_decimal( $order->get_cart_tax(), $dp ),
426
- 'shipping_tax' => wc_format_decimal( $order->get_shipping_tax(), $dp ),
427
- 'discount_total' => wc_format_decimal( $order->get_total_discount(), $dp ),
428
- 'shipping_methods' => $order->get_shipping_method(),
429
- 'payment_details' => array(
430
- 'method_id' => $order->get_payment_method(),
431
- 'method_title' => $order->get_payment_method_title(),
432
- 'paid' => !is_null($order->get_date_paid()),
433
- ),
434
- 'billing' => array(
435
- 'first_name' => $order->get_billing_first_name(),
436
- 'last_name' => $order->get_billing_last_name(),
437
- 'company' => $order->get_billing_company(),
438
- 'address_1' => $order->get_billing_address_1(),
439
- 'address_2' => $order->get_billing_address_2(),
440
- 'city' => $order->get_billing_city(),
441
- 'state' => $order->get_billing_state(),
442
- 'postcode' => $order->get_billing_postcode(),
443
- 'country' => $order->get_billing_country(),
444
- 'email' => $order->get_billing_email(),
445
- 'phone' => $order->get_billing_phone(),
446
- ),
447
- 'shipping' => array(
448
- 'first_name' => $order->get_shipping_first_name(),
449
- 'last_name' => $order->get_shipping_last_name(),
450
- 'company' => $order->get_shipping_company(),
451
- 'address_1' => $order->get_shipping_address_1(),
452
- 'address_2' => $order->get_shipping_address_2(),
453
- 'city' => $order->get_shipping_city(),
454
- 'state' => $order->get_shipping_state(),
455
- 'postcode' => $order->get_shipping_postcode(),
456
- 'country' => $order->get_shipping_country(),
457
- ),
458
- 'customer_note' => $order->get_customer_note(),
459
- 'customer_ip' => $order->get_customer_ip_address(),
460
- 'customer_user_agent' => $order->get_customer_user_agent(),
461
- 'customer_id' => $order->get_user_id(),
462
- 'view_order_url' => $order->get_view_order_url(),
463
- 'line_items' => array(),
464
- 'shipping_lines' => array(),
465
- 'tax_lines' => array(),
466
- 'fee_lines' => array(),
467
- 'coupon_lines' => array()
468
- );
469
-
470
- // add line items
471
- foreach ( $order->get_items() as $item_id => $item ) {
472
- $product = $item->get_product();
473
- $item_meta = $item->get_formatted_meta_data();
474
-
475
- foreach ( $item_meta as $key => $values ) {
476
- $item_meta[ $key ]->label = $values->display_key;
477
- unset( $item_meta[ $key ]->display_key );
478
- unset( $item_meta[ $key ]->display_value );
479
- }
480
-
481
- try {
482
-
483
- $product_data = array(
484
- 'images' => array(),
485
- 'downloads' => array()
486
- );
487
- $attachment_ids = $product->get_gallery_image_ids();
488
- foreach ( $attachment_ids as $attachment_id ) {
489
- $product_data[ 'images' ][] = wp_get_attachment_url( $attachment_id );
490
- }
491
-
492
- $product_data[ "on_sale" ] = $product->is_on_sale();
493
- $product_data[ "sale_price" ] = $product->get_sale_price();
494
- $product_data[ "regular_price" ] = $product->get_regular_price();
495
-
496
- if ( $product->is_downloadable() ) {
497
- $item_downloads = $item->get_item_downloads();
498
- foreach ( $item_downloads as $item_download )
499
- {
500
- $product_data[ "downloads" ][] = array(
501
- 'line_item_id' => $item->get_id(),
502
- 'product_id' => $item->get_product_id(),
503
- 'download_url' => $item_download[ "download_url" ],
504
- 'download_file' => $item_download[ "file" ],
505
- 'download_name' => $item_download[ "name" ],
506
- 'download_id' => $item_download[ "id" ],
507
- 'downloads_remaining' => $item_download[ "downloads_remaining" ],
508
- 'download_access_expires' => wc_format_datetime($item_download[ "access_expires" ], 'U'),
509
- 'download_limit' => $product->get_download_limit(),
510
- 'download_expiry' => $product->get_download_expiry(),
511
- );
512
- }
513
- }
514
-
515
- } catch ( Exception $ex )
516
- {
517
- RaygunManager::get_instance()->exception_handler( $ex );
518
- }
519
-
520
- $src = wc_placeholder_img_src();
521
- if ( $image_id = $product->get_image_id() ) {
522
- $image_src = wp_get_attachment_image_src( $image_id, 'full' );
523
- list( $src ) = is_array( $image_src ) ? $image_src : array('');
524
- }
525
-
526
- $order_data[ 'line_items' ][] = array(
527
- 'id' => $item_id,
528
- 'subtotal' => wc_format_decimal( $order->get_line_subtotal( $item, false, false ), $dp ),
529
- 'subtotal_tax' => wc_format_decimal( $item->get_subtotal_tax(), $dp ),
530
- 'total' => wc_format_decimal( $order->get_line_total( $item, false, false ), $dp ),
531
- 'total_tax' => wc_format_decimal( $item->get_total_tax(), $dp ),
532
- 'price' => wc_format_decimal( $order->get_item_total( $item, false, false ), $dp ),
533
- 'quantity' => $item->get_quantity(),
534
- 'tax_class' => $item->get_tax_class(),
535
- 'name' => $item->get_name(),
536
- 'product_id' => $item->get_product_id(),
537
- 'product_image' => $src,
538
- 'product_data' => $product_data,
539
- 'sku' => is_a($product, 'WC_Product') ? $product->get_sku() : null,
540
- 'meta' => array_values( $item_meta ),
541
- 'product_url' => get_the_permalink( $item->get_product_id() ),
542
- 'variation_id' => $item->get_variation_id()
543
- );
544
- }
545
-
546
- // Add shipping.
547
- foreach ( $order->get_shipping_methods() as $shipping_item_id => $shipping_item ) {
548
- $order_data[ 'shipping_lines' ][] = array(
549
- 'id' => $shipping_item_id,
550
- 'method_id' => $shipping_item->get_method_id(),
551
- 'method_title' => $shipping_item->get_name(),
552
- 'total' => wc_format_decimal( $shipping_item->get_total(), $dp ),
553
- );
554
- }
555
-
556
- // Add taxes.
557
- foreach ( $order->get_tax_totals() as $tax_code => $tax ) {
558
- $order_data[ 'tax_lines' ][] = array(
559
- 'id' => $tax->id,
560
- 'rate_id' => $tax->rate_id,
561
- 'code' => $tax_code,
562
- 'title' => $tax->label,
563
- 'total' => wc_format_decimal($tax->amount, $dp),
564
- 'compound' => ( bool )$tax->is_compound,
565
- );
566
- }
567
-
568
- // Add fees.
569
- foreach ( $order->get_fees() as $fee_item_id => $fee_item ) {
570
- $order_data[ 'fee_lines' ][] = array(
571
- 'id' => $fee_item_id,
572
- 'title' => $fee_item->get_name(),
573
- 'tax_class' => $fee_item->get_tax_class(),
574
- 'total' => wc_format_decimal( $order->get_line_total( $fee_item ), $dp ),
575
- 'total_tax' => wc_format_decimal( $order->get_line_tax( $fee_item ), $dp ),
576
- );
577
- }
578
-
579
- // Add coupons.
580
- foreach ( $order->get_items( 'coupon' ) as $coupon_item_id => $coupon_item ) {
581
- $order_data[ 'coupon_lines' ][] = array(
582
- 'id' => $coupon_item_id,
583
- 'code' => $coupon_item->get_code(),
584
- 'amount' => wc_format_decimal( $coupon_item->get_discount(), $dp ),
585
- );
586
- }
587
- $data->order = $order_data;
588
- $with_data = true;
589
- }
590
- catch ( Exception $ex ) {
591
- RaygunManager::get_instance()->exception_handler( $ex );
592
- $with_data = false;
593
- }
594
- }
595
-
596
- $parsed_data = wp_json_encode( $data );
597
- $requestItem->data = is_string( $parsed_data ) ? $parsed_data : '';
598
- $endpoint = EnvironmentHelper::get_app_gateway_url( 'wordpress' ).'/v1.0/wc/trigger';
599
- if ( $with_data )
600
- {
601
- $endpoint = EnvironmentHelper::get_app_gateway_url( 'wordpress' ) . '/v1.0/wc/trigger-with-data';
602
- }
603
-
604
- wp_remote_post(
605
- $endpoint, array(
606
- 'method' => 'POST',
607
- 'timeout' => 10,
608
- 'headers' => array(
609
- 'x-account-id' => OptionsHelper::get_connected_account_id(),
610
- 'x-api-key' => OptionsHelper::get_instance_api_key(),
611
- 'content-type' => 'application/json'
612
- ),
613
- 'body' => wp_json_encode( $requestItem )
614
- )
615
- );
616
- }
617
-
618
- /**
619
- * Initializes email management.
620
- *
621
- * @internal
622
- *
623
- * @since 1.1.0
624
- */
625
- public function manage_emails()
626
- {
627
- if ( empty( $this->managed_email_notifications ) || ! is_array( $this->managed_email_notifications) ) {
628
- return;
629
- }
630
-
631
- // Disable managed emails.
632
- foreach ( $this->managed_email_notifications as $notification )
633
- {
634
- if ( $this->is_email_managed( $notification->name ) ) {
635
- add_filter( "woocommerce_email_enabled_". $notification->name ."", '__return_false');
636
- }
637
- }
638
-
639
- add_filter( 'woocommerce_email_title', array( $this, 'override_managed_email_title' ), 10, 2 );
640
- add_filter( 'woocommerce_email_description', array( $this, 'override_managed_email_description' ), 10, 2 );
641
- }
642
-
643
-
644
- /**
645
- * Overrides email titles for managed emails.
646
- *
647
- * @param string $title the email title
648
- * @param WC_Email $email the email object
649
- *
650
- * @internal
651
- * @since 1.1.0
652
- *
653
- * @return string
654
- */
655
- public function override_managed_email_title( $title, $email )
656
- {
657
- if ( !empty( $email->id ) && $this->is_email_managed( $email->id ) ) {
658
- $title .= __( ' (Managed by Creative Mail)', 'ce4wp' );
659
- }
660
-
661
- return $title;
662
- }
663
-
664
-
665
- /**
666
- * Overrides email description for managed emails.
667
- *
668
- * @param string $description description text
669
- * @param WC_Email $email the email object
670
- *
671
- * @internal
672
- * @since 1.1.0
673
- * @return string
674
- */
675
- public function override_managed_email_description( $description, $email )
676
- {
677
- if ( !empty( $email->id ) && $this->is_email_managed( $email->id ) ) {
678
- $description .= __( ' This email is being managed and sent by Creative Mail.', 'ce4wp' );
679
- }
680
-
681
- return $description;
682
- }
683
-
684
- /**
685
- * Redirects the settings page of a managed email to the CreativeMail transactional notification for that email.
686
- *
687
- * @param WC_Email $email the email object
688
- *
689
- * @since 1.1.0
690
- */
691
- public function redirect_managed_email_settings_to_creative_mail( $email )
692
- {
693
- if ( $this->is_email_managed( $email->id ) ) {
694
- $url = CreativeMail::get_instance()->get_admin_manager()->request_single_sign_on_url_internal( "66eabdb1-5d55-4bc0-a435-0415c5ada60a", array(
695
- "woocommerceTemplateSlug" => $email->id
696
- ) );
697
- wp_redirect( $url );
698
- exit;
699
- }
700
-
701
- if ( $email->id === 'cart_abandoned_ce4wp' ) {
702
- $url = CreativeMail::get_instance()->get_admin_manager()->request_single_sign_on_url_internal( "1fabdbe2-95ed-4e1e-a2f3-ba0278f5096f", array (
703
- "source" => "woocommerce_emails"
704
- ));
705
- wp_redirect( $url );
706
- exit;
707
- }
708
- }
709
-
710
- /**
711
- * Checks if a given email ID is being managed by CreativeMail and is active.
712
- *
713
- * @param string $email_id woocommerce email ID
714
- *
715
- * @since 1.1.0
716
- * @return bool
717
- */
718
- public function is_email_managed( $email_id )
719
- {
720
- return ( bool ) $this->get_managed_notification_param( $email_id, 'active' );
721
- }
722
-
723
- /**
724
- * Gets a param from the managed email notification for the given email ID.
725
- *
726
- * @param string $email_id woocommerce email ID
727
- * @param string $param param name
728
- *
729
- * @since 1.1.0
730
- *
731
- * @return mixed|null
732
- */
733
- public function get_managed_notification_param( $email_id, $param )
734
- {
735
- foreach( $this->managed_email_notifications as $managed_email_notification ) {
736
- if ( $email_id == $managed_email_notification->name && property_exists( $managed_email_notification, $param ) ) {
737
- return $managed_email_notification->$param;
738
- }
739
- }
740
- return null;
741
- }
742
-
743
- /**
744
- * Gets the managed email notification for the given email ID.
745
- *
746
- * @param array $items managed email notifications
747
- * @param string $email_id woocommerce email ID
748
- *
749
- * @since 1.1.0
750
- * @return mixed|null
751
- */
752
- public function get_managed_notification( $items, $email_id )
753
- {
754
-
755
- foreach( $items as $managed_email_notification ) {
756
- if ( $email_id == $managed_email_notification->name ) {
757
- return $managed_email_notification;
758
- }
759
- }
760
- return null;
761
- }
762
-
763
- /**
764
- * Gets the transactional notification ID for a given notification.
765
- *
766
- * @param string $email_id woocommerce email ID
767
- *
768
- * @since 1.1.0
769
- *
770
- * @return int|null
771
- */
772
- public function get_transactional_notification_id( $email_id )
773
- {
774
- return $this->get_managed_notification_param( $email_id, 'transactional_notification_id' );
775
- }
776
-
777
- /**
778
- * Gets the transactional notification state.
779
- *
780
- * @param string $email_id woocommerce email ID
781
- *
782
- * @return string|null
783
- * @since 1.1.0
784
- */
785
- public function get_managed_notification_state( $email_id )
786
- {
787
-
788
- return $this->get_managed_notification_param( $email_id, 'state' );
789
- }
790
-
791
- public function get_valid_email_notification_names()
792
- {
793
- return $this->valid_email_notification_names;
794
- }
795
-
796
- private function get_view_order_url( $order_id, $order )
797
- {
798
- try {
799
- if (!isset( $order )) {
800
- $order = wc_get_order( $order_id );
801
- }
802
-
803
- if (isset( $order ) && is_object($order) && method_exists( $order, 'get_view_order_url' ) ) {
804
- return $order->get_view_order_url();
805
- }
806
- } catch ( Exception $exception ) {
807
- RaygunManager::get_instance()->exception_handler( $exception );
808
- }
809
-
810
- return null;
811
- }
812
-
813
- private function get_my_account_url()
814
- {
815
- try {
816
- return wc_get_page_permalink( 'myaccount' );
817
- } catch ( Exception $exception ) {
818
- RaygunManager::get_instance()->exception_handler( $exception );
819
- }
820
-
821
- return null;
822
- }
823
-
824
- private function get_customer_data( $customer_id )
825
- {
826
- try {
827
- $customer = new WC_Customer( $customer_id );
828
-
829
- $data = $customer->get_data();
830
-
831
- if ($data[ 'date_created' ] != null) {
832
- $data[ 'date_created' ] = $customer->get_date_created();
833
- if (!empty($data[ 'date_created' ]) && is_a($data[ 'date_created' ], 'WC_DateTime')) {
834
- $data[ 'date_created' ] = $data[ 'date_created' ]->getTimestamp();
835
- }
836
- }
837
- if ($data[ 'date_modified' ] != null) {
838
- $data[ 'date_modified' ] = $customer->get_date_modified();
839
- if (!empty($data[ 'date_modified' ]) && is_a($data[ 'date_modified' ], 'WC_DateTime')) {
840
- $data[ 'date_modified' ] = $data[ 'date_modified' ]->getTimestamp();
841
- }
842
- }
843
-
844
- return $data;
845
- } catch ( Exception $exception ) {
846
- RaygunManager::get_instance()->exception_handler( $exception );
847
- }
848
- return null;
849
- }
850
  }
4
  namespace CreativeMail\Managers;
5
 
6
  use CreativeMail\CreativeMail;
 
7
  use CreativeMail\Models\CustomerNewAccount;
8
  use CreativeMail\Models\CustomerNote;
9
  use CreativeMail\Models\CustomerResetPassword;
21
  *
22
  * @package CreativeMail\Managers
23
  */
24
+ class EmailManager {
25
+
26
+ /**
27
+ * Email ids being managed by CreativeMail
28
+ *
29
+ * @var array
30
+ */
31
+ protected $managed_email_notifications;
32
+
33
+ private $valid_email_notification_names = array(
34
+ 'customer_completed_order',
35
+ 'customer_refunded_order',
36
+ 'customer_processing_order',
37
+ 'customer_on_hold_order',
38
+ 'customer_new_account',
39
+ 'customer_reset_password',
40
+ 'customer_invoice',
41
+ 'customer_note',
42
+ 'cart_abandoned_ce4wp',
43
+ );
44
+
45
+ const CHECKOUT_CONSENT_CHECKBOX_ID = 'ce4wp_checkout_consent_checkbox';
46
+ const CHECKOUT_CONSENT_CHECKBOX_VALUE = 'ce4wp_checkout_consent';
47
+
48
+ public function __construct() {
49
+ $this->managed_email_notifications = $this->get_managed_email_notifications();
50
+ }
51
+
52
+ public function add_hooks() {
53
+ // Check if woocommerce is active.
54
+ if ( in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins'))) ) {
55
+ add_action('init', array( $this, 'manage_emails' ));
56
+
57
+ // Email settings table customizations.
58
+ add_filter('woocommerce_email_setting_columns', array( $this, 'customize_email_setting_columns' ));
59
+ add_action('woocommerce_email_setting_column_wc_ce_status', array( $this, 'render_email_status_column' ));
60
+ add_action('woocommerce_email_settings_before', array( $this, 'redirect_managed_email_settings_to_creative_mail' ));
61
+
62
+ // Woocommerce hooks.
63
+ add_action('woocommerce_new_order', array( $this, 'ce_email_notification_new_order' ), 10, 2);
64
+ add_action('woocommerce_order_status_cancelled', array( $this, 'ce_email_notification_cancelled' ), 10, 2);
65
+ add_action('woocommerce_order_status_failed', array( $this, 'ce_email_notification_failed' ), 10, 2);
66
+ add_action('woocommerce_order_status_on-hold', array( $this, 'ce_email_notification_hold' ), 10, 2);
67
+ add_action('woocommerce_order_status_processing', array( $this, 'ce_email_notification_processing' ), 10, 2);
68
+ add_action('woocommerce_order_status_completed', array( $this, 'ce_email_notification_completed' ), 10, 2);
69
+ add_action('woocommerce_order_status_refunded', array( $this, 'ce_email_notification_refunded' ), 10, 2);
70
+ add_action('woocommerce_after_resend_order_email', array( $this, 'ce_email_notification_invoice' ), 10, 2);
71
+
72
+ // Payment complete.
73
+ add_action('woocommerce_payment_complete', array( $this, 'ce_email_notification_payment_complete' ), 10, 1);
74
+ // New customer Note.
75
+ add_action('woocommerce_new_customer_note', array( $this, 'ce_email_notification_new_customer_note' ), 10, 2);
76
+ // Password reset.
77
+ add_action('woocommerce_reset_password_notification', array( $this, 'ce_email_notification_customer_reset_password' ), 10, 2);
78
+ add_action('woocommerce_created_customer', array( $this, 'ce_email_notification_customer_new_account' ), 10, 3);
79
+ // Replace WC Email settings.
80
+ add_filter('woocommerce_email_settings', array( $this, 'replace_wc_email_settings' ));
81
+ add_action('woocommerce_admin_field_ce_manage_button', array( $this, 'print_ce_manage_button' ));
82
+ // Add checkbox to check out if enabled.
83
+ if ( OptionsHelper::get_checkout_checkbox_enabled() == '1' ) {
84
+ add_filter('woocommerce_after_order_notes', array( $this, 'add_checkout_field' ));
85
+ add_action('woocommerce_checkout_update_order_meta', array( $this, 'ce4wp_checkout_order_meta' ));
86
+ }
87
+ // Modify emails emails.
88
+ add_filter( 'woocommerce_email_classes', array( $this, 'add_emails' ), 20 );
89
+ }
90
+ }
91
+
92
+ public function add_emails( $email_classes ) {
93
+ // Add fake email.
94
+ $email_classes['AbandonedCartEmail'] = new AbandonedCartEmail();
95
+ return $email_classes;
96
+ }
97
+
98
+ public function ce4wp_checkout_order_meta( $order_id ) {
99
+ if ( isset( $_REQUEST['woocommerce-process-checkout-nonce'] )
100
+ && wp_verify_nonce(
101
+ sanitize_text_field( wp_unslash ( $_REQUEST['woocommerce-process-checkout-nonce'] ) ),
102
+ 'woocommerce-process_checkout')
103
+ ) {
104
+ if ( isset($_POST[ self::CHECKOUT_CONSENT_CHECKBOX_ID ]) ) {
105
+ $checkbox_value = esc_attr(sanitize_text_field ( wp_unslash( $_POST[ self::CHECKOUT_CONSENT_CHECKBOX_ID ] ) ) );
106
+ } else {
107
+ $checkbox_value = '0';
108
+ }
109
+ update_post_meta($order_id, self::CHECKOUT_CONSENT_CHECKBOX_VALUE, $checkbox_value);
110
+ }
111
+ }
112
+
113
+ public function add_checkout_field( $checkout ) {
114
+ $checked = $checkout->get_value(self::CHECKOUT_CONSENT_CHECKBOX_ID) ? $checkout->get_value(self::CHECKOUT_CONSENT_CHECKBOX_ID) : 0;
115
+ $checkbox_text = stripslashes(OptionsHelper::get_checkout_checkbox_text());
116
+
117
+ woocommerce_form_field(
118
+ self::CHECKOUT_CONSENT_CHECKBOX_ID, array(
119
+ 'type' => 'checkbox',
120
+ 'class' => array( 'ce-field form-row-wide' ),
121
+ 'label' => $checkbox_text,
122
+ ), $checked
123
+ );
124
+ }
125
+
126
+ public function replace_wc_email_settings( $settings ) {
127
+ $default_setting_replacement = array(
128
+ 'woocommerce_email_header_image' => 'header_image',
129
+ 'woocommerce_email_footer_text' => 'footer_content_text',
130
+ 'woocommerce_email_base_color' => null,
131
+ 'woocommerce_email_background_color' => 'background_color',
132
+ 'woocommerce_email_body_background_color' => 'email_background_color',
133
+ 'woocommerce_email_text_color' => 'text_color',
134
+ );
135
+
136
+ // Define options that need to be replaced.
137
+ $replace = array_merge(array_keys($default_setting_replacement), array( 'email_template_options' ));
138
+
139
+ // Remove settings.
140
+ foreach ( $settings as $setting_key => $setting ) {
141
+ if ( isset($setting['id']) && in_array($setting['id'], $replace, true) ) {
142
+ unset($settings[ $setting_key ]);
143
+ }
144
+ }
145
+
146
+ $settings[] = array(
147
+ 'id' => 'ce_manage',
148
+ 'type' => 'title',
149
+ 'title' => __('Creative Mail', 'creative-mail-by-constant-contact'),
150
+ );
151
+
152
+ $settings[] = array(
153
+ 'id' => 'ce_manage_button',
154
+ 'type' => 'ce_manage_button',
155
+ );
156
+
157
+ $settings[] = array(
158
+ 'id' => 'ce_manage',
159
+ 'type' => 'sectionend',
160
+ );
161
+ return $settings;
162
+ }
163
+
164
+ public function print_ce_manage_button( $options ) { ?>
165
+ <tr valign="top">
166
+ <th scope="row" class="titledesc"><?php esc_html_e('Customize Emails', 'creative-mail-by-constant-contact'); ?></th>
167
+ <td class="forminp forminp-<?php echo esc_attr( sanitize_title($options['type']) ); ?>">
168
+ <a href="<?php echo esc_url( admin_url( 'admin.php?page=creativemail' ) ); ?>">
169
+ <button type="button" class="button button-secondary" value="<?php esc_attr_e('Manage', 'creative-mail-by-constant-contact'); ?>">
170
+ <?php esc_html_e('Manage', 'creative-mail-by-constant-contact'); ?>
171
+ </button>
172
+ </a>
173
+ <p class="description">
174
+ <?php esc_html_e('Manage all your email settings and templates with Creative Mail', 'creative-mail-by-constant-contact'); ?>
175
+ </p>
176
+ </td>
177
+ </tr>
178
+ <?php
179
+ }
180
+
181
+ public function get_managed_email_notifications() {
182
+ return OptionsHelper::get_managed_email_notifications();
183
+ }
184
+
185
+ public function set_managed_email_notifications( $body ) {
186
+ if ( empty($body) ) {
187
+ return null;
188
+ }
189
+
190
+ if ( property_exists($body, 'name') && in_array( $body->name, $this->valid_email_notification_names, true ) ) {
191
+ OptionsHelper::set_managed_email_notification($body->name, true == $body->active ? true : false);
192
+ return $body;
193
+ }
194
+
195
+ return null;
196
+ }
197
+
198
+ /**
199
+ * Renders the custom email status column.
200
+ *
201
+ * @param WC_Email $email the email.
202
+ *
203
+ * @internal
204
+ * @since 1.1.0
205
+ */
206
+ public function render_email_status_column( WC_Email $email ) {
207
+
208
+ echo '<td class="wc-email-settings-table-status">';
209
+
210
+ if ( $this->is_email_managed($email->id) ) {
211
+ echo '<span class="status-creativemail tips" data-tip="' . esc_attr__('Managed by Creative Mail', 'creative-mail-by-constant-contact') . '">' . esc_html__('Managed by CreativeMail', 'creative-mail-by-constant-contact') . '</span>';
212
+ } elseif ( 'cart_abandoned_ce4wp' === $email->id ) {
213
+ echo '<span class="status-disabled tips" data-tip="' . esc_attr__('Disabled', 'woocommerce') . '">-</span>';
214
+ } elseif ( $email->is_manual() ) {
215
+ echo '<span class="status-manual tips" data-tip="' . esc_attr__('Manually sent', 'woocommerce') . '">' . esc_html__('Manual', 'woocommerce') . '</span>';
216
+ } elseif ( $email->is_enabled() ) {
217
+ echo '<span class="status-enabled tips" data-tip="' . esc_attr__('Enabled', 'woocommerce') . '">' . esc_html__('Yes', 'woocommerce') . '</span>';
218
+ } else {
219
+ echo '<span class="status-disabled tips" data-tip="' . esc_attr__('Disabled', 'woocommerce') . '">-</span>';
220
+ }
221
+
222
+ echo '</td>';
223
+ }
224
+
225
+ public function customize_email_setting_columns( $columns ) {
226
+
227
+ $column_keys = array_keys($columns);
228
+
229
+ // Replace the status column, or put at the beginning if status isn't found.
230
+ $status_index = array_search('status', $column_keys, true);
231
+ array_splice($column_keys, is_numeric($status_index) ? $status_index : 0, is_numeric($status_index) ? 1 : 0, 'wc_ce_status');
232
+
233
+ $new_columns = array();
234
+ $columns['wc_ce_status'] = '';
235
+
236
+ foreach ( $column_keys as $column_key ) {
237
+ if ( isset($columns[ $column_key ]) ) {
238
+ $new_columns[ $column_key ] = $columns[ $column_key ];
239
+ }
240
+ }
241
+
242
+ return $new_columns;
243
+ }
244
+
245
+ public function ce_email_notification_new_customer_note( $array ) {
246
+ $data = new CustomerNote();
247
+ $data->order_id = $array['order_id'];
248
+ $data->note = $array['customer_note'];
249
+ $data->order_url = $this->get_view_order_url( $data->order_id, null );
250
+
251
+ $this->execute_trigger( 'customer_note', $data, wc_get_order( $data->order_id ) );
252
+ }
253
+
254
+ public function ce_email_notification_customer_new_account( $customer_id, $new_customer_data, $password_generated ) {
255
+ $data = new CustomerNewAccount();
256
+ $data->customer_id = $customer_id;
257
+ $data->account_url = $this->get_my_account_url();
258
+ $data->customer = $this->get_customer_data( $customer_id );
259
+
260
+ if ( $password_generated && key_exists( 'user_pass', $new_customer_data ) ) {
261
+ try {
262
+ $salted = '';
263
+ $dx = '';
264
+ $salt = null;
265
+
266
+ $generated_password = $new_customer_data['user_pass'];
267
+ $key = sha1( OptionsHelper::get_instance_api_key() . OptionsHelper::get_instance_uuid() );
268
+ $openssl_cipher_iv_length = openssl_cipher_iv_length( 'aes-256-cbc' );
269
+
270
+ if ( ! is_bool( $openssl_cipher_iv_length ) ) {
271
+ $salt = openssl_random_pseudo_bytes( $openssl_cipher_iv_length );
272
+ }
273
+ if ( ! empty($salt) && is_string( $salt ) ) {
274
+ $salt_len = strlen( $salted ) < 48;
275
+ while ( $salt_len ) {
276
+ $dx = md5( $dx . $key . $salt, true );
277
+ $salted .= $dx;
278
+ $salt_len = strlen( $salted ) < 48;
279
+ }
280
+ }
281
+ $key = substr( $salted, 0, 32 );
282
+ $iv = substr( $salted, 32, 16 );
283
+ $gp = openssl_encrypt( $generated_password, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv );
284
+ $data->salt = bin2hex( is_string($salt) ? $salt : '' );
285
+ $data->generated_password = base64_encode( is_string($gp) ? $gp : '' );
286
+ } catch ( Exception $ex ) {
287
+ RaygunManager::get_instance()->exception_handler( $ex );
288
+ }
289
+ }
290
+
291
+ $this->execute_trigger( 'customer_new_account', $data, null, true );
292
+ }
293
+
294
+ public function ce_email_notification_customer_reset_password( $user_login = '', $reset_key = '' ) {
295
+ if ( $user_login && $reset_key ) {
296
+ $data = new CustomerResetPassword();
297
+ $user = get_user_by( 'login', $user_login );
298
+ if ( ! empty($user) ) {
299
+ $data->customer_id = $user->ID;
300
+ $data->customer = $this->get_customer_data($user->ID);
301
+ }
302
+ $data->account_url = $this->get_my_account_url();
303
+ $data->reset_url = add_query_arg(
304
+ array(
305
+ 'key' => $reset_key,
306
+ 'id' => $data->customer_id,
307
+ ), wc_get_endpoint_url( 'lost-password', '', $data->account_url )
308
+ );
309
+
310
+ $this->execute_trigger( 'customer_reset_password', $data, null, true );
311
+ }
312
+ }
313
+
314
+ public function ce_email_notification_payment_complete( $order_id ) {
315
+ $data = new EmailNotification();
316
+ $data->order_id = $order_id;
317
+ $data->order_url = $this->get_view_order_url( $order_id, null );
318
+
319
+ $this->execute_trigger( 'payment_received', $data, wc_get_order( $order_id ) );
320
+ }
321
+
322
+ public function ce_email_notification_failed( $order_id, $order ) {
323
+ $data = new EmailNotification();
324
+ $data->order_id = $order_id;
325
+ $data->order_url = $this->get_view_order_url( $order_id, $order );
326
+
327
+ $this->execute_trigger( 'failed_order', $data, $order );
328
+ }
329
+ public function ce_email_notification_hold( $order_id, $order ) {
330
+ $data = new EmailNotification();
331
+ $data->order_id = $order_id;
332
+ $data->order_url = $this->get_view_order_url( $order_id, $order );
333
+
334
+ $this->execute_trigger( 'customer_on_hold_order', $data, $order );
335
+ }
336
+ public function ce_email_notification_processing( $order_id, $order ) {
337
+ $data = new EmailNotification();
338
+ $data->order_id = $order_id;
339
+ $data->order_url = $this->get_view_order_url( $order_id, $order );
340
+
341
+ $this->execute_trigger( 'customer_processing_order', $data, $order );
342
+ }
343
+ public function ce_email_notification_completed( $order_id, $order ) {
344
+ $data = new EmailNotification();
345
+ $data->order_id = $order_id;
346
+ $data->order_url = $this->get_view_order_url( $order_id, $order );
347
+
348
+ $this->execute_trigger( 'customer_completed_order', $data, $order );
349
+ }
350
+
351
+ public function ce_email_notification_refunded( $order_id, $order ) {
352
+ $data = new EmailNotification();
353
+ $data->order_id = $order_id;
354
+ $data->order_url = $this->get_view_order_url( $order_id, $order );
355
+
356
+ $this->execute_trigger( 'customer_refunded_order', $data, $order );
357
+ }
358
+ public function ce_email_notification_cancelled( $order_id, $order ) {
359
+ $data = new EmailNotification();
360
+ $data->order_id = $order_id;
361
+ $data->order_url = $this->get_view_order_url( $order_id, $order );
362
+
363
+ $this->execute_trigger( 'cancelled_order', $data, $order );
364
+ }
365
+
366
+ public function ce_email_notification_new_order( $order_id, $order ) {
367
+ $data = new EmailNotification();
368
+ $data->order_id = $order_id;
369
+ $data->order_url = $this->get_view_order_url( $order_id, $order );
370
+
371
+ $this->execute_trigger( 'new_order', $data, $order );
372
+ }
373
+
374
+ public function ce_email_notification_invoice( $order, $type ) {
375
+ if ( 'new_order' === $type ) {
376
+ $this->ce_email_notification_new_order( $order->id, $order );
377
+ return;
378
+ }
379
+
380
+ $data = new EmailNotification();
381
+ $data->order_id = $order->get_id();
382
+ $data->order_url = $this->get_view_order_url( $order->get_id(), $order );
383
+
384
+ $this->execute_trigger( 'customer_invoice', $data, $order );
385
+ }
386
+
387
+ public function execute_trigger( $type, $data, $order = null, $with_data = false ) {
388
+ // If not managed do not trigger.
389
+ if ( ! $this->is_email_managed( $type ) ) {
390
+ return;
391
+ }
392
+
393
+ $requestItem = new TriggerExecution();
394
+ $requestItem->type = $type;
395
+ $decimal_point = 2;
396
+
397
+ if ( ! is_null( $order ) ) {
398
+ try {
399
+ $order_data = array(
400
+ 'id' => $order->get_id(),
401
+ 'number' => $order->get_order_number(),
402
+ 'date_created' => $order->get_date_created() ? $order->get_date_created()->getTimestamp() : 0,
403
+ 'date_modified' => $order->get_date_modified() ? $order->get_date_modified()->getTimestamp() : 0,
404
+ 'date_completed' => $order->get_date_completed() ? $order->get_date_completed()->getTimestamp() : 0,
405
+ 'status' => $order->get_status(),
406
+ 'currency' => $order->get_currency(),
407
+ 'currency_symbol' => get_woocommerce_currency_symbol( $order->get_currency()),
408
+ 'total' => wc_format_decimal( $order->get_total(), $decimal_point ),
409
+ 'subtotal' => wc_format_decimal( $order->get_subtotal(), $decimal_point ),
410
+ 'total_line_items_quantity' => $order->get_item_count(),
411
+ 'total_tax' => wc_format_decimal( $order->get_total_tax(), $decimal_point ),
412
+ 'shipping_total' => wc_format_decimal( $order->get_shipping_total(), $decimal_point ),
413
+ 'cart_tax' => wc_format_decimal( $order->get_cart_tax(), $decimal_point ),
414
+ 'shipping_tax' => wc_format_decimal( $order->get_shipping_tax(), $decimal_point ),
415
+ 'discount_total' => wc_format_decimal( $order->get_total_discount(), $decimal_point ),
416
+ 'shipping_methods' => $order->get_shipping_method(),
417
+ 'payment_details' => array(
418
+ 'method_id' => $order->get_payment_method(),
419
+ 'method_title' => $order->get_payment_method_title(),
420
+ 'paid' => ! is_null($order->get_date_paid()),
421
+ ),
422
+ 'billing' => array(
423
+ 'first_name' => $order->get_billing_first_name(),
424
+ 'last_name' => $order->get_billing_last_name(),
425
+ 'company' => $order->get_billing_company(),
426
+ 'address_1' => $order->get_billing_address_1(),
427
+ 'address_2' => $order->get_billing_address_2(),
428
+ 'city' => $order->get_billing_city(),
429
+ 'state' => $order->get_billing_state(),
430
+ 'postcode' => $order->get_billing_postcode(),
431
+ 'country' => $order->get_billing_country(),
432
+ 'email' => $order->get_billing_email(),
433
+ 'phone' => $order->get_billing_phone(),
434
+ ),
435
+ 'shipping' => array(
436
+ 'first_name' => $order->get_shipping_first_name(),
437
+ 'last_name' => $order->get_shipping_last_name(),
438
+ 'company' => $order->get_shipping_company(),
439
+ 'address_1' => $order->get_shipping_address_1(),
440
+ 'address_2' => $order->get_shipping_address_2(),
441
+ 'city' => $order->get_shipping_city(),
442
+ 'state' => $order->get_shipping_state(),
443
+ 'postcode' => $order->get_shipping_postcode(),
444
+ 'country' => $order->get_shipping_country(),
445
+ ),
446
+ 'customer_note' => $order->get_customer_note(),
447
+ 'customer_ip' => $order->get_customer_ip_address(),
448
+ 'customer_user_agent' => $order->get_customer_user_agent(),
449
+ 'customer_id' => $order->get_user_id(),
450
+ 'view_order_url' => $order->get_view_order_url(),
451
+ 'line_items' => array(),
452
+ 'shipping_lines' => array(),
453
+ 'tax_lines' => array(),
454
+ 'fee_lines' => array(),
455
+ 'coupon_lines' => array(),
456
+ );
457
+
458
+ // Add line items.
459
+ foreach ( $order->get_items() as $item_id => $item ) {
460
+ $product = $item->get_product();
461
+ $item_meta = $item->get_formatted_meta_data();
462
+
463
+ foreach ( $item_meta as $key => $values ) {
464
+ $item_meta[ $key ]->label = $values->display_key;
465
+ unset( $item_meta[ $key ]->display_key );
466
+ unset( $item_meta[ $key ]->display_value );
467
+ }
468
+
469
+ try {
470
+
471
+ $product_data = array(
472
+ 'images' => array(),
473
+ 'downloads' => array(),
474
+ );
475
+ $attachment_ids = $product->get_gallery_image_ids();
476
+ foreach ( $attachment_ids as $attachment_id ) {
477
+ $product_data['images'][] = wp_get_attachment_url( $attachment_id );
478
+ }
479
+
480
+ $product_data['on_sale'] = $product->is_on_sale();
481
+ $product_data['sale_price'] = $product->get_sale_price();
482
+ $product_data['regular_price'] = $product->get_regular_price();
483
+
484
+ if ( $product->is_downloadable() ) {
485
+ $item_downloads = $item->get_item_downloads();
486
+ foreach ( $item_downloads as $item_download ) {
487
+ $product_data['downloads'][] = array(
488
+ 'line_item_id' => $item->get_id(),
489
+ 'product_id' => $item->get_product_id(),
490
+ 'download_url' => $item_download['download_url'],
491
+ 'download_file' => $item_download['file'],
492
+ 'download_name' => $item_download['name'],
493
+ 'download_id' => $item_download['id'],
494
+ 'downloads_remaining' => $item_download['downloads_remaining'],
495
+ 'download_access_expires' => wc_format_datetime($item_download['access_expires'], 'U'),
496
+ 'download_limit' => $product->get_download_limit(),
497
+ 'download_expiry' => $product->get_download_expiry(),
498
+ );
499
+ }
500
+ }
501
+ } catch ( Exception $ex ) {
502
+ RaygunManager::get_instance()->exception_handler( $ex );
503
+ }
504
+
505
+ $src = wc_placeholder_img_src();
506
+ $image_id = $product->get_image_id();
507
+ if ( $image_id ) {
508
+ $image_src = wp_get_attachment_image_src( $image_id, 'full' );
509
+ list( $src ) = is_array( $image_src ) ? $image_src : array( '' );
510
+ }
511
+
512
+ $order_data['line_items'][] = array(
513
+ 'id' => $item_id,
514
+ 'subtotal' => wc_format_decimal( $order->get_line_subtotal( $item, false, false ), $decimal_point ),
515
+ 'subtotal_tax' => wc_format_decimal( $item->get_subtotal_tax(), $decimal_point ),
516
+ 'total' => wc_format_decimal( $order->get_line_total( $item, false, false ), $decimal_point ),
517
+ 'total_tax' => wc_format_decimal( $item->get_total_tax(), $decimal_point ),
518
+ 'price' => wc_format_decimal( $order->get_item_total( $item, false, false ), $decimal_point ),
519
+ 'quantity' => $item->get_quantity(),
520
+ 'tax_class' => $item->get_tax_class(),
521
+ 'name' => $item->get_name(),
522
+ 'product_id' => $item->get_product_id(),
523
+ 'product_image' => $src,
524
+ 'product_data' => $product_data,
525
+ 'sku' => is_a($product, 'WC_Product') ? $product->get_sku() : null,
526
+ 'meta' => array_values( $item_meta ),
527
+ 'product_url' => get_the_permalink( $item->get_product_id() ),
528
+ 'variation_id' => $item->get_variation_id(),
529
+ );
530
+ }
531
+
532
+ // Add shipping.
533
+ foreach ( $order->get_shipping_methods() as $shipping_item_id => $shipping_item ) {
534
+ $order_data['shipping_lines'][] = array(
535
+ 'id' => $shipping_item_id,
536
+ 'method_id' => $shipping_item->get_method_id(),
537
+ 'method_title' => $shipping_item->get_name(),
538
+ 'total' => wc_format_decimal( $shipping_item->get_total(), $decimal_point ),
539
+ );
540
+ }
541
+
542
+ // Add taxes.
543
+ foreach ( $order->get_tax_totals() as $tax_code => $tax ) {
544
+ $order_data['tax_lines'][] = array(
545
+ 'id' => $tax->id,
546
+ 'rate_id' => $tax->rate_id,
547
+ 'code' => $tax_code,
548
+ 'title' => $tax->label,
549
+ 'total' => wc_format_decimal($tax->amount, $decimal_point),
550
+ 'compound' => (bool) $tax->is_compound,
551
+ );
552
+ }
553
+
554
+ // Add fees.
555
+ foreach ( $order->get_fees() as $fee_item_id => $fee_item ) {
556
+ $order_data['fee_lines'][] = array(
557
+ 'id' => $fee_item_id,
558
+ 'title' => $fee_item->get_name(),
559
+ 'tax_class' => $fee_item->get_tax_class(),
560
+ 'total' => wc_format_decimal( $order->get_line_total( $fee_item ), $decimal_point ),
561
+ 'total_tax' => wc_format_decimal( $order->get_line_tax( $fee_item ), $decimal_point ),
562
+ );
563
+ }
564
+
565
+ // Add coupons.
566
+ foreach ( $order->get_items( 'coupon' ) as $coupon_item_id => $coupon_item ) {
567
+ $order_data['coupon_lines'][] = array(
568
+ 'id' => $coupon_item_id,
569
+ 'code' => $coupon_item->get_code(),
570
+ 'amount' => wc_format_decimal( $coupon_item->get_discount(), $decimal_point ),
571
+ );
572
+ }
573
+ $data->order = $order_data;
574
+ $with_data = true;
575
+ } catch ( Exception $ex ) {
576
+ RaygunManager::get_instance()->exception_handler( $ex );
577
+ $with_data = false;
578
+ }
579
+ }
580
+
581
+ $parsed_data = wp_json_encode( $data );
582
+ $requestItem->data = is_string( $parsed_data ) ? $parsed_data : '';
583
+ $endpoint = EnvironmentHelper::get_app_gateway_url( 'wordpress/v1.0/wc/trigger' );
584
+ if ( $with_data ) {
585
+ $endpoint = EnvironmentHelper::get_app_gateway_url( 'wordpress/v1.0/wc/trigger-with-data' );
586
+ }
587
+
588
+ wp_remote_post(
589
+ $endpoint, array(
590
+ 'method' => 'POST',
591
+ 'timeout' => 10,
592
+ 'headers' => array(
593
+ 'x-account-id' => OptionsHelper::get_connected_account_id(),
594
+ 'x-api-key' => OptionsHelper::get_instance_api_key(),
595
+ 'content-type' => 'application/json',
596
+ ),
597
+ 'body' => wp_json_encode( $requestItem ),
598
+ )
599
+ );
600
+ }
601
+
602
+ /**
603
+ * Initializes email management.
604
+ *
605
+ * @internal
606
+ *
607
+ * @since 1.1.0
608
+ */
609
+ public function manage_emails() {
610
+ if ( empty( $this->managed_email_notifications ) || ! is_array( $this->managed_email_notifications) ) {
611
+ return;
612
+ }
613
+
614
+ // Disable managed emails.
615
+ foreach ( $this->managed_email_notifications as $notification ) {
616
+ if ( $this->is_email_managed( $notification->name ) ) {
617
+ add_filter( 'woocommerce_email_enabled_' . $notification->name . '', '__return_false');
618
+ }
619
+ }
620
+
621
+ add_filter( 'woocommerce_email_title', array( $this, 'override_managed_email_title' ), 10, 2 );
622
+ add_filter( 'woocommerce_email_description', array( $this, 'override_managed_email_description' ), 10, 2 );
623
+ }
624
+
625
+
626
+ /**
627
+ * Overrides email titles for managed emails.
628
+ *
629
+ * @param string $title the email title.
630
+ * @param WC_Email $email the email object.
631
+ *
632
+ * @internal
633
+ * @since 1.1.0
634
+ *
635
+ * @return string
636
+ */
637
+ public function override_managed_email_title( $title, $email ) {
638
+ if ( ! empty( $email->id ) && $this->is_email_managed( $email->id ) ) {
639
+ $title .= __( ' (Managed by Creative Mail)', 'creative-mail-by-constant-contact' );
640
+ }
641
+
642
+ return $title;
643
+ }
644
+
645
+
646
+ /**
647
+ * Overrides email description for managed emails.
648
+ *
649
+ * @param string $description description text.
650
+ * @param WC_Email $email the email object.
651
+ *
652
+ * @internal
653
+ * @since 1.1.0
654
+ * @return string
655
+ */
656
+ public function override_managed_email_description( $description, $email ) {
657
+ if ( ! empty( $email->id ) && $this->is_email_managed( $email->id ) ) {
658
+ $description .= __( ' This email is being managed and sent by Creative Mail.', 'creative-mail-by-constant-contact' );
659
+ }
660
+
661
+ return $description;
662
+ }
663
+
664
+ /**
665
+ * Redirects the settings page of a managed email to the CreativeMail transactional notification for that email.
666
+ *
667
+ * @param WC_Email $email the email object.
668
+ *
669
+ * @since 1.1.0
670
+ */
671
+ public function redirect_managed_email_settings_to_creative_mail( $email ) {
672
+ if ( $this->is_email_managed( $email->id ) ) {
673
+ $url = CreativeMail::get_instance()->get_admin_manager()->request_single_sign_on_url_internal( '66eabdb1-5d55-4bc0-a435-0415c5ada60a', array(
674
+ 'woocommerceTemplateSlug' => $email->id,
675
+ ) );
676
+ wp_safe_redirect( $url );
677
+ exit;
678
+ }
679
+
680
+ if ( 'cart_abandoned_ce4wp' === $email->id ) {
681
+ $url = CreativeMail::get_instance()->get_admin_manager()->request_single_sign_on_url_internal( '1fabdbe2-95ed-4e1e-a2f3-ba0278f5096f', array(
682
+ 'source' => 'woocommerce_emails',
683
+ ));
684
+ wp_safe_redirect( $url );
685
+ exit;
686
+ }
687
+ }
688
+
689
+ /**
690
+ * Checks if a given email ID is being managed by CreativeMail and is active.
691
+ *
692
+ * @param string $email_id woocommerce email ID.
693
+ *
694
+ * @since 1.1.0
695
+ * @return bool
696
+ */
697
+ public function is_email_managed( $email_id ) {
698
+ return (bool) $this->get_managed_notification_param( $email_id, 'active' );
699
+ }
700
+
701
+ /**
702
+ * Gets a param from the managed email notification for the given email ID.
703
+ *
704
+ * @param string $email_id woocommerce email ID.
705
+ * @param string $param param name.
706
+ *
707
+ * @since 1.1.0
708
+ *
709
+ * @return mixed|null
710
+ */
711
+ public function get_managed_notification_param( $email_id, $param ) {
712
+ foreach ( $this->managed_email_notifications as $managed_email_notification ) {
713
+ if ( $email_id == $managed_email_notification->name && property_exists( $managed_email_notification, $param ) ) {
714
+ return $managed_email_notification->$param;
715
+ }
716
+ }
717
+ return null;
718
+ }
719
+
720
+ /**
721
+ * Gets the managed email notification for the given email ID.
722
+ *
723
+ * @param array $items managed email notifications.
724
+ * @param string $email_id woocommerce email ID.
725
+ *
726
+ * @since 1.1.0
727
+ * @return mixed|null
728
+ */
729
+ public function get_managed_notification( $items, $email_id ) {
730
+
731
+ foreach ( $items as $managed_email_notification ) {
732
+ if ( $email_id == $managed_email_notification->name ) {
733
+ return $managed_email_notification;
734
+ }
735
+ }
736
+ return null;
737
+ }
738
+
739
+ /**
740
+ * Gets the transactional notification ID for a given notification.
741
+ *
742
+ * @param string $email_id woocommerce email ID.
743
+ *
744
+ * @since 1.1.0
745
+ *
746
+ * @return int|null
747
+ */
748
+ public function get_transactional_notification_id( $email_id ) {
749
+ return $this->get_managed_notification_param( $email_id, 'transactional_notification_id' );
750
+ }
751
+
752
+ /**
753
+ * Gets the transactional notification state.
754
+ *
755
+ * @param string $email_id woocommerce email ID.
756
+ *
757
+ * @return string|null
758
+ * @since 1.1.0
759
+ */
760
+ public function get_managed_notification_state( $email_id ) {
761
+
762
+ return $this->get_managed_notification_param( $email_id, 'state' );
763
+ }
764
+
765
+ public function get_valid_email_notification_names() {
766
+ return $this->valid_email_notification_names;
767
+ }
768
+
769
+ private function get_view_order_url( $order_id, $order ) {
770
+ try {
771
+ if ( ! isset( $order ) ) {
772
+ $order = wc_get_order( $order_id );
773
+ }
774
+
775
+ if ( isset( $order ) && is_object($order) && method_exists( $order, 'get_view_order_url' ) ) {
776
+ return $order->get_view_order_url();
777
+ }
778
+ } catch ( Exception $exception ) {
779
+ RaygunManager::get_instance()->exception_handler( $exception );
780
+ }
781
+
782
+ return null;
783
+ }
784
+
785
+ private function get_my_account_url() {
786
+ try {
787
+ return wc_get_page_permalink( 'myaccount' );
788
+ } catch ( Exception $exception ) {
789
+ RaygunManager::get_instance()->exception_handler( $exception );
790
+ }
791
+
792
+ return null;
793
+ }
794
+
795
+ private function get_customer_data( $customer_id ) {
796
+ try {
797
+ $customer = new WC_Customer( $customer_id );
798
+ $data = $customer->get_data();
799
+
800
+ if ( null != $data['date_created'] ) {
801
+ $data['date_created'] = $customer->get_date_created();
802
+ if ( ! empty($data['date_created']) && is_a($data['date_created'], 'WC_DateTime') ) {
803
+ $data['date_created'] = $data['date_created']->getTimestamp();
804
+ }
805
+ }
806
+ if ( null != $data['date_modified'] ) {
807
+ $data['date_modified'] = $customer->get_date_modified();
808
+ if ( ! empty($data['date_modified']) && is_a($data['date_modified'], 'WC_DateTime') ) {
809
+ $data['date_modified'] = $data['date_modified']->getTimestamp();
810
+ }
811
+ }
812
+
813
+ return $data;
814
+ } catch ( Exception $exception ) {
815
+ RaygunManager::get_instance()->exception_handler( $exception );
816
+ }
817
+ return null;
818
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
819
  }
src/Managers/FormManager.php CHANGED
@@ -13,100 +13,94 @@ use Exception;
13
  *
14
  * @package CreativeMail\Managers
15
  */
16
- class FormManager
17
- {
18
- const NONCE = 'nonce';
19
- const DOMAIN = 'ce4wp';
20
- const TELEPHONE = 'telephone';
21
- const FIRSTNAME = 'first_name';
22
- const LASTNAME = 'last_name';
23
- const EMAIL = 'email';
24
- const CONSENT = 'consent';
25
- const LISTID = 'list_id';
26
-
27
- private $creative_mail_client;
28
-
29
- /**
30
- * DashboardWidgetModule constructor.
31
- */
32
- public function __construct()
33
- {
34
- $this->creative_mail_client = new CreativeMailClient();
35
- }
36
-
37
- /**
38
- * Add hooks
39
- *
40
- * @since 1.4.0+
41
- */
42
- public function add_hooks()
43
- {
44
- add_action('wp_ajax_ce4wp_form_submission', array($this, 'submit_contact'));
45
- add_action('wp_ajax_nopriv_ce4wp_form_submission', array($this, 'submit_contact'));
46
- add_action('wp_ajax_ce4wp_get_all_custom_lists', array($this, 'get_all_custom_lists'));
47
- add_action('wp_ajax_ce4wp_creative_email_activated', array($this, 'get_creative_email_activated'));
48
- }
49
-
50
-
51
- /**
52
- * AJAX handler for subscribed contact.
53
- *
54
- * @since 1.4.0+
55
- */
56
- public function submit_contact()
57
- {
58
- $data = filter_input_array(INPUT_POST, [
59
- self::NONCE => FILTER_SANITIZE_STRING,
60
- self::FIRSTNAME => FILTER_SANITIZE_STRING,
61
- self::TELEPHONE => FILTER_SANITIZE_STRING,
62
- self::LASTNAME => FILTER_SANITIZE_STRING,
63
- self::EMAIL => FILTER_SANITIZE_EMAIL,
64
- self::CONSENT => FILTER_SANITIZE_STRING,
65
- self::LISTID => FILTER_SANITIZE_STRING
66
- ]);
67
-
68
- if (is_array($data) && (empty($data[self::NONCE]) || !wp_verify_nonce($data[self::NONCE], 'ce4wp_form_submission'))) {
69
- wp_send_json_error(esc_html__('Invalid nonce.', self::DOMAIN));
70
- }
71
-
72
- do_action('ce4wp_contact_submission', $data);
73
-
74
- try {
75
- // Insert submission into database.
76
- CreativeMail::get_instance()->get_database_manager()->insert_contact($data);
77
- } catch (Exception $exception) {
78
- RaygunManager::get_instance()->exception_handler($exception);
79
- }
80
-
81
- wp_send_json_success();
82
- }
83
-
84
- public function get_all_custom_lists()
85
- {
86
- $data = filter_input_array(INPUT_POST, [
87
- self::NONCE => FILTER_SANITIZE_STRING
88
- ]);
89
- if (is_array($data) && (empty($data[self::NONCE]) || !wp_verify_nonce($data[self::NONCE], 'ce4wp_get_lists'))) {
90
- wp_send_json_error(esc_html__('Invalid nonce.', self::DOMAIN));
91
- }
92
- $list = $this->creative_mail_client->get_all_custom_lists();
93
- if(isset($list)) {
94
- wp_send_json_success($list);
95
- }
96
- else {
97
- wp_send_json_error(esc_html__('Could not retrieve data.', self::DOMAIN));
98
- }
99
- }
100
-
101
- public function get_creative_email_activated()
102
- {
103
- $data = filter_input_array(INPUT_POST, [
104
- self::NONCE => FILTER_SANITIZE_STRING
105
- ]);
106
-
107
- if (is_array($data) && (empty($data[self::NONCE]) || !wp_verify_nonce($data[self::NONCE], 'ce4wp_get_creative_email_activated'))) {
108
- wp_send_json_error(esc_html__('Invalid nonce.', self::DOMAIN));
109
- }
110
- wp_send_json_success(OptionsHelper::get_instance_id() != null);
111
- }
112
  }
13
  *
14
  * @package CreativeMail\Managers
15
  */
16
+ class FormManager {
17
+
18
+ const NONCE = 'nonce';
19
+ const DOMAIN = 'creative-mail-by-constant-contact';
20
+ const TELEPHONE = 'telephone';
21
+ const FIRSTNAME = 'first_name';
22
+ const LASTNAME = 'last_name';
23
+ const EMAIL = 'email';
24
+ const CONSENT = 'consent';
25
+ const LISTID = 'list_id';
26
+
27
+ private $creative_mail_client;
28
+
29
+ /**
30
+ * DashboardWidgetModule constructor.
31
+ */
32
+ public function __construct() {
33
+ $this->creative_mail_client = new CreativeMailClient();
34
+ }
35
+
36
+ /**
37
+ * Add hooks
38
+ *
39
+ * @since 1.4.0+
40
+ */
41
+ public function add_hooks() {
42
+ add_action('wp_ajax_ce4wp_form_submission', array( $this, 'submit_contact' ));
43
+ add_action('wp_ajax_nopriv_ce4wp_form_submission', array( $this, 'submit_contact' ));
44
+ add_action('wp_ajax_ce4wp_get_all_custom_lists', array( $this, 'get_all_custom_lists' ));
45
+ add_action('wp_ajax_ce4wp_creative_email_activated', array( $this, 'get_creative_email_activated' ));
46
+ }
47
+
48
+
49
+ /**
50
+ * AJAX handler for subscribed contact.
51
+ *
52
+ * @since 1.4.0+
53
+ */
54
+ public function submit_contact() {
55
+ $data = filter_input_array(INPUT_POST, array(
56
+ self::NONCE => FILTER_SANITIZE_STRING,
57
+ self::FIRSTNAME => FILTER_SANITIZE_STRING,
58
+ self::TELEPHONE => FILTER_SANITIZE_STRING,
59
+ self::LASTNAME => FILTER_SANITIZE_STRING,
60
+ self::EMAIL => FILTER_SANITIZE_EMAIL,
61
+ self::CONSENT => FILTER_SANITIZE_STRING,
62
+ self::LISTID => FILTER_SANITIZE_STRING,
63
+ ));
64
+
65
+ if ( is_array($data) && ( empty($data[ self::NONCE ]) || ! wp_verify_nonce($data[ self::NONCE ], 'ce4wp_form_submission') ) ) {
66
+ wp_send_json_error(esc_html__('Invalid nonce.', self::DOMAIN));
67
+ }
68
+
69
+ do_action('ce4wp_contact_submission', $data);
70
+
71
+ try {
72
+ // Insert submission into database.
73
+ CreativeMail::get_instance()->get_database_manager()->insert_contact($data);
74
+ } catch ( Exception $exception ) {
75
+ RaygunManager::get_instance()->exception_handler($exception);
76
+ }
77
+
78
+ wp_send_json_success();
79
+ }
80
+
81
+ public function get_all_custom_lists() {
82
+ $data = filter_input_array(INPUT_POST, array(
83
+ self::NONCE => FILTER_SANITIZE_STRING,
84
+ ));
85
+ if ( is_array($data) && ( empty($data[ self::NONCE ]) || ! wp_verify_nonce($data[ self::NONCE ], 'ce4wp_get_lists') ) ) {
86
+ wp_send_json_error(esc_html__('Invalid nonce.', self::DOMAIN));
87
+ }
88
+ $list = $this->creative_mail_client->get_all_custom_lists();
89
+ if ( isset($list) ) {
90
+ wp_send_json_success($list);
91
+ } else {
92
+ wp_send_json_error(esc_html__('Could not retrieve data.', self::DOMAIN));
93
+ }
94
+ }
95
+
96
+ public function get_creative_email_activated() {
97
+ $data = filter_input_array(INPUT_POST, array(
98
+ self::NONCE => FILTER_SANITIZE_STRING,
99
+ ));
100
+
101
+ if ( is_array($data) && ( empty($data[ self::NONCE ]) || ! wp_verify_nonce($data[ self::NONCE ], 'ce4wp_get_creative_email_activated') ) ) {
102
+ wp_send_json_error(esc_html__('Invalid nonce.', self::DOMAIN));
103
+ }
104
+ wp_send_json_success(OptionsHelper::get_instance_id() != null);
105
+ }
 
 
 
 
 
 
106
  }
src/Managers/InstanceManager.php CHANGED
@@ -5,6 +5,8 @@ namespace CreativeMail\Managers;
5
 
6
  use CreativeMail\CreativeMail;
7
  use CreativeMail\Helpers\OptionsHelper;
 
 
8
  use WP_Error;
9
 
10
  /**
@@ -12,42 +14,42 @@ use WP_Error;
12
  *
13
  * @package CreativeMail\Managers
14
  */
15
- class InstanceManager
16
- {
17
- public function __construct()
18
- {
19
-
20
- }
21
-
22
- public function add_hooks()
23
- {
24
-
25
- }
26
-
27
- /**
28
- * Handles the callback from the WordPress API and will store all the instance details.
29
- *
30
- * @param $request
31
- *
32
- * @return bool|WP_Error
33
- */
34
- public function handle_callback($request)
35
- {
36
- $account_information = json_decode($request->get_body());
37
- if ($account_information === null) {
38
- return new WP_Error('rest_bad_request', 'Invalid account details', array('status' => 400));
39
- }
40
-
41
- // Store the account information in the settings
42
- OptionsHelper::set_instance_id($account_information->site_id);
43
- OptionsHelper::set_instance_api_key($account_information->api_key);
44
- OptionsHelper::set_connected_account_id($account_information->account_id);
45
-
46
- // refresh woo commerce api key
47
- if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
48
- CreativeMail::get_instance()->get_api_manager()->refresh_key();
49
- }
50
-
51
- return true;
52
- }
53
  }
5
 
6
  use CreativeMail\CreativeMail;
7
  use CreativeMail\Helpers\OptionsHelper;
8
+ use Defuse\Crypto\Exception\BadFormatException;
9
+ use Defuse\Crypto\Exception\EnvironmentIsBrokenException;
10
  use WP_Error;
11
 
12
  /**
14
  *
15
  * @package CreativeMail\Managers
16
  */
17
+ class InstanceManager {
18
+
19
+ public function __construct() {
20
+
21
+ }
22
+
23
+ public function add_hooks() {
24
+
25
+ }
26
+
27
+ /**
28
+ * Handles the callback from the WordPress API and will store all the instance details.
29
+ *
30
+ * @param array $request The request from the WordPress API.
31
+ *
32
+ * @return bool|WP_Error
33
+ *
34
+ * @throws BadFormatException
35
+ * @throws EnvironmentIsBrokenException
36
+ */
37
+ public function handle_callback( $request ) {
38
+ $account_information = json_decode($request->get_body());
39
+ if ( null === $account_information ) {
40
+ return new WP_Error('rest_bad_request', 'Invalid account details', array( 'status' => 400 ));
41
+ }
42
+
43
+ // Store the account information in the settings.
44
+ OptionsHelper::set_instance_id($account_information->site_id);
45
+ OptionsHelper::set_instance_api_key($account_information->api_key);
46
+ OptionsHelper::set_connected_account_id($account_information->account_id);
47
+
48
+ // Refresh woo commerce api key.
49
+ if ( in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')), true) ) {
50
+ CreativeMail::get_instance()->get_api_manager()->refresh_key();
51
+ }
52
+
53
+ return true;
54
+ }
55
  }
src/Managers/IntegrationManager.php CHANGED
@@ -28,189 +28,182 @@ use ReflectionClass;
28
  *
29
  * @package CreativeMail\Managers
30
  */
31
- class IntegrationManager
32
- {
33
- private $supported_integrations;
34
- private $active_integrations;
35
-
36
- public function __construct()
37
- {
38
- $this->active_integrations = array();
39
- $environment = strtolower(EnvironmentHelper::get_environment());
40
- // Set up the default integrations.
41
- $this->supported_integrations = array(
42
- new Integration('jetpack', 'Jetpack Forms', 'jetpack/jetpack.php', JetpackPluginHandler::class, false),
43
- new Integration('jetpack-beta', 'Jetpack Forms (Beta)', 'jetpack-beta-master/jetpack-beta.php', JetpackPluginHandler::class, true),
44
- new Integration('woocommerce', 'WooCommerce', 'woocommerce/woocommerce.php', WooCommercePluginHandler::class, false),
45
- new Integration('contact-form-7', 'Contact Form 7', 'contact-form-7/wp-contact-form-7.php', ContactFormSevenPluginHandler::class, false),
46
- new Integration('newsletter', 'Newsletter', 'newsletter/plugin.php', NewsLetterContactFormPluginHandler::class, false),
47
- new Integration('wpforms', 'WPForms', 'wpforms/wpforms.php', WpFormsPluginHandler::class, false, 'https://wpforms.com/'),
48
- new Integration('wpformslite', 'WPForms Lite', 'wpforms-lite/wpforms.php', WpFormsPluginHandler::class, true, admin_url('plugin-install.php?tab=plugin-information&plugin=wpforms-lite&TB_iframe=true&width=772&height=1144')),
49
- new Integration('gravityforms', 'Gravity Forms', 'gravityforms/gravityforms.php', GravityFormsPluginHandler::class, false, 'https://www.gravityforms.com/'),
50
- new Integration('elementor', 'Elementor', 'elementor/elementor.php', ElementorPluginHandler::class, false),
51
- new Integration('ninjaforms', 'Ninja Forms', 'ninja-forms/ninja-forms.php', NinjaFormsPluginHandler::class, false, admin_url('plugin-install.php?tab=plugin-information&plugin=ninja-forms&TB_iframe=true&width=772&height=1144')),
52
- new Integration('caldera', 'Caldera Forms', 'caldera-forms/caldera-core.php', CalderaPluginHandler::class, false, admin_url('plugin-install.php?tab=plugin-information&plugin=caldera-forms&TB_iframe=true&width=772&height=1144')),
53
- new Integration('bluehost', 'Bluehost Builder', "wb4wp-wordpress-plugin-bluehost-$environment/wb4wp-plugin.php", BlueHostBuilderPluginHandler::class, false, 'https://www.bluehost.com/'),
54
- new Integration('formidable', 'Formidable', 'formidable/formidable.php', FormidablePluginHandler::class, false, admin_url('plugin-install.php?tab=plugin-information&plugin=formidable&TB_iframe=true&width=772&height=1144')),
55
- new Integration('creativemail', 'CreativeMail', 'creativ-email-wordpress-plugin/creative-mail-plugin.php', CreativeMailPluginHandler::class, true, null, true, true)
56
- );
57
- }
58
-
59
- /**
60
- * Will register all the required hooks for this manager.
61
- */
62
- public function add_hooks()
63
- {
64
- $active_plugins = array_filter(
65
- $this->get_active_plugins(), function ($item) {
66
- return array_search($item->get_slug(), $this->get_activated_plugins(), true) !== false;
67
- });
68
-
69
- foreach ($active_plugins as $active_plugin) {
70
- try {
71
- if (array_key_exists($active_plugin->get_slug(), $this->active_integrations) === false) {
72
- // Use reflection to create instance of class.
73
- $class = new ReflectionClass($active_plugin->get_integration_handler());
74
- $this->active_integrations[$active_plugin->get_slug()] = $class->newInstance();
75
- }
76
- // Register hooks for integration class.
77
- $this->active_integrations[$active_plugin->get_slug()]->registerHooks();
78
- } catch (Exception $e) {
79
- RaygunManager::get_instance()->exception_handler($e);
80
- }
81
- }
82
- }
83
-
84
- /**
85
- * Will remove all the registered hooks.
86
- */
87
- public function remove_hooks()
88
- {
89
- foreach ($this->active_integrations as $active_integration) {
90
- $active_integration->unregisterHooks();
91
- }
92
- }
93
-
94
- /**
95
- * Will get all the supported plugins that are installed and active on this WP instance.
96
- *
97
- * @return array
98
- */
99
- public function get_active_plugins()
100
- {
101
- $activated_plugins = array();
102
-
103
- foreach ($this->supported_integrations as $integration) {
104
- $activePlugins = $integration->use_basename()
105
- ? array_map('basename', apply_filters('active_plugins', get_option('active_plugins')))
106
- : apply_filters('active_plugins', get_option('active_plugins'));
107
- // Check if the plugin is activated.
108
- if (in_array($integration->get_class(), $activePlugins)) {
109
- array_push($activated_plugins, $integration);
110
- }
111
- }
112
-
113
- if (count(array_filter($activated_plugins, function ($item) {
114
- return $item->get_slug() == 'creativemail';
115
- })) == 0) {
116
- $x = array_filter($this->supported_integrations, function($item) {return $item->get_slug() == 'creativemail';});
117
- array_push($activated_plugins, array_pop($x));
118
- }
119
- return $activated_plugins;
120
- }
121
-
122
- public function is_plugin_active($slug)
123
- {
124
- return array_key_exists($slug, $this->active_integrations);
125
- }
126
-
127
- /**
128
- * Stores the plugins that were activated by the user.
129
- *
130
- * @param $plugins
131
- */
132
- public function set_activated_plugins($plugins)
133
- {
134
- // Store the activated plugins.
135
- OptionsHelper::set_activated_plugins(implode(';', $plugins));
136
-
137
- // Remove the hooks and add them again.
138
- $this->remove_hooks();
139
- $this->add_hooks();
140
-
141
- do_action(CE4WP_SYNCHRONIZE_ACTION);
142
- }
143
-
144
- /**
145
- * Gets a list of slugs representing the plugins that were activated by the user.
146
- *
147
- * @return array
148
- */
149
- public function get_activated_plugins()
150
- {
151
- $activated_plugins = OptionsHelper::get_activated_plugins();
152
- if ( empty( $activated_plugins) ) {
153
- $activated_plugins = '';
154
- }
155
- if (is_array($activated_plugins)) {
156
- $activated_plugins = implode(';', $activated_plugins);
157
- }
158
- $plugins = explode(';', $activated_plugins);
159
- array_push($plugins, 'creativemail');
160
- return $plugins;
161
- }
162
-
163
- /**
164
- * Will return a list of the activated integrations.
165
- *
166
- * @return array
167
- */
168
- public function get_activated_integrations()
169
- {
170
- return array_filter(
171
- $this->get_active_plugins(), function ($item) {
172
- return array_search($item->get_slug(), $this->get_activated_plugins(), true) !== false;
173
- }
174
- );
175
- }
176
-
177
- /**
178
- * Will get all the supported plugins that are installed and active on this WP instance.
179
- *
180
- * @return array
181
- */
182
- private function get_not_installed()
183
- {
184
- $supported_plugins = array();
185
- foreach ($this->supported_integrations as $integration) {
186
- $activePlugins = $integration->use_basename()
187
- ? array_map('basename', apply_filters('active_plugins', get_option('active_plugins')))
188
- : apply_filters('active_plugins', get_option('active_plugins'));
189
-
190
- // Check if the plugin is activated
191
- if (!in_array($integration->get_class(), $activePlugins)) {
192
- array_push($supported_plugins, $integration);
193
- }
194
- }
195
-
196
- return $supported_plugins;
197
- }
198
-
199
- /**
200
- * Will return a list of all the integrations that we support.
201
- *
202
- * @return array A list of all the supported integrations.
203
- */
204
- public function get_supported_integrations($filter_on_already_installed = false)
205
- {
206
- if ($filter_on_already_installed) {
207
- return $this->get_not_installed();
208
- }
209
- return $this->supported_integrations;
210
- }
211
-
212
- public function get_permalinks_enabled()
213
- {
214
- return get_option('permalink_structure') !== '';
215
- }
216
  }
28
  *
29
  * @package CreativeMail\Managers
30
  */
31
+ class IntegrationManager {
32
+
33
+ private $supported_integrations;
34
+ private $active_integrations;
35
+
36
+ public function __construct() {
37
+ $this->active_integrations = array();
38
+ $environment = strtolower(EnvironmentHelper::get_environment());
39
+ // Set up the default integrations.
40
+ $this->supported_integrations = array(
41
+ new Integration('jetpack', 'Jetpack Forms', 'jetpack/jetpack.php', JetpackPluginHandler::class, false),
42
+ new Integration('jetpack-beta', 'Jetpack Forms (Beta)', 'jetpack-beta-master/jetpack-beta.php', JetpackPluginHandler::class, true),
43
+ new Integration('woocommerce', 'WooCommerce', 'woocommerce/woocommerce.php', WooCommercePluginHandler::class, false),
44
+ new Integration('contact-form-7', 'Contact Form 7', 'contact-form-7/wp-contact-form-7.php', ContactFormSevenPluginHandler::class, false),
45
+ new Integration('newsletter', 'Newsletter', 'newsletter/plugin.php', NewsLetterContactFormPluginHandler::class, false),
46
+ new Integration('wpforms', 'WPForms', 'wpforms/wpforms.php', WpFormsPluginHandler::class, false, 'https://wpforms.com/'),
47
+ new Integration('wpformslite', 'WPForms Lite', 'wpforms-lite/wpforms.php', WpFormsPluginHandler::class, true, admin_url('plugin-install.php?tab=plugin-information&plugin=wpforms-lite&TB_iframe=true&width=772&height=1144')),
48
+ new Integration('gravityforms', 'Gravity Forms', 'gravityforms/gravityforms.php', GravityFormsPluginHandler::class, false, 'https://www.gravityforms.com/'),
49
+ new Integration('elementor', 'Elementor', 'elementor/elementor.php', ElementorPluginHandler::class, false),
50
+ new Integration('ninjaforms', 'Ninja Forms', 'ninja-forms/ninja-forms.php', NinjaFormsPluginHandler::class, false, admin_url('plugin-install.php?tab=plugin-information&plugin=ninja-forms&TB_iframe=true&width=772&height=1144')),
51
+ new Integration('caldera', 'Caldera Forms', 'caldera-forms/caldera-core.php', CalderaPluginHandler::class, false, admin_url('plugin-install.php?tab=plugin-information&plugin=caldera-forms&TB_iframe=true&width=772&height=1144')),
52
+ new Integration('bluehost', 'Bluehost Builder', "wb4wp-wordpress-plugin-bluehost-$environment/wb4wp-plugin.php", BlueHostBuilderPluginHandler::class, false, 'https://www.bluehost.com/'),
53
+ new Integration('formidable', 'Formidable', 'formidable/formidable.php', FormidablePluginHandler::class, false, admin_url('plugin-install.php?tab=plugin-information&plugin=formidable&TB_iframe=true&width=772&height=1144')),
54
+ new Integration('creativemail', 'CreativeMail', 'creativ-email-wordpress-plugin/creative-mail-plugin.php', CreativeMailPluginHandler::class, true, null, true, true),
55
+ );
56
+ }
57
+
58
+ /**
59
+ * Will register all the required hooks for this manager.
60
+ */
61
+ public function add_hooks() {
62
+ $active_plugins = array_filter(
63
+ $this->get_active_plugins(), function ( $item ) {
64
+ return array_search($item->get_slug(), $this->get_activated_plugins(), true) !== false;
65
+ });
66
+
67
+ foreach ( $active_plugins as $active_plugin ) {
68
+ try {
69
+ if ( array_key_exists($active_plugin->get_slug(), $this->active_integrations) === false ) {
70
+ // Use reflection to create instance of class.
71
+ $class = new ReflectionClass($active_plugin->get_integration_handler());
72
+ $this->active_integrations[ $active_plugin->get_slug() ] = $class->newInstance();
73
+ }
74
+ // Register hooks for integration class.
75
+ $this->active_integrations[ $active_plugin->get_slug() ]->registerHooks();
76
+ } catch ( Exception $e ) {
77
+ RaygunManager::get_instance()->exception_handler($e);
78
+ }
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Will remove all the registered hooks.
84
+ */
85
+ public function remove_hooks() {
86
+ foreach ( $this->active_integrations as $active_integration ) {
87
+ $active_integration->unregisterHooks();
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Will get all the supported plugins that are installed and active on this WP instance.
93
+ *
94
+ * @return array
95
+ */
96
+ public function get_active_plugins() {
97
+ $activated_plugins = array();
98
+
99
+ foreach ( $this->supported_integrations as $integration ) {
100
+ $activePlugins = $integration->use_basename()
101
+ ? array_map('basename', apply_filters('active_plugins', get_option('active_plugins')))
102
+ : apply_filters('active_plugins', get_option('active_plugins'));
103
+ // Check if the plugin is activated.
104
+ if ( in_array($integration->get_class(), $activePlugins, true) ) {
105
+ array_push($activated_plugins, $integration);
106
+ }
107
+ }
108
+
109
+ if ( count(array_filter($activated_plugins, function ( $item ) {
110
+ return $item->get_slug() == 'creativemail';
111
+ })) == 0 ) {
112
+ $x = array_filter($this->supported_integrations, function( $item ) {
113
+ return $item->get_slug() == 'creativemail';
114
+ });
115
+ array_push($activated_plugins, array_pop($x));
116
+ }
117
+ return $activated_plugins;
118
+ }
119
+
120
+ public function is_plugin_active( $slug ) {
121
+ return array_key_exists($slug, $this->active_integrations);
122
+ }
123
+
124
+ /**
125
+ * Stores the plugins that were activated by the user.
126
+ *
127
+ * @param array $plugins The plugins that were activated.
128
+ */
129
+ public function set_activated_plugins( $plugins ) {
130
+ // Store the activated plugins.
131
+ OptionsHelper::set_activated_plugins(implode(';', $plugins));
132
+
133
+ // Remove the hooks and add them again.
134
+ $this->remove_hooks();
135
+ $this->add_hooks();
136
+
137
+ do_action(CE4WP_SYNCHRONIZE_ACTION);
138
+ }
139
+
140
+ /**
141
+ * Gets a list of slugs representing the plugins that were activated by the user.
142
+ *
143
+ * @return array
144
+ */
145
+ public function get_activated_plugins() {
146
+ $activated_plugins = OptionsHelper::get_activated_plugins();
147
+ if ( empty( $activated_plugins) ) {
148
+ $activated_plugins = '';
149
+ }
150
+ if ( is_array($activated_plugins) ) {
151
+ $activated_plugins = implode(';', $activated_plugins);
152
+ }
153
+ $plugins = explode(';', $activated_plugins);
154
+ array_push($plugins, 'creativemail');
155
+ return $plugins;
156
+ }
157
+
158
+ /**
159
+ * Will return a list of the activated integrations.
160
+ *
161
+ * @return array
162
+ */
163
+ public function get_activated_integrations() {
164
+ return array_filter(
165
+ $this->get_active_plugins(), function ( $item ) {
166
+ return array_search($item->get_slug(), $this->get_activated_plugins(), true) !== false;
167
+ }
168
+ );
169
+ }
170
+
171
+ /**
172
+ * Will get all the supported plugins that are installed and active on this WP instance.
173
+ *
174
+ * @return array
175
+ */
176
+ private function get_not_installed() {
177
+ $supported_plugins = array();
178
+ foreach ( $this->supported_integrations as $integration ) {
179
+ $activePlugins = $integration->use_basename()
180
+ ? array_map('basename', apply_filters('active_plugins', get_option('active_plugins')))
181
+ : apply_filters('active_plugins', get_option('active_plugins'));
182
+
183
+ // Check if the plugin is activated.
184
+ if ( ! in_array($integration->get_class(), $activePlugins, true) ) {
185
+ array_push($supported_plugins, $integration);
186
+ }
187
+ }
188
+
189
+ return $supported_plugins;
190
+ }
191
+
192
+ /**
193
+ * Will return a list of all the integrations that we support.
194
+ *
195
+ * @param bool $filter_on_already_installed If true, will filter out the plugins that are already installed.
196
+ *
197
+ * @return array A list of all the supported integrations.
198
+ */
199
+ public function get_supported_integrations( $filter_on_already_installed = false ) {
200
+ if ( $filter_on_already_installed ) {
201
+ return $this->get_not_installed();
202
+ }
203
+ return $this->supported_integrations;
204
+ }
205
+
206
+ public function get_permalinks_enabled() {
207
+ return get_option('permalink_structure') !== '';
208
+ }
 
 
 
 
 
 
 
209
  }
src/Managers/RaygunManager.php CHANGED
@@ -11,92 +11,87 @@ use Raygun4php\RaygunClient;
11
  *
12
  * @package CreativeMail\Managers
13
  */
14
- final class RaygunManager
15
- {
16
- // Let's make this a singleton.
17
- private static $instance;
18
- private $raygun_client;
19
-
20
- /**
21
- * RaygunManager constructor.
22
- */
23
- public function __construct()
24
- {
25
- $this->raygun_client = new RaygunClient(CE4WP_RAYGUN_PHP_KEY);
26
- }
27
-
28
- /**
29
- * Transmits an error to the Raygun.io API
30
- *
31
- * @param int $err_no The error number
32
- * @param string $err_str The error string
33
- * @param string $err_file The file the error occurred in
34
- * @param int $err_line The line the error occurred on
35
- */
36
- function error_handler($err_no, $err_str, $err_file, $err_line)
37
- {
38
- $this->raygun_client->SendError($err_no, $err_str, $err_file, $err_line, self::build_tags(), self::build_custom_user_data());
39
- }
40
-
41
- /**
42
- * Transmits an exception to the Raygun.io API
43
- *
44
- * @param Exception $exception An exception object to transmit
45
- */
46
- function exception_handler($exception)
47
- {
48
- $this->raygun_client->SendException($exception, self::build_tags(), self::build_custom_user_data());
49
- }
50
-
51
- /**
52
- * Builds the tags to be sent to Raygun.io
53
- *
54
- * @throws Exception
55
- */
56
- function build_tags()
57
- {
58
- $tags = [];
59
- $tags['CE4WP_PLUGIN_VERSION'] = CE4WP_PLUGIN_VERSION;
60
- $tags['CE4WP_ENVIRONMENT'] = CE4WP_ENVIRONMENT;
61
- $tags['CE4WP_BUILD'] = CE4WP_BUILD_NUMBER;
62
- return $tags;
63
- }
64
-
65
- /**
66
- * Builds the custom user data to be sent to Raygun.io
67
- *
68
- * @throws Exception
69
- */
70
- function build_custom_user_data()
71
- {
72
- $userData = [];
73
-
74
- try {
75
- // Get as much metadata as possible.
76
- $userData['CE4WP_APP_URL'] = CE4WP_APP_URL;
77
- $userData['CE4WP_APP_GATEWAY_URL'] = CE4WP_APP_GATEWAY_URL;
78
-
79
- // User data that helps us identify the error.
80
- $userData['CE4WP_CONNECTED_ACCOUNT_ID'] = get_option(CE4WP_CONNECTED_ACCOUNT_ID);
81
- $userData['CE4WP_INSTANCE_UUID_KEY'] = get_option(CE4WP_INSTANCE_UUID_KEY);
82
- $userData['CE4WP_MANAGED_EMAIL_NOTIFICATIONS'] = get_option(CE4WP_MANAGED_EMAIL_NOTIFICATIONS);
83
- $userData['CE4WP_ACTIVATED_PLUGINS'] = get_option(CE4WP_ACTIVATED_PLUGINS);
84
-
85
- } catch (Exception $e) {
86
- // We don't want to throw an exception here, as this is just a helper function.
87
- // We'll just log the error and move on.
88
- error_log($e->getMessage());
89
- }
90
-
91
- return $userData;
92
- }
93
-
94
- public static function get_instance()
95
- {
96
- if (self::$instance === null) {
97
- self::$instance = new RaygunManager();
98
- }
99
-
100
- return self::$instance;
101
- }
102
  }
11
  *
12
  * @package CreativeMail\Managers
13
  */
14
+ final class RaygunManager {
15
+
16
+ /**
17
+ * The RaygunManager instance.
18
+ *
19
+ * @var RaygunManager
20
+ */
21
+ private static $instance;
22
+
23
+ /**
24
+ * The RaygunClient instance.
25
+ *
26
+ * @var RaygunClient
27
+ */
28
+ private $raygun_client;
29
+
30
+ /**
31
+ * RaygunManager constructor.
32
+ */
33
+ public function __construct() {
34
+ $this->raygun_client = new RaygunClient(CE4WP_RAYGUN_PHP_KEY);
35
+ }
36
+
37
+ /**
38
+ * Transmits an exception to the Raygun.io API
39
+ *
40
+ * @param Exception $exception An exception object to transmit.
41
+ *
42
+ * @return void
43
+ */
44
+ public function exception_handler( Exception $exception ): void {
45
+ $this->raygun_client->SendException($exception, self::build_tags(), self::build_custom_user_data());
46
+ }
47
+
48
+ /**
49
+ * Builds the tags to be sent to Raygun.io
50
+ *
51
+ * @return array<string, string>
52
+ */
53
+ public function build_tags(): array {
54
+ $tags = array();
55
+ $tags['CE4WP_PLUGIN_VERSION'] = CE4WP_PLUGIN_VERSION;
56
+ $tags['CE4WP_ENVIRONMENT'] = CE4WP_ENVIRONMENT;
57
+ $tags['CE4WP_BUILD'] = CE4WP_BUILD_NUMBER;
58
+
59
+ return $tags;
60
+ }
61
+
62
+ /**
63
+ * Builds the custom user data to be sent to Raygun.io
64
+ *
65
+ * @return array<string, mixed>
66
+ */
67
+ private function build_custom_user_data(): array {
68
+ $userData = array();
69
+
70
+ try {
71
+ // Get as much metadata as possible.
72
+ $userData['CE4WP_APP_URL'] = CE4WP_APP_URL;
73
+ $userData['CE4WP_APP_GATEWAY_URL'] = CE4WP_APP_GATEWAY_URL;
74
+
75
+ // User data that helps us identify the error.
76
+ $userData['CE4WP_CONNECTED_ACCOUNT_ID'] = get_option(CE4WP_CONNECTED_ACCOUNT_ID);
77
+ $userData['CE4WP_INSTANCE_UUID_KEY'] = get_option(CE4WP_INSTANCE_UUID_KEY);
78
+ $userData['CE4WP_MANAGED_EMAIL_NOTIFICATIONS'] = get_option(CE4WP_MANAGED_EMAIL_NOTIFICATIONS);
79
+ $userData['CE4WP_ACTIVATED_PLUGINS'] = get_option(CE4WP_ACTIVATED_PLUGINS);
80
+
81
+ } catch ( Exception $e ) {
82
+ // We don't want to throw an exception here, as this is just a helper function.
83
+ // We'll just log the error and move on.
84
+ error_log($e->getMessage());
85
+ }
86
+
87
+ return $userData;
88
+ }
89
+
90
+ public static function get_instance(): RaygunManager {
91
+ if ( null === self::$instance ) {
92
+ self::$instance = new RaygunManager();
93
+ }
94
+
95
+ return self::$instance;
96
+ }
 
 
 
 
 
97
  }
src/Models/ApiSchema.php CHANGED
@@ -2,30 +2,30 @@
2
 
3
  namespace CreativeMail\Models;
4
 
5
- class ApiSchema
6
- {
7
- /**
8
- * Key used to identify the consumer
9
- *
10
- * @var string
11
- */
12
- public $consumer_key;
13
- /**
14
- * Secret used for the consumer
15
- *
16
- * @var string
17
- */
18
- public $consumer_secret;
19
- /**
20
- * ID of the key
21
- *
22
- * @var int
23
- */
24
- public $key_id;
25
- /**
26
- * ID of the user
27
- *
28
- * @var int
29
- */
30
- public $user_id;
31
  }
2
 
3
  namespace CreativeMail\Models;
4
 
5
+ class ApiSchema {
6
+
7
+ /**
8
+ * Key used to identify the consumer
9
+ *
10
+ * @var string
11
+ */
12
+ public $consumer_key;
13
+ /**
14
+ * Secret used for the consumer
15
+ *
16
+ * @var string
17
+ */
18
+ public $consumer_secret;
19
+ /**
20
+ * ID of the key
21
+ *
22
+ * @var int
23
+ */
24
+ public $key_id;
25
+ /**
26
+ * ID of the user
27
+ *
28
+ * @var int
29
+ */
30
+ public $user_id;
31
  }
src/Models/Campaign.php CHANGED
@@ -2,36 +2,36 @@
2
 
3
  namespace CreativeMail\Models;
4
 
5
- class Campaign
6
- {
7
- /**
8
- * ID of the campaign
9
- *
10
- * @var string
11
- */
12
- public $id;
13
- /**
14
- * Whether the campaign is active or not
15
- *
16
- * @var bool
17
- */
18
- public $is_draft;
19
- /**
20
- * Name of the campaign
21
- *
22
- * @var string
23
- */
24
- public $name;
25
- /**
26
- * Amount of money the campaign is set to raise
27
- *
28
- * @var float
29
- */
30
- public $open_rate;
31
- /**
32
- * The campaign's status
33
- *
34
- * @var string
35
- */
36
- public $status;
37
  }
2
 
3
  namespace CreativeMail\Models;
4
 
5
+ class Campaign {
6
+
7
+ /**
8
+ * ID of the campaign
9
+ *
10
+ * @var string
11
+ */
12
+ public $id;
13
+ /**
14
+ * Whether the campaign is active or not
15
+ *
16
+ * @var bool
17
+ */
18
+ public $is_draft;
19
+ /**
20
+ * Name of the campaign
21
+ *
22
+ * @var string
23
+ */
24
+ public $name;
25
+ /**
26
+ * Amount of money the campaign is set to raise
27
+ *
28
+ * @var float
29
+ */
30
+ public $open_rate;
31
+ /**
32
+ * The campaign's status
33
+ *
34
+ * @var string
35
+ */
36
+ public $status;
37
  }
src/Models/CartData.php CHANGED
@@ -2,48 +2,54 @@
2
 
3
  namespace CreativeMail\Models;
4
 
5
- class CartData
6
- {
7
- /**
8
- * Coupons array
9
- *
10
- * @var array
11
- */
12
- public $coupons;
13
- /**
14
- * Coupons currency
15
- *
16
- * @var string
17
- */
18
- public $currency;
19
- /**
20
- * Coupons currency symbol
21
- *
22
- * @var string
23
- */
24
- public $currency_symbol;
25
- /**
26
- * Cart items
27
- *
28
- * @var array
29
- */
30
- public $products;
31
- /**
32
- * User data
33
- *
34
- * @var User
35
- */
36
- public $user;
37
- /**
38
- * Cart Shipping Total
39
- *
40
- * @var float
41
- */
42
- public $shipping_total;
43
- /**
44
- * Cart Shipping Taxes
45
- *
46
- * @var array
47
- */
48
- public $shipping_taxes;
 
 
 
 
 
 
49
  }
2
 
3
  namespace CreativeMail\Models;
4
 
5
+ final class CartData {
6
+
7
+ /**
8
+ * Coupons array
9
+ *
10
+ * @var array<Coupon>
11
+ */
12
+ public $coupons;
13
+
14
+ /**
15
+ * Coupons currency
16
+ *
17
+ * @var string
18
+ */
19
+ public $currency;
20
+
21
+ /**
22
+ * Coupons currency symbol
23
+ *
24
+ * @var string
25
+ */
26
+ public $currency_symbol;
27
+
28
+ /**
29
+ * Cart items
30
+ *
31
+ * @var array<string,mixed>
32
+ */
33
+ public $products;
34
+
35
+ /**
36
+ * User data
37
+ *
38
+ * @var User
39
+ */
40
+ public $user;
41
+
42
+ /**
43
+ * Cart Shipping Total
44
+ *
45
+ * @var float
46
+ */
47
+ public $shipping_total;
48
+
49
+ /**
50
+ * Cart Shipping Taxes
51
+ *
52
+ * @var mixed
53
+ */
54
+ public $shipping_taxes;
55
  }
src/Models/Checkout.php CHANGED
@@ -2,36 +2,36 @@
2
 
3
  namespace CreativeMail\Models;
4
 
5
- class Checkout
6
- {
7
- /**
8
- * Order currency
9
- *
10
- * @var string
11
- */
12
- public $order_currency;
13
- /**
14
- * Order Identifier
15
- *
16
- * @var int
17
- */
18
- public $order_id;
19
- /**
20
- * Order total
21
- *
22
- * @var float
23
- */
24
- public $order_total;
25
- /**
26
- * Recovery time
27
- *
28
- * @var string
29
- */
30
- public $recovery_date;
31
- /**
32
- * Universal Identifier
33
- *
34
- * @var string
35
- */
36
- public $uuid;
37
  }
2
 
3
  namespace CreativeMail\Models;
4
 
5
+ class Checkout {
6
+
7
+ /**
8
+ * Order currency
9
+ *
10
+ * @var string
11
+ */
12
+ public $order_currency;
13
+ /**
14
+ * Order Identifier
15
+ *
16
+ * @var int
17
+ */
18
+ public $order_id;
19
+ /**
20
+ * Order total
21
+ *
22
+ * @var float
23
+ */
24
+ public $order_total;
25
+ /**
26
+ * Recovery time
27
+ *
28
+ * @var string
29
+ */
30
+ public $recovery_date;
31
+ /**
32
+ * Universal Identifier
33
+ *
34
+ * @var string
35
+ */
36
+ public $uuid;
37
  }
src/Models/CheckoutSave.php CHANGED
@@ -2,36 +2,36 @@
2
 
3
  namespace CreativeMail\Models;
4
 
5
- class CheckoutSave
6
- {
7
- /**
8
- * Billing email address
9
- *
10
- * @var string|false
11
- */
12
- public $billing_email;
13
- /**
14
- * Checkout data
15
- *
16
- * @var string|false
17
- */
18
- public $data;
19
- /**
20
- * Date timestamp
21
- *
22
- * @var string
23
- */
24
- public $timestamp;
25
- /**
26
- * User ID
27
- *
28
- * @var int
29
- */
30
- public $user_id;
31
- /**
32
- * Universal Identifier
33
- *
34
- * @var string
35
- */
36
- public $uuid;
37
  }
2
 
3
  namespace CreativeMail\Models;
4
 
5
+ class CheckoutSave {
6
+
7
+ /**
8
+ * Billing email address
9
+ *
10
+ * @var string|bool
11
+ */
12
+ public $billing_email;
13
+ /**
14
+ * Checkout data
15
+ *
16
+ * @var string|bool
17
+ */
18
+ public $data;
19
+ /**
20
+ * Date timestamp
21
+ *
22
+ * @var string
23
+ */
24
+ public $timestamp;
25
+ /**
26
+ * User ID
27
+ *
28
+ * @var int
29
+ */
30
+ public $user_id;
31
+ /**
32
+ * Universal Identifier
33
+ *
34
+ * @var string
35
+ */
36
+ public $uuid;
37
  }
src/Models/Coupon.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace CreativeMail\Models;
4
+
5
+ final class Coupon {
6
+
7
+ /**
8
+ * Holds the coupon code.
9
+ *
10
+ * @var string
11
+ */
12
+ public $code;
13
+
14
+ /**
15
+ * Holds the coupon amount.
16
+ *
17
+ * @var float
18
+ */
19
+ public $amount;
20
+
21
+ /**
22
+ * Holds the discount type.
23
+ *
24
+ * @var string
25
+ */
26
+ public $discount_type;
27
+
28
+ /**
29
+ * Holds the coupon description.
30
+ *
31
+ * @var string
32
+ */
33
+ public $description;
34
+
35
+ /**
36
+ * Checks for Free Shipping.
37
+ *
38
+ * @var bool
39
+ */
40
+ public $free_shipping;
41
+
42
+ public function __construct(
43
+ ?string $code,
44
+ ?float $amount,
45
+ ?string $discount_type,
46
+ ?string $description,
47
+ ?bool $free_shipping
48
+ ) {
49
+ $this->code = $code;
50
+ $this->amount = $amount;
51
+ $this->discount_type = $discount_type;
52
+ $this->description = $description;
53
+ $this->free_shipping = $free_shipping;
54
+ }
55
+ }
src/Models/CustomerNewAccount.php CHANGED
@@ -4,36 +4,36 @@ namespace CreativeMail\Models;
4
 
5
  use WC_Customer;
6
 
7
- class CustomerNewAccount
8
- {
9
- /**
10
- * Account URL string
11
- *
12
- * @var string
13
- */
14
- public $account_url;
15
- /**
16
- * Customer object
17
- *
18
- * @var WC_Customer
19
- */
20
- public $customer;
21
- /**
22
- * Customer ID
23
- *
24
- * @var int
25
- */
26
- public $customer_id;
27
- /**
28
- * Customer Password
29
- *
30
- * @var string
31
- */
32
- public $generated_password;
33
- /**
34
- * Salt created for the customer password
35
- *
36
- * @var string
37
- */
38
- public $salt;
39
  }
4
 
5
  use WC_Customer;
6
 
7
+ class CustomerNewAccount {
8
+
9
+ /**
10
+ * Account URL string
11
+ *
12
+ * @var string
13
+ */
14
+ public $account_url;
15
+ /**
16
+ * Customer object
17
+ *
18
+ * @var WC_Customer
19
+ */
20
+ public $customer;
21
+ /**
22
+ * Customer ID
23
+ *
24
+ * @var int
25
+ */
26
+ public $customer_id;
27
+ /**
28
+ * Customer Password
29
+ *
30
+ * @var string
31
+ */
32
+ public $generated_password;
33
+ /**
34
+ * Salt created for the customer password
35
+ *
36
+ * @var string
37
+ */
38
+ public $salt;
39
  }
src/Models/CustomerNote.php CHANGED
@@ -2,24 +2,24 @@
2
 
3
  namespace CreativeMail\Models;
4
 
5
- class CustomerNote
6
- {
7
- /**
8
- * Customer notes
9
- *
10
- * @var string
11
- */
12
- public $note;
13
- /**
14
- * Order ID
15
- *
16
- * @var int
17
- */
18
- public $order_id;
19
- /**
20
- * Order URL string
21
- *
22
- * @var string
23
- */
24
- public $order_url;
25
  }
2
 
3
  namespace CreativeMail\Models;
4
 
5
+ class CustomerNote {
6
+
7
+ /**
8
+ * Customer notes
9
+ *
10
+ * @var string
11
+ */
12
+ public $note;
13
+ /**
14
+ * Order ID
15
+ *
16
+ * @var int
17
+ */
18
+ public $order_id;
19
+ /**
20
+ * Order URL string
21
+ *
22
+ * @var string
23
+ */
24
+ public $order_url;
25
  }
src/Models/CustomerResetPassword.php CHANGED
@@ -4,30 +4,30 @@ namespace CreativeMail\Models;
4
 
5
  use WC_Customer;
6
 
7
- class CustomerResetPassword
8
- {
9
- /**
10
- * Account URL string
11
- *
12
- * @var string
13
- */
14
- public $account_url;
15
- /**
16
- * Customer object
17
- *
18
- * @var WC_Customer
19
- */
20
- public $customer;
21
- /**
22
- * Customer ID
23
- *
24
- * @var int
25
- */
26
- public $customer_id;
27
- /**
28
- * Reset password URL string
29
- *
30
- * @var string
31
- */
32
- public $reset_url;
33
  }
4
 
5
  use WC_Customer;
6
 
7
+ class CustomerResetPassword {
8
+
9
+ /**
10
+ * Account URL string
11
+ *
12
+ * @var string
13
+ */
14
+ public $account_url;
15
+ /**
16
+ * Customer object
17
+ *
18
+ * @var WC_Customer
19
+ */
20
+ public $customer;
21
+ /**
22
+ * Customer ID
23
+ *
24
+ * @var int
25
+ */
26
+ public $customer_id;
27
+ /**
28
+ * Reset password URL string
29
+ *
30
+ * @var string
31
+ */
32
+ public $reset_url;
33
  }
src/Models/EmailNotification.php CHANGED
@@ -2,18 +2,18 @@
2
 
3
  namespace CreativeMail\Models;
4
 
5
- class EmailNotification
6
- {
7
- /**
8
- * Order ID
9
- *
10
- * @var int
11
- */
12
- public $order_id;
13
- /**
14
- * Order URL to view the order
15
- *
16
- * @var string
17
- */
18
- public $order_url;
19
  }
2
 
3
  namespace CreativeMail\Models;
4
 
5
+ class EmailNotification {
6
+
7
+ /**
8
+ * Order ID
9
+ *
10
+ * @var int
11
+ */
12
+ public $order_id;
13
+ /**
14
+ * Order URL to view the order
15
+ *
16
+ * @var string
17
+ */
18
+ public $order_url;
19
  }
src/Models/HashSchema.php CHANGED
@@ -2,30 +2,30 @@
2
 
3
  namespace CreativeMail\Models;
4
 
5
- class HashSchema
6
- {
7
- /**
8
- * Hash key string
9
- *
10
- * @var string
11
- */
12
- public $key;
13
- /**
14
- * Hash salt string
15
- *
16
- * @var string
17
- */
18
- public $salt;
19
- /**
20
- * Hash secret string
21
- *
22
- * @var string
23
- */
24
- public $secret;
25
- /**
26
- * Hash version
27
- *
28
- * @var string
29
- */
30
- public $version;
31
  }
2
 
3
  namespace CreativeMail\Models;
4
 
5
+ class HashSchema {
6
+
7
+ /**
8
+ * Hash key string
9
+ *
10
+ * @var string
11
+ */
12
+ public $key;
13
+ /**
14
+ * Hash salt string
15
+ *
16
+ * @var string
17
+ */
18
+ public $salt;
19
+ /**
20
+ * Hash secret string
21
+ *
22
+ * @var string
23
+ */
24
+ public $secret;
25
+ /**
26
+ * Hash version
27
+ *
28
+ * @var string
29
+ */
30
+ public $version;
31
  }
src/Models/OptionsSchema.php CHANGED
@@ -2,18 +2,18 @@
2
 
3
  namespace CreativeMail\Models;
4
 
5
- class OptionsSchema
6
- {
7
- /**
8
- * Option activation
9
- *
10
- * @var bool
11
- */
12
- public $active;
13
- /**
14
- * Option name
15
- *
16
- * @var string
17
- */
18
- public $name;
19
  }
2
 
3
  namespace CreativeMail\Models;
4
 
5
+ class OptionsSchema {
6
+
7
+ /**
8
+ * Option activation
9
+ *
10
+ * @var bool
11
+ */
12
+ public $active;
13
+ /**
14
+ * Option name
15
+ *
16
+ * @var string
17
+ */
18
+ public $name;
19
  }
src/Models/Order.php CHANGED
@@ -2,36 +2,40 @@
2
 
3
  namespace CreativeMail\Models;
4
 
5
- class Order
6
- {
7
- /**
8
- * Order billing information
9
- *
10
- * @var OrderBilling
11
- */
12
- public $billing;
13
- /**
14
- * Currency string
15
- *
16
- * @var string
17
- */
18
- public $currency;
19
- /**
20
- * Currency symbol
21
- *
22
- * @var string
23
- */
24
- public $currency_symbol;
25
- /**
26
- * Order items
27
- *
28
- * @var array
29
- */
30
- public $line_items;
31
- /**
32
- * Total of items in the order
33
- *
34
- * @var int|string
35
- */
36
- public $total_line_items_quantity;
 
 
 
 
37
  }
2
 
3
  namespace CreativeMail\Models;
4
 
5
+ class Order {
6
+
7
+ /**
8
+ * Order billing information
9
+ *
10
+ * @var OrderBilling
11
+ */
12
+ public $billing;
13
+
14
+ /**
15
+ * Currency string
16
+ *
17
+ * @var string
18
+ */
19
+ public $currency;
20
+
21
+ /**
22
+ * Currency symbol
23
+ *
24
+ * @var string
25
+ */
26
+ public $currency_symbol;
27
+
28
+ /**
29
+ * Order items
30
+ *
31
+ * @var array<OrderLineItem>
32
+ */
33
+ public $line_items;
34
+
35
+ /**
36
+ * Total of items in the order
37
+ *
38
+ * @var int|string
39
+ */
40
+ public $total_line_items_quantity;
41
  }
src/Models/OrderBilling.php CHANGED
@@ -4,108 +4,124 @@ namespace CreativeMail\Models;
4
 
5
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
6
 
7
- class OrderBilling
8
- {
9
- /**
10
- * Order Address Number 1
11
- *
12
- * @var string
13
- */
14
- public $address_1;
15
- /**
16
- * Order Address Number 2
17
- *
18
- * @var string
19
- */
20
- public $address_2;
21
- /**
22
- * Order city
23
- *
24
- * @var string
25
- */
26
- public $city;
27
- /**
28
- * Order company
29
- *
30
- * @var string
31
- */
32
- public $company;
33
- /**
34
- * Order country
35
- *
36
- * @var string
37
- */
38
- public $country;
39
- /**
40
- * Order email address
41
- *
42
- * @var string
43
- */
44
- public $email;
45
- /**
46
- * Order customer first name
47
- *
48
- * @var string
49
- */
50
- public $first_name;
51
- /**
52
- * Variable to check is customer is first buyer
53
- *
54
- * @var bool
55
- */
56
- public $is_first_time_buyer;
57
- /**
58
- * Order customer last name
59
- *
60
- * @var string
61
- */
62
- public $last_name;
63
- /**
64
- * Order customer opt action by
65
- *
66
- * @var OptActionBy
67
- */
68
- public $opt_action_by;
69
- /**
70
- * Order customer opt action by
71
- *
72
- * @var bool|null
73
- */
74
- public $opt_in;
75
- /**
76
- * Order customer opt action by
77
- *
78
- * @var bool|null
79
- */
80
- public $opt_out;
81
- /**
82
- * Order payments details
83
- *
84
- * @var array
85
- */
86
- public $payment_details;
87
- /**
88
- * Order phone number
89
- *
90
- * @var string
91
- */
92
- public $phone;
93
- /**
94
- * Order shipping postcode
95
- *
96
- * @var string
97
- */
98
- public $postcode;
99
- /**
100
- * Order shipping details
101
- *
102
- * @var array
103
- */
104
- public $shipping;
105
- /**
106
- * Order Shipping state
107
- *
108
- * @var string
109
- */
110
- public $state;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  }
4
 
5
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
6
 
7
+ final class OrderBilling {
8
+
9
+ /**
10
+ * Order Address Number 1
11
+ *
12
+ * @var string
13
+ */
14
+ public $address_1;
15
+
16
+ /**
17
+ * Order Address Number 2
18
+ *
19
+ * @var string
20
+ */
21
+ public $address_2;
22
+
23
+ /**
24
+ * Order city
25
+ *
26
+ * @var string
27
+ */
28
+ public $city;
29
+
30
+ /**
31
+ * Order company
32
+ *
33
+ * @var string
34
+ */
35
+ public $company;
36
+
37
+ /**
38
+ * Order country
39
+ *
40
+ * @var string
41
+ */
42
+ public $country;
43
+
44
+ /**
45
+ * Order email address
46
+ *
47
+ * @var string
48
+ */
49
+ public $email;
50
+
51
+ /**
52
+ * Order customer first name
53
+ *
54
+ * @var string
55
+ */
56
+ public $first_name;
57
+
58
+ /**
59
+ * Variable to check is customer is first buyer
60
+ *
61
+ * @var bool
62
+ */
63
+ public $is_first_time_buyer;
64
+
65
+ /**
66
+ * Order customer last name
67
+ *
68
+ * @var string
69
+ */
70
+ public $last_name;
71
+
72
+ /**
73
+ * Order customer opt action by
74
+ *
75
+ * @var OptActionBy
76
+ */
77
+ public $opt_action_by;
78
+
79
+ /**
80
+ * Order customer opt action by
81
+ *
82
+ * @var bool|null
83
+ */
84
+ public $opt_in;
85
+
86
+ /**
87
+ * Order customer opt action by
88
+ *
89
+ * @var bool|null
90
+ */
91
+ public $opt_out;
92
+
93
+ /**
94
+ * Order payments details
95
+ *
96
+ * @var OrderBillingPaymentDetails
97
+ */
98
+ public $payment_details;
99
+
100
+ /**
101
+ * Order phone number
102
+ *
103
+ * @var string
104
+ */
105
+ public $phone;
106
+
107
+ /**
108
+ * Order shipping postcode
109
+ *
110
+ * @var string
111
+ */
112
+ public $postcode;
113
+
114
+ /**
115
+ * Order shipping details
116
+ *
117
+ * @var OrderBillingShipping
118
+ */
119
+ public $shipping;
120
+
121
+ /**
122
+ * Order Shipping state
123
+ *
124
+ * @var string
125
+ */
126
+ public $state;
127
  }
src/Models/OrderBillingPaymentDetails.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace CreativeMail\Models;
4
+
5
+ final class OrderBillingPaymentDetails {
6
+
7
+ /**
8
+ * Holds the payment method.
9
+ *
10
+ * @var string
11
+ */
12
+ public $method_id;
13
+
14
+ /**
15
+ * Holds the payment method title.
16
+ *
17
+ * @var string
18
+ */
19
+ public $method_title;
20
+
21
+ /**
22
+ * Checks if order has been paid or not.
23
+ *
24
+ * @var bool
25
+ */
26
+ public $paid;
27
+
28
+ /**
29
+ * OrderBillingPaymentDetails constructor.
30
+ *
31
+ * @param string $method_id The payment method.
32
+ * @param string $method_title The payment method title.
33
+ * @param bool $paid The payment status.
34
+ */
35
+ public function __construct( string $method_id, string $method_title, bool $paid ) {
36
+ $this->method_id = $method_id;
37
+ $this->method_title = $method_title;
38
+ $this->paid = $paid;
39
+ }
40
+ }
src/Models/OrderBillingShipping.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace CreativeMail\Models;
4
+
5
+ use WC_Order;
6
+
7
+ final class OrderBillingShipping {
8
+
9
+ /**
10
+ * Holds the first address.
11
+ *
12
+ * @var string
13
+ */
14
+ protected $address_1;
15
+
16
+ /**
17
+ * Holds the second address.
18
+ *
19
+ * @var string
20
+ */
21
+ public $address_2;
22
+
23
+ /**
24
+ * Holds the city.
25
+ *
26
+ * @var string
27
+ */
28
+ public $city;
29
+
30
+ /**
31
+ * Holds the company.
32
+ *
33
+ * @var string
34
+ */
35
+ public $company;
36
+
37
+ /**
38
+ * Holds the country.
39
+ *
40
+ * @var string
41
+ */
42
+ public $country;
43
+
44
+ /**
45
+ * Holds the first name.
46
+ *
47
+ * @var string
48
+ */
49
+ public $first_name;
50
+
51
+ /**
52
+ * Holds the last name.
53
+ *
54
+ * @var string
55
+ */
56
+ protected $last_name;
57
+
58
+ /**
59
+ * Holds the postcode.
60
+ *
61
+ * @var string
62
+ */
63
+ public $postcode;
64
+
65
+ /**
66
+ * Holds the shipping method used.
67
+ *
68
+ * @var string
69
+ */
70
+ public $shipping_methods;
71
+
72
+ /**
73
+ * Holds the state.
74
+ *
75
+ * @var string
76
+ */
77
+ public $state;
78
+
79
+ /**
80
+ * OrderBillingShipping constructor.
81
+ *
82
+ * @param WC_Order $woocommerce_order The WooCommerce order.
83
+ */
84
+ public function __construct( WC_Order $woocommerce_order ) {
85
+ $this->address_1 = $woocommerce_order->get_shipping_address_1();
86
+ $this->address_2 = $woocommerce_order->get_shipping_address_2();
87
+ $this->city = $woocommerce_order->get_shipping_city();
88
+ $this->company = $woocommerce_order->get_shipping_company();
89
+ $this->country = $woocommerce_order->get_shipping_country();
90
+ $this->first_name = $woocommerce_order->get_shipping_first_name();
91
+ $this->last_name = $woocommerce_order->get_shipping_last_name();
92
+ $this->shipping_methods = $woocommerce_order->get_shipping_method();
93
+ $this->state = $woocommerce_order->get_shipping_state();
94
+ $this->postcode = $woocommerce_order->get_shipping_postcode();
95
+ }
96
+ }
src/Models/OrderLineItem.php ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace CreativeMail\Models;
4
+
5
+ use WC_Order;
6
+ use WC_Order_Item;
7
+ use WC_Product;
8
+
9
+ final class OrderLineItem {
10
+
11
+ /**
12
+ * Stores the product ID of the order line item.
13
+ *
14
+ * @var int
15
+ */
16
+ public $product_id;
17
+
18
+ /**
19
+ * Stores the product name of the order line item.
20
+ *
21
+ * @var array
22
+ */
23
+ public $item_meta;
24
+
25
+ /**
26
+ * Stores the order subtotal.
27
+ *
28
+ * @var string
29
+ */
30
+ public $subtotal;
31
+
32
+ /**
33
+ * Stores the order subtotal tax.
34
+ *
35
+ * @var string
36
+ */
37
+ public $subtotal_tax;
38
+
39
+ /**
40
+ * Stores the order total.
41
+ *
42
+ * @var string
43
+ */
44
+ public $total;
45
+
46
+ /**
47
+ * Stores the order total tax.
48
+ *
49
+ * @var string
50
+ */
51
+ public $total_tax;
52
+
53
+ /**
54
+ * Stores the product price.
55
+ *
56
+ * @var string
57
+ */
58
+ public $price;
59
+
60
+ /**
61
+ * Stores the product quantity.
62
+ *
63
+ * @var int
64
+ */
65
+ public $quantity;
66
+
67
+ /**
68
+ * Stores the Tax Class.
69
+ *
70
+ * @var string
71
+ */
72
+ public $tax_class;
73
+
74
+ /**
75
+ * Stores the product name.
76
+ *
77
+ * @var string
78
+ */
79
+ public $name;
80
+
81
+ /**
82
+ * Stores the product image.
83
+ *
84
+ * @var string|mixed
85
+ */
86
+ public $product_image;
87
+
88
+ /**
89
+ * Stores the product data.
90
+ *
91
+ * @var array<array<mixed>>
92
+ */
93
+ public $product_data;
94
+
95
+ /**
96
+ * Stores the product SKU.
97
+ *
98
+ * @var string|null
99
+ */
100
+ public $sku;
101
+
102
+ /**
103
+ * Stores the product variation meta.
104
+ *
105
+ * @var array<mixed>
106
+ */
107
+ public $meta;
108
+
109
+ /**
110
+ * Stores the product URL.
111
+ *
112
+ * @var string
113
+ */
114
+ public $product_url;
115
+
116
+ /**
117
+ * Stores the variation ID of the product.
118
+ *
119
+ * @var int
120
+ */
121
+ public $variation_id;
122
+
123
+ /**
124
+ * OrderLineItem constructor.
125
+ *
126
+ * @param WC_Order_Item $woocommerce_item The WooCommerce order item.
127
+ * @param int $decimal_point The decimal point.
128
+ * @param WC_Order $woocommerce_order The WooCommerce order.
129
+ * @param array<mixed> $item_meta The item meta.
130
+ * @param mixed $src The source.
131
+ * @param array<mixed> $product_data The product data.
132
+ * @param WC_Product $woocommerce_product The WooCommerce product.
133
+ */
134
+ public function __construct(
135
+ WC_Order_Item $woocommerce_item,
136
+ int $decimal_point,
137
+ WC_Order $woocommerce_order,
138
+ array $item_meta,
139
+ $src,
140
+ array $product_data,
141
+ WC_Product $woocommerce_product
142
+ ) {
143
+ $this->product_id = $woocommerce_item->get_product_id();
144
+ $this->item_meta = $woocommerce_item->get_formatted_meta_data();
145
+ $this->subtotal = wc_format_decimal(
146
+ $woocommerce_order->get_line_subtotal(
147
+ $woocommerce_item,
148
+ false,
149
+ false
150
+ ), $decimal_point
151
+ );
152
+ $this->subtotal_tax = wc_format_decimal( $woocommerce_item->get_subtotal_tax(), $decimal_point );
153
+ $this->total = wc_format_decimal(
154
+ $woocommerce_order->get_line_total(
155
+ $woocommerce_item,
156
+ false,
157
+ false
158
+ ), $decimal_point
159
+ );
160
+ $this->total_tax = wc_format_decimal( $woocommerce_item->get_total_tax(), $decimal_point );
161
+ $this->price = wc_format_decimal(
162
+ $woocommerce_order->get_item_total(
163
+ $woocommerce_item,
164
+ false,
165
+ false
166
+ ), $decimal_point
167
+ );
168
+ $this->quantity = $woocommerce_item->get_quantity();
169
+ $this->tax_class = $woocommerce_item->get_tax_class();
170
+ $this->name = $woocommerce_item->get_name();
171
+ $this->meta = array_values( $item_meta );
172
+ $this->product_url = get_the_permalink( $woocommerce_item->get_product_id() )
173
+ ? get_the_permalink( $woocommerce_item->get_product_id() )
174
+ : '';
175
+ $this->variation_id = $woocommerce_item->get_variation_id();
176
+ $this->product_image = $src;
177
+ $this->product_data = $product_data;
178
+ $this->sku = is_a($woocommerce_product, 'WC_Product') ? $woocommerce_product->get_sku() : null;
179
+ }
180
+ }
src/Models/RequestItem.php CHANGED
@@ -4,120 +4,120 @@ namespace CreativeMail\Models;
4
 
5
  use WC_DateTime;
6
 
7
- class RequestItem
8
- {
9
- /**
10
- * Cart tax
11
- *
12
- * @var float
13
- */
14
- public $cart_tax;
15
- /**
16
- * Customer ID
17
- *
18
- * @var int
19
- */
20
- public $customer_id;
21
- /**
22
- * Customer IP address
23
- *
24
- * @var string
25
- */
26
- public $customer_ip;
27
- /**
28
- * Customer user agent
29
- *
30
- * @var string
31
- */
32
- public $customer_user_agent;
33
- /**
34
- * Date completed
35
- *
36
- * @var WC_DateTime|NULL
37
- */
38
- public $date_completed;
39
- /**
40
- * Date created
41
- *
42
- * @var WC_DateTime|NULL
43
- */
44
- public $date_created;
45
- /**
46
- * Date modified
47
- *
48
- * @var WC_DateTime|NULL
49
- */
50
- public $date_modified;
51
- /**
52
- * Discount total
53
- *
54
- * @var string
55
- */
56
- public $discount_total;
57
- /**
58
- * Notes
59
- *
60
- * @var string
61
- */
62
- public $note;
63
- /**
64
- * Order object
65
- *
66
- * @var Order
67
- */
68
- public $order;
69
- /**
70
- * Order ID
71
- *
72
- * @var int
73
- */
74
- public $order_id;
75
- /**
76
- * Order number
77
- *
78
- * @var string
79
- */
80
- public $order_number;
81
- /**
82
- * Order URL string
83
- *
84
- * @var string
85
- */
86
- public $order_url;
87
- /**
88
- * Shipping tax value
89
- *
90
- * @var string
91
- */
92
- public $shipping_tax;
93
- /**
94
- * Shipping total
95
- *
96
- * @var string
97
- */
98
- public $shipping_total;
99
- /**
100
- * Request status
101
- *
102
- * @var string
103
- */
104
- public $status;
105
- /**
106
- * Subtotal
107
- *
108
- * @var string
109
- */
110
- public $subtotal;
111
- /**
112
- * Total
113
- *
114
- * @var string
115
- */
116
- public $total;
117
- /**
118
- * Total tax
119
- *
120
- * @var string
121
- */
122
- public $total_tax;
123
  }
4
 
5
  use WC_DateTime;
6
 
7
+ class RequestItem {
8
+
9
+ /**
10
+ * Cart tax
11
+ *
12
+ * @var float
13
+ */
14
+ public $cart_tax;
15
+ /**
16
+ * Customer ID
17
+ *
18
+ * @var int
19
+ */
20
+ public $customer_id;
21
+ /**
22
+ * Customer IP address
23
+ *
24
+ * @var string
25
+ */
26
+ public $customer_ip;
27
+ /**
28
+ * Customer user agent
29
+ *
30
+ * @var string
31
+ */
32
+ public $customer_user_agent;
33
+ /**
34
+ * Date completed
35
+ *
36
+ * @var WC_DateTime|NULL
37
+ */
38
+ public $date_completed;
39
+ /**
40
+ * Date created
41
+ *
42
+ * @var WC_DateTime|NULL
43
+ */
44
+ public $date_created;
45
+ /**
46
+ * Date modified
47
+ *
48
+ * @var WC_DateTime|NULL
49
+ */
50
+ public $date_modified;
51
+ /**
52
+ * Discount total
53
+ *
54
+ * @var string
55
+ */
56
+ public $discount_total;
57
+ /**
58
+ * Notes
59
+ *
60
+ * @var string
61
+ */
62
+ public $note;
63
+ /**
64
+ * Order object
65
+ *
66
+ * @var Order
67
+ */
68
+ public $order;
69
+ /**
70
+ * Order ID
71
+ *
72
+ * @var int
73
+ */
74
+ public $order_id;
75
+ /**
76
+ * Order number
77
+ *
78
+ * @var string
79
+ */
80
+ public $order_number;
81
+ /**
82
+ * Order URL string
83
+ *
84
+ * @var string
85
+ */
86
+ public $order_url;
87
+ /**
88
+ * Shipping tax value
89
+ *
90
+ * @var string
91
+ */
92
+ public $shipping_tax;
93
+ /**
94
+ * Shipping total
95
+ *
96
+ * @var string
97
+ */
98
+ public $shipping_total;
99
+ /**
100
+ * Request status
101
+ *
102
+ * @var string
103
+ */
104
+ public $status;
105
+ /**
106
+ * Subtotal
107
+ *
108
+ * @var string
109
+ */
110
+ public $subtotal;
111
+ /**
112
+ * Total
113
+ *
114
+ * @var string
115
+ */
116
+ public $total;
117
+ /**
118
+ * Total tax
119
+ *
120
+ * @var string
121
+ */
122
+ public $total_tax;
123
  }
src/Models/Response.php CHANGED
@@ -2,12 +2,12 @@
2
 
3
  namespace CreativeMail\Models;
4
 
5
- class Response
6
- {
7
- /**
8
- * Response URL string
9
- *
10
- * @var string
11
- */
12
- public $url;
13
  }
2
 
3
  namespace CreativeMail\Models;
4
 
5
+ class Response {
6
+
7
+ /**
8
+ * Response URL string
9
+ *
10
+ * @var string
11
+ */
12
+ public $url;
13
  }
src/Models/TriggerExecution.php CHANGED
@@ -2,18 +2,18 @@
2
 
3
  namespace CreativeMail\Models;
4
 
5
- class TriggerExecution
6
- {
7
- /**
8
- * Data for the execution of the trigger.
9
- *
10
- * @var string
11
- */
12
- public $data;
13
- /**
14
- * Type of the trigger.
15
- *
16
- * @var string
17
- */
18
- public $type;
19
  }
2
 
3
  namespace CreativeMail\Models;
4
 
5
+ class TriggerExecution {
6
+
7
+ /**
8
+ * Data for the execution of the trigger.
9
+ *
10
+ * @var string
11
+ */
12
+ public $data;
13
+ /**
14
+ * Type of the trigger.
15
+ *
16
+ * @var string
17
+ */
18
+ public $type;
19
  }
src/Models/User.php CHANGED
@@ -2,42 +2,42 @@
2
 
3
  namespace CreativeMail\Models;
4
 
5
- class User
6
- {
7
- /**
8
- * User display name
9
- *
10
- * @var string
11
- */
12
- public $display_name;
13
- /**
14
- * User email address
15
- *
16
- * @var string
17
- */
18
- public $email;
19
- /**
20
- * User first name
21
- *
22
- * @var string
23
- */
24
- public $first_name;
25
- /**
26
- * User ID
27
- *
28
- * @var int
29
- */
30
- public $id;
31
- /**
32
- * User last name
33
- *
34
- * @var string
35
- */
36
- public $last_name;
37
- /**
38
- * User login username
39
- *
40
- * @var string
41
- */
42
- public $username;
43
  }
2
 
3
  namespace CreativeMail\Models;
4
 
5
+ class User {
6
+
7
+ /**
8
+ * User display name
9
+ *
10
+ * @var string
11
+ */
12
+ public $display_name;
13
+ /**
14
+ * User email address
15
+ *
16
+ * @var string
17
+ */
18
+ public $email;
19
+ /**
20
+ * User first name
21
+ *
22
+ * @var string
23
+ */
24
+ public $first_name;
25
+ /**
26
+ * User ID
27
+ *
28
+ * @var int
29
+ */
30
+ public $id;
31
+ /**
32
+ * User last name
33
+ *
34
+ * @var string
35
+ */
36
+ public $last_name;
37
+ /**
38
+ * User login username
39
+ *
40
+ * @var string
41
+ */
42
+ public $username;
43
  }
src/Modules/Api/Models/ApiRequestItem.php CHANGED
@@ -5,28 +5,68 @@ namespace CreativeMail\Modules\Api\Models;
5
  use CreativeMail\Helpers\EnvironmentHelper;
6
  use CreativeMail\Helpers\OptionsHelper;
7
 
8
- class ApiRequestItem
9
- {
10
-
11
- public $httpMethod;
12
- public $contentType;
13
- public $endpoint;
14
- public $payload;
15
- public $apiKey;
16
- public $accountId;
17
-
18
- function __construct($httpMethod, $contentType, $endpoint, $payload)
19
- {
20
-
21
- $apiKey = OptionsHelper::get_instance_api_key();
22
- $accountId = OptionsHelper::get_connected_account_id();
23
- $baseUrl = EnvironmentHelper::get_app_gateway_url('wordpress');
24
-
25
- $this->httpMethod = $httpMethod;
26
- $this->contentType = $contentType;
27
- $this->endpoint = $baseUrl.$endpoint;
28
- $this->payload = $payload;
29
- $this->apiKey = $apiKey;
30
- $this->accountId = $accountId;
31
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  }
5
  use CreativeMail\Helpers\EnvironmentHelper;
6
  use CreativeMail\Helpers\OptionsHelper;
7
 
8
+ final class ApiRequestItem {
9
+
10
+ /**
11
+ * Stores the HTTP method of the request.
12
+ *
13
+ * @var string
14
+ */
15
+ public $httpMethod;
16
+
17
+ /**
18
+ * Stores the content type of the request.
19
+ *
20
+ * @var string
21
+ */
22
+ public $contentType;
23
+
24
+ /**
25
+ * Stores the endpoint of the request.
26
+ *
27
+ * @var string
28
+ */
29
+ public $endpoint;
30
+
31
+ /**
32
+ * Stores the payload of the request.
33
+ *
34
+ * @var string
35
+ */
36
+ public $payload;
37
+
38
+ /**
39
+ * Stores the API Key of the request.
40
+ *
41
+ * @var string
42
+ */
43
+ public $apiKey;
44
+
45
+ /**
46
+ * Stores the Account ID of the request.
47
+ *
48
+ * @var int|null
49
+ */
50
+ public $accountId;
51
+
52
+ /**
53
+ * Main constructor of the API Method.
54
+ *
55
+ * @param string $httpMethod The HTTP method of the request.
56
+ * @param string $contentType The content type of the request.
57
+ * @param string $endpoint The endpoint of the request.
58
+ * @param string $payload The payload of the request.
59
+ */
60
+ public function __construct( string $httpMethod, string $contentType, string $endpoint, string $payload ) {
61
+ $apiKey = OptionsHelper::get_instance_api_key();
62
+ $accountId = OptionsHelper::get_connected_account_id();
63
+ $baseUrl = EnvironmentHelper::get_app_gateway_url('wordpress');
64
+
65
+ $this->httpMethod = $httpMethod;
66
+ $this->contentType = $contentType;
67
+ $this->endpoint = $baseUrl . $endpoint;
68
+ $this->payload = $payload;
69
+ $this->apiKey = $apiKey;
70
+ $this->accountId = $accountId;
71
+ }
72
  }
src/Modules/Api/Processes/ApiBackgroundProcess.php CHANGED
@@ -5,71 +5,73 @@ namespace CreativeMail\Modules\Api\Processes;
5
  use CreativeMail\Modules\Api\Models\ApiRequestItem;
6
  use WP_Background_Process;
7
 
8
- class ApiBackgroundProcess extends WP_Background_Process
9
- {
10
 
11
- protected $action = 'ce_api_background_process';
 
 
 
 
 
12
 
13
- /**
14
- * Task
15
- *
16
- * Override this method to perform any actions required on each
17
- * queue item. Return the modified item for further processing
18
- * in the next pass through. Or, return false to remove the
19
- * item from the queue.
20
- *
21
- * @param ApiRequestItem $item Queue item to iterate over
22
- *
23
- * @return mixed
24
- */
25
- protected function task( $item )
26
- {
27
- if (!isset($item->httpMethod) || empty($item->httpMethod)) {
28
- return false;
29
- }
30
 
31
- if (!isset($item->endpoint) || empty($item->endpoint)) {
32
- return false;
33
- }
34
 
35
- $httpMethod = strtoupper($item->httpMethod);
36
 
37
- if ($httpMethod === 'POST') {
38
- wp_remote_post(
39
- $item->endpoint, array(
40
- 'method' => $httpMethod,
41
- 'headers' => array(
42
- 'x-account-id' => $item->accountId,
43
- 'x-api-key' => $item->apiKey,
44
- 'content-type' => $item->contentType
45
- ),
46
- 'body' => $item->payload
47
- )
48
- );
49
- return false;
50
- }
51
 
52
- wp_remote_get(
53
- $item->endpoint, array(
54
- 'method' => $httpMethod,
55
- 'headers' => array(
56
- 'x-account-id' => $item->accountId,
57
- 'x-api-key' => $item->apiKey,
58
- 'content-type' => $item->contentType
59
- )
60
- )
61
- );
62
- return false;
63
- }
64
 
65
- /**
66
- * Complete
67
- *
68
- * Override if applicable, but ensure that the below actions are
69
- * performed, or, call parent::complete().
70
- */
71
- protected function complete()
72
- {
73
- parent::complete();
74
- }
75
  }
5
  use CreativeMail\Modules\Api\Models\ApiRequestItem;
6
  use WP_Background_Process;
7
 
8
+ final class ApiBackgroundProcess extends WP_Background_Process {
 
9
 
10
+ /**
11
+ * Sets the action name.
12
+ *
13
+ * @var string
14
+ */
15
+ protected $action = 'ce_api_background_process';
16
 
17
+ /**
18
+ * Task
19
+ *
20
+ * Override this method to perform any actions required on each
21
+ * queue item. Return the modified item for further processing
22
+ * in the next pass through. Or, return false to remove the
23
+ * item from the queue.
24
+ *
25
+ * @param ApiRequestItem $item Queue item to iterate over.
26
+ *
27
+ * @return false
28
+ */
29
+ protected function task( $item ): bool {
30
+ if ( ! isset($item->httpMethod) || empty($item->httpMethod) ) {
31
+ return false;
32
+ }
 
33
 
34
+ if ( ! isset($item->endpoint) || empty($item->endpoint) ) {
35
+ return false;
36
+ }
37
 
38
+ $httpMethod = strtoupper($item->httpMethod);
39
 
40
+ if ( 'POST' === $httpMethod ) {
41
+ wp_remote_post(
42
+ $item->endpoint, array(
43
+ 'method' => $httpMethod,
44
+ 'headers' => array(
45
+ 'x-account-id' => $item->accountId,
46
+ 'x-api-key' => $item->apiKey,
47
+ 'content-type' => $item->contentType,
48
+ ),
49
+ 'body' => $item->payload,
50
+ )
51
+ );
52
+ return false;
53
+ }
54
 
55
+ wp_remote_get(
56
+ $item->endpoint, array(
57
+ 'method' => $httpMethod,
58
+ 'headers' => array(
59
+ 'x-account-id' => $item->accountId,
60
+ 'x-api-key' => $item->apiKey,
61
+ 'content-type' => $item->contentType,
62
+ ),
63
+ )
64
+ );
65
+ return false;
66
+ }
67
 
68
+ /**
69
+ * Complete
70
+ *
71
+ * Override if applicable, but ensure that the below actions are
72
+ * performed, or, call parent::complete().
73
+ */
74
+ protected function complete() {
75
+ parent::complete();
76
+ }
 
77
  }
src/Modules/Blog/Models/BlogAttachment.php CHANGED
@@ -2,28 +2,28 @@
2
 
3
  namespace CreativeMail\Modules\Blog\Models;
4
 
5
- class BlogAttachment
6
- {
7
- public $id;
8
- public $date;
9
- public $name;
10
- public $modified;
11
- public $url;
12
- public $thumbnail;
13
- public $meta_data;
14
 
15
- function __construct($wp_attachment)
16
- {
17
- $this->id = $wp_attachment->ID;
18
- $this->name = $wp_attachment->post_title;
19
- $this->date = $wp_attachment->post_date;
20
- $this->modified = $wp_attachment->post_modified;
21
- $this->url = wp_get_attachment_url($wp_attachment->ID);
22
- $this->thumbnail = wp_get_attachment_image_url($wp_attachment->ID, 'medium_large');
23
- $this->meta_data = wp_get_attachment_metadata($wp_attachment->ID);
24
- // in case false on failure
25
- if ($this->meta_data === false) {
26
- $this->meta_data = array();
27
- }
28
- }
 
 
 
 
 
 
 
 
29
  }
2
 
3
  namespace CreativeMail\Modules\Blog\Models;
4
 
5
+ class BlogAttachment {
 
 
 
 
 
 
 
 
6
 
7
+ public $id;
8
+ public $date;
9
+ public $name;
10
+ public $modified;
11
+ public $url;
12
+ public $thumbnail;
13
+ public $meta_data;
14
+
15
+ public function __construct( $wp_attachment ) {
16
+ $this->id = $wp_attachment->ID;
17
+ $this->name = $wp_attachment->post_title;
18
+ $this->date = $wp_attachment->post_date;
19
+ $this->modified = $wp_attachment->post_modified;
20
+ $this->url = wp_get_attachment_url($wp_attachment->ID);
21
+ $this->thumbnail = wp_get_attachment_image_url($wp_attachment->ID, 'medium_large');
22
+ $this->meta_data = wp_get_attachment_metadata($wp_attachment->ID);
23
+
24
+ // In case false on failure.
25
+ if ( false === $this->meta_data ) {
26
+ $this->meta_data = array();
27
+ }
28
+ }
29
  }
src/Modules/Blog/Models/BlogInformation.php CHANGED
@@ -4,38 +4,37 @@ namespace CreativeMail\Modules\Blog\Models;
4
 
5
  use CreativeMail\Modules\WooCommerce\Models\WCStoreInformation;
6
 
7
- class BlogInformation
8
- {
9
- public $plugin_version;
10
- public $title;
11
- public $description;
12
- public $url;
13
- public $admin_email;
14
- public $language;
15
- public $rss2_url;
16
- public $logo;
17
- public $template;
18
 
19
- public $first_name;
20
- public $last_name;
21
- public $company;
22
- public $email;
 
 
 
 
 
23
 
24
- public $woocommerce;
 
 
 
25
 
26
- function __construct()
27
- {
28
- $this->plugin_version = CE4WP_PLUGIN_VERSION;
29
- $this->title = get_bloginfo('name');
30
- $this->description = get_bloginfo('description');
31
- $this->url = get_bloginfo('url');
32
- $this->admin_email = get_bloginfo('admin_email');
33
- $this->language = get_bloginfo('language');
34
- $this->rss2_url = get_bloginfo('rss2_url');
35
- if(has_custom_logo()) {
36
- $this->logo = get_custom_logo();
37
- }
38
- $this->template = get_template();
39
- $this->woocommerce = new WCStoreInformation();
40
- }
 
41
  }
4
 
5
  use CreativeMail\Modules\WooCommerce\Models\WCStoreInformation;
6
 
7
+ class BlogInformation {
 
 
 
 
 
 
 
 
 
 
8
 
9
+ public $plugin_version;
10
+ public $title;
11
+ public $description;
12
+ public $url;
13
+ public $admin_email;
14
+ public $language;
15
+ public $rss2_url;
16
+ public $logo;
17
+ public $template;
18
 
19
+ public $first_name;
20
+ public $last_name;
21
+ public $company;
22
+ public $email;
23
 
24
+ public $woocommerce;
25
+
26
+ public function __construct() {
27
+ $this->plugin_version = CE4WP_PLUGIN_VERSION;
28
+ $this->title = get_bloginfo('name');
29
+ $this->description = get_bloginfo('description');
30
+ $this->url = get_bloginfo('url');
31
+ $this->admin_email = get_bloginfo('admin_email');
32
+ $this->language = get_bloginfo('language');
33
+ $this->rss2_url = get_bloginfo('rss2_url');
34
+ if ( has_custom_logo() ) {
35
+ $this->logo = get_custom_logo();
36
+ }
37
+ $this->template = get_template();
38
+ $this->woocommerce = new WCStoreInformation();
39
+ }
40
  }
src/Modules/Blog/Models/BlogPost.php CHANGED
@@ -2,42 +2,41 @@
2
 
3
  namespace CreativeMail\Modules\Blog\Models;
4
 
5
- class BlogPost
6
- {
7
- public $id;
8
- public $author;
9
- public $date;
10
- public $content;
11
 
12
- public $title;
13
- public $excerpt;
14
- public $status;
15
- public $name;
16
 
17
- public $modified;
18
- public $parent_id;
19
- public $menu_order;
20
- public $comment_count;
21
 
22
- public $url;
23
- public $thumbnail;
 
 
24
 
25
- function __construct($wp_post)
26
- {
27
- $this->id = $wp_post->ID;
28
- $this->author = $wp_post->post_author;
29
- $this->date = $wp_post->post_date;
30
- $this->modified = $wp_post->post_modified;
31
- $this->content = apply_filters("the_content", $wp_post->post_content);
32
- $this->title = $wp_post->post_title;
33
- $this->excerpt = $wp_post->post_excerpt;
34
- $this->status = $wp_post->post_status;
35
- $this->parent_id = $wp_post->post_parent;
36
- $this->menu_order = $wp_post->menu_order;
37
- $this->comment_count = $wp_post->comment_count;
38
- $this->url = get_permalink($wp_post->ID);
39
- if (has_post_thumbnail($wp_post->ID)) {
40
- $this->thumbnail = get_the_post_thumbnail_url($wp_post->ID);
41
- }
42
- }
 
 
43
  }
2
 
3
  namespace CreativeMail\Modules\Blog\Models;
4
 
5
+ class BlogPost {
 
 
 
 
 
6
 
7
+ public $id;
8
+ public $author;
9
+ public $date;
10
+ public $content;
11
 
12
+ public $title;
13
+ public $excerpt;
14
+ public $status;
15
+ public $name;
16
 
17
+ public $modified;
18
+ public $parent_id;
19
+ public $menu_order;
20
+ public $comment_count;
21
 
22
+ public $url;
23
+ public $thumbnail;
24
+
25
+ public function __construct( $wp_post ) {
26
+ $this->id = $wp_post->ID;
27
+ $this->author = $wp_post->post_author;
28
+ $this->date = $wp_post->post_date;
29
+ $this->modified = $wp_post->post_modified;
30
+ $this->content = apply_filters('the_content', $wp_post->post_content);
31
+ $this->title = $wp_post->post_title;
32
+ $this->excerpt = $wp_post->post_excerpt;
33
+ $this->status = $wp_post->post_status;
34
+ $this->parent_id = $wp_post->post_parent;
35
+ $this->menu_order = $wp_post->menu_order;
36
+ $this->comment_count = $wp_post->comment_count;
37
+ $this->url = get_permalink($wp_post->ID);
38
+ if ( has_post_thumbnail($wp_post->ID) ) {
39
+ $this->thumbnail = get_the_post_thumbnail_url($wp_post->ID);
40
+ }
41
+ }
42
  }
src/Modules/Contacts/Exceptions/InvalidContactSyncBackgroundRequestException.php CHANGED
@@ -4,10 +4,9 @@ namespace CreativeMail\Modules\Contacts\Exceptions;
4
 
5
  use Exception;
6
 
7
- class InvalidContactSyncBackgroundRequestException extends Exception
8
- {
9
- public function __construct ($message)
10
- {
11
- parent::__construct('[CreativeMail - Contact sync] ' . $message);
12
- }
13
  }
4
 
5
  use Exception;
6
 
7
+ class InvalidContactSyncBackgroundRequestException extends Exception {
8
+
9
+ public function __construct( $message ) {
10
+ parent::__construct('[CreativeMail - Contact sync] ' . $message);
11
+ }
 
12
  }
src/Modules/Contacts/Exceptions/InvalidHandlerContactSyncRequestException.php CHANGED
@@ -4,10 +4,9 @@ namespace CreativeMail\Modules\Contacts\Exceptions;
4
 
5
  use Exception;
6
 
7
- class InvalidHandlerContactSyncRequestException extends Exception
8
- {
9
- public function __construct($message)
10
- {
11
- parent::__construct('[CreativeMail - Contact sync request] ' . $message);
12
- }
13
  }
4
 
5
  use Exception;
6
 
7
+ class InvalidHandlerContactSyncRequestException extends Exception {
8
+
9
+ public function __construct( $message ) {
10
+ parent::__construct('[CreativeMail - Contact sync request] ' . $message);
11
+ }
 
12
  }
src/Modules/Contacts/Handlers/BaseContactFormPluginHandler.php CHANGED
@@ -5,64 +5,58 @@ namespace CreativeMail\Modules\Contacts\Handlers;
5
  use CreativeMail\Modules\Contacts\Services\ContactsSyncService;
6
  use Exception;
7
 
8
- abstract class BaseContactFormPluginHandler
9
- {
10
- private $contactSyncService;
11
-
12
- public abstract function convertToContactModel($contactForm);
13
- public abstract function registerHooks();
14
- public abstract function unregisterHooks();
15
- public abstract function get_contacts($limit = null);
16
-
17
- protected $birthdayFields = array('birthday', 'date-of-birth', 'date_of_birth', 'birth_date', 'birth-date', 'birth date', 'birth day', 'date of birth');
18
- protected $phoneFields = array('phone', 'phone_number', 'telephone', 'tel', 'tel-number', 'tel_number', 'mobile_number', 'mobile number', 'phone number');
19
- protected $emailFields = array('your-email', 'email', 'e-mail', 'emailaddress', 'email_address', 'email address', 'email-address', 'e-mail address', 'UserEmailAddress');
20
- protected $firstnameFields = array('firstname', 'first_name', 'name', 'your-name', 'first name', 'first-name', 'first', 'UserFirstName');
21
- protected $lastnameFields = array('lastname', 'last_name', 'last name', 'last-name', 'last', 'UserLastName');
22
- protected $consentFields = array('accept-this', 'acceptance', 'consent');
23
- protected $cityFields = array('your-city', 'city', 'UserCity');
24
- protected $stateFields = array('your-state', 'state', 'StateDropDown');
25
- protected $countryFields = array('your-country','country', 'CountryDropDown');
26
- protected $zipFields = array('your-zip','zip', 'zipcode', 'UserZip');
27
-
28
- public function upsertContact($model)
29
- {
30
- if (!isset($model)) {
31
- throw new Exception('No model provided');
32
- }
33
-
34
- $contactModel = null;
35
- if (!is_a($model, 'CreativeMail\Modules\Contacts\Models\ContactModel')) {
36
- $contactModel = $this->convertToContactModel($model);
37
- }
38
- else {
39
- $contactModel = $model;
40
- }
41
- $this->contactSyncService->upsertContact($contactModel);
42
- }
43
-
44
- public function batchUpsertContacts($models)
45
- {
46
- if (!isset($models)) {
47
- throw new Exception('No models provided');
48
- }
49
-
50
- $this->contactSyncService->upsertContacts($models);
51
- }
52
-
53
- protected function isNullOrEmpty($value)
54
- {
55
- return !isset($value) && empty($value);
56
- }
57
-
58
- function __construct()
59
- {
60
- $this->contactSyncService = new ContactsSyncService();
61
- $this->registerHooks();
62
- }
63
-
64
- function __destruct()
65
- {
66
- $this->unregisterHooks();
67
- }
68
  }
5
  use CreativeMail\Modules\Contacts\Services\ContactsSyncService;
6
  use Exception;
7
 
8
+ abstract class BaseContactFormPluginHandler {
9
+
10
+ private $contactSyncService;
11
+
12
+ abstract public function convertToContactModel( $contactForm);
13
+ abstract public function registerHooks();
14
+ abstract public function unregisterHooks();
15
+ abstract public function get_contacts( $limit = null);
16
+
17
+ protected $birthdayFields = array( 'birthday', 'date-of-birth', 'date_of_birth', 'birth_date', 'birth-date', 'birth date', 'birth day', 'date of birth' );
18
+ protected $phoneFields = array( 'phone', 'phone_number', 'telephone', 'tel', 'tel-number', 'tel_number', 'mobile_number', 'mobile number', 'phone number' );
19
+ protected $emailFields = array( 'your-email', 'email', 'e-mail', 'emailaddress', 'email_address', 'email address', 'email-address', 'e-mail address', 'UserEmailAddress' );
20
+ protected $firstnameFields = array( 'firstname', 'first_name', 'name', 'your-name', 'first name', 'first-name', 'first', 'UserFirstName' );
21
+ protected $lastnameFields = array( 'lastname', 'last_name', 'last name', 'last-name', 'last', 'UserLastName' );
22
+ protected $consentFields = array( 'accept-this', 'acceptance', 'consent' );
23
+ protected $cityFields = array( 'your-city', 'city', 'UserCity' );
24
+ protected $stateFields = array( 'your-state', 'state', 'StateDropDown' );
25
+ protected $countryFields = array( 'your-country', 'country', 'CountryDropDown' );
26
+ protected $zipFields = array( 'your-zip', 'zip', 'zipcode', 'UserZip' );
27
+
28
+ public function upsertContact( $model ) {
29
+ if ( ! isset($model) ) {
30
+ throw new Exception('No model provided');
31
+ }
32
+
33
+ $contactModel = null;
34
+ if ( ! is_a($model, 'CreativeMail\Modules\Contacts\Models\ContactModel') ) {
35
+ $contactModel = $this->convertToContactModel($model);
36
+ } else {
37
+ $contactModel = $model;
38
+ }
39
+ $this->contactSyncService->upsertContact($contactModel);
40
+ }
41
+
42
+ public function batchUpsertContacts( $models ) {
43
+ if ( ! isset($models) ) {
44
+ throw new Exception('No models provided');
45
+ }
46
+
47
+ $this->contactSyncService->upsertContacts($models);
48
+ }
49
+
50
+ protected function isNullOrEmpty( $value ) {
51
+ return ! isset($value) && empty($value);
52
+ }
53
+
54
+ public function __construct() {
55
+ $this->contactSyncService = new ContactsSyncService();
56
+ $this->registerHooks();
57
+ }
58
+
59
+ public function __destruct() {
60
+ $this->unregisterHooks();
61
+ }
 
 
 
 
 
 
62
  }
src/Modules/Contacts/Handlers/BlueHostBuilderPluginHandler.php CHANGED
@@ -9,110 +9,104 @@ use CreativeMail\Modules\Contacts\Models\ContactModel;
9
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
10
  use Exception;
11
 
12
- class BlueHostBuilderPluginHandler extends BaseContactFormPluginHandler
13
- {
14
- public function convertToContactModel($contact)
15
- {
16
- $contactModel = new ContactModel();
17
-
18
- $email = $contact->email_address;
19
- if ($this->isNullOrEmpty($email)) {
20
- return null;
21
- }
22
- $contactModel->setEmail($email);
23
- $contactModel->setEventType(CE4WP_WB4WP_EVENTTYPE);
24
- // @phpstan-ignore-next-line
25
- if (!empty($contact->opt_in) && (!$contact->opt_out || $contact->opt_out < $contact->opt_in)) {
26
- $contactModel->setOptIn(true);
27
- $contactModel->setOptActionBy(OptActionBy::Owner);
28
- }
29
- // @phpstan-ignore-next-line
30
- if (!empty($contact->opt_out) && (!$contact->opt_in || $contact->opt_out > $contact->opt_in)) {
31
- $contactModel->setOptOut($contact->opt_out);
32
- $contactModel->setOptActionBy(OptActionBy::Visitor);
33
- }
34
-
35
- if (!empty($contact->first_name)) {
36
- $contactModel->setFirstName($contact->first_name);
37
- }
38
- if (!empty($contact->last_name)) {
39
- $contactModel->setLastName($contact->last_name);
40
- }
41
- if (!empty($contact->phone)) {
42
- $contactModel->setPhone($contact->phone);
43
- }
44
- if (!empty($contact->birthday)) {
45
- $contactModel->setBirthday($contact->birthday);
46
- }
47
-
48
- return $contactModel;
49
- }
50
-
51
- public function ceHandleBHWBFormSubmission($contact_id)
52
- {
53
- try {
54
- global $wpdb;
55
- $table = $wpdb->prefix . 'wb4wp_contacts';
56
- $contact = $wpdb->get_row("SELECT * FROM $table WHERE contact_id = $contact_id");
57
- if (empty($contact->email_address)) {
58
- return;
59
- }
60
- $this->upsertContact($this->convertToContactModel($contact));
61
- } catch (Exception $exception) {
62
- RaygunManager::get_instance()->exception_handler($exception);
63
- }
64
- }
65
-
66
- public function registerHooks()
67
- {
68
- add_action('wb4wp_contacts_updated', array($this, 'ceHandleBHWBFormSubmission'), 10, 1);
69
- }
70
-
71
- public function unregisterHooks()
72
- {
73
- remove_action('wb4wp_contacts_updated', array($this, 'ceHandleBHWBFormSubmission'));
74
- }
75
-
76
- public function get_contacts($limit = null)
77
- {
78
- if (!is_int($limit) || $limit <= 0) {
79
- $limit = null;
80
- }
81
-
82
- if (in_array('wb4wp-plugin.php', array_map('basename', apply_filters('active_plugins', get_option('active_plugins'))))) {
83
- global $wpdb;
84
-
85
- $contactsArray = array();
86
- $table = $wpdb->prefix . 'wb4wp_contacts';
87
- $contacts = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table"));
88
-
89
- //loop through the entries and extract necessary data
90
- foreach ($contacts as $contact) {
91
- //Convert to contactModel
92
- $contactModel = null;
93
- try {
94
- $contactModel = $this->convertToContactModel($contact);
95
- } catch (Exception $exception) {
96
- RaygunManager::get_instance()->exception_handler($exception);
97
- continue;
98
- }
99
- if (!empty($contactModel)) {
100
- array_push($contactsArray, $contactModel);
101
- }
102
- if (isset($limit) && count($contactsArray) >= $limit) {
103
- break;
104
- }
105
- }
106
-
107
- if (!empty($contactsArray)) {
108
- return $contactsArray;
109
- }
110
- }
111
- return null;
112
- }
113
-
114
- function __construct()
115
- {
116
- parent::__construct();
117
- }
118
  }
9
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
10
  use Exception;
11
 
12
+ class BlueHostBuilderPluginHandler extends BaseContactFormPluginHandler {
13
+
14
+ public function convertToContactModel( $contact ) {
15
+ $contactModel = new ContactModel();
16
+
17
+ $email = $contact->email_address;
18
+ if ( $this->isNullOrEmpty($email) ) {
19
+ return null;
20
+ }
21
+ $contactModel->setEmail($email);
22
+ $contactModel->setEventType(CE4WP_WB4WP_EVENTTYPE);
23
+ // @phpstan-ignore-next-line
24
+ if ( ! empty($contact->opt_in) && ( ! $contact->opt_out || $contact->opt_out < $contact->opt_in ) ) {
25
+ $contactModel->setOptIn(true);
26
+ $contactModel->setOptActionBy(OptActionBy::OWNER);
27
+ }
28
+ // @phpstan-ignore-next-line
29
+ if ( ! empty($contact->opt_out) && ( ! $contact->opt_in || $contact->opt_out > $contact->opt_in ) ) {
30
+ $contactModel->setOptOut($contact->opt_out);
31
+ $contactModel->setOptActionBy(OptActionBy::VISITOR);
32
+ }
33
+
34
+ if ( ! empty($contact->first_name) ) {
35
+ $contactModel->setFirstName($contact->first_name);
36
+ }
37
+ if ( ! empty($contact->last_name) ) {
38
+ $contactModel->setLastName($contact->last_name);
39
+ }
40
+ if ( ! empty($contact->phone) ) {
41
+ $contactModel->setPhone($contact->phone);
42
+ }
43
+ if ( ! empty($contact->birthday) ) {
44
+ $contactModel->setBirthday($contact->birthday);
45
+ }
46
+
47
+ return $contactModel;
48
+ }
49
+
50
+ public function ceHandleBHWBFormSubmission( $contact_id ) {
51
+ try {
52
+ global $wpdb;
53
+ $table = $wpdb->prefix . 'wb4wp_contacts';
54
+ $contact = $wpdb->get_row( $wpdb->prepare ( 'SELECT * FROM %s WHERE contact_id = %s', $table, $contact_id ) );
55
+ if ( empty($contact->email_address) ) {
56
+ return;
57
+ }
58
+ $this->upsertContact($this->convertToContactModel($contact));
59
+ } catch ( Exception $exception ) {
60
+ RaygunManager::get_instance()->exception_handler($exception);
61
+ }
62
+ }
63
+
64
+ public function registerHooks() {
65
+ add_action('wb4wp_contacts_updated', array( $this, 'ceHandleBHWBFormSubmission' ), 10, 1);
66
+ }
67
+
68
+ public function unregisterHooks() {
69
+ remove_action('wb4wp_contacts_updated', array( $this, 'ceHandleBHWBFormSubmission' ));
70
+ }
71
+
72
+ public function get_contacts( $limit = null ) {
73
+ if ( ! is_int($limit) || $limit <= 0 ) {
74
+ $limit = null;
75
+ }
76
+
77
+ if ( in_array('wb4wp-plugin.php', array_map('basename', apply_filters('active_plugins', get_option('active_plugins')))) ) {
78
+ global $wpdb;
79
+
80
+ $contactsArray = array();
81
+ $table = $wpdb->prefix . 'wb4wp_contacts';
82
+ $contacts = $wpdb->get_results($wpdb->prepare('SELECT * FROM %s', $table));
83
+
84
+ // Loop through the entries and extract necessary data.
85
+ foreach ( $contacts as $contact ) {
86
+ // Convert to contactModel.
87
+ $contactModel = null;
88
+ try {
89
+ $contactModel = $this->convertToContactModel($contact);
90
+ } catch ( Exception $exception ) {
91
+ RaygunManager::get_instance()->exception_handler($exception);
92
+ continue;
93
+ }
94
+ if ( ! empty($contactModel) ) {
95
+ array_push($contactsArray, $contactModel);
96
+ }
97
+ if ( isset($limit) && count($contactsArray) >= $limit ) {
98
+ break;
99
+ }
100
+ }
101
+
102
+ if ( ! empty($contactsArray) ) {
103
+ return $contactsArray;
104
+ }
105
+ }
106
+ return null;
107
+ }
108
+
109
+ public function __construct() {
110
+ parent::__construct();
111
+ }
 
 
 
 
 
 
112
  }
src/Modules/Contacts/Handlers/CalderaPluginHandler.php CHANGED
@@ -7,184 +7,178 @@ define('CE4WP_CAL_EVENTTYPE', 'WordPress - Caldera Forms');
7
  use CreativeMail\Managers\RaygunManager;
8
  use CreativeMail\Modules\Contacts\Models\ContactModel;
9
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
10
-
11
- class CalderaPluginHandler extends BaseContactFormPluginHandler
12
- {
13
- private function GetCalderaPhoneFields()
14
- {
15
- return array_merge($this->phoneFields, ['phone_better']);
16
- }
17
-
18
- private function GetNameFromForm($entry)
19
- {
20
- if ($this->isNullOrEmpty($entry)) {
21
- return null;
22
- }
23
-
24
- $name = null;
25
- foreach ($entry as $field) {
26
- if ($field->slug === "first_name") {
27
- $name["firstname"] = $field->value;
28
- continue;
29
- }
30
- if ($field->slug === "last_name") {
31
- $name["lastname"] = $field->value;
32
- return $name;
33
- }
34
- }
35
- return $name;
36
- }
37
-
38
- private function FindFormValues($entry, $calderaContact)
39
- {
40
- if ($this->isNullOrEmpty($entry)) {
41
- return null;
42
- }
43
- $calderaPhoneFields = $this->GetCalderaPhoneFields();
44
- foreach ($entry as $field) {
45
- $slug = strtolower($field->slug);
46
- if (in_array($slug, $calderaPhoneFields)) {
47
- $calderaContact->phone = $field->value;
48
- } elseif (in_array($slug, $this->birthdayFields)) {
49
- $calderaContact->birthday = $field->value;
50
- } elseif ($slug == "email_address") {
51
- $calderaContact->email = $field->value;
52
- } elseif ($slug == "consent") {
53
- $calderaContact->consent = $field->value;
54
- }
55
- }
56
- }
57
-
58
- public function convertToContactModel($contact)
59
- {
60
- $email = $contact->email;
61
- if ($this->isNullOrEmpty($email)) {
62
- return null;
63
- }
64
-
65
- $contactModel = new ContactModel();
66
-
67
- $contactModel->setEventType(CE4WP_CAL_EVENTTYPE);
68
- $contactModel->setOptOut(false);
69
-
70
- //if its a form submission we take the opt_in value and set action to visitor
71
- if ($contact->isFormSubmission) {
72
- $contactModel->setOptIn(boolval($contact->consent));
73
- $contactModel->setOptActionBy(OptActionBy::Visitor);
74
- } else {
75
- $contactModel->setOptIn(true);
76
- $contactModel->setOptActionBy(OptActionBy::Owner);
77
- }
78
-
79
- $contactModel->setEmail($email);
80
-
81
- if (!empty($contact->firstname)) {
82
- $contactModel->setFirstName($contact->firstname);
83
- }
84
- if (!empty($contact->lastname)) {
85
- $contactModel->setLastName($contact->lastname);
86
- }
87
- if (!empty($contact->phone)) {
88
- $contactModel->setPhone($contact->phone);
89
- }
90
- if (!empty($contact->birthday)) {
91
- $contactModel->setBirthday($contact->birthday);
92
- }
93
-
94
- return $contactModel;
95
- }
96
-
97
- public function ceHandleCalderaFormSubmission($form, $referrer, $process_id, $entryid)
98
- {
99
- try {
100
- global $wpdb;
101
- $calderaContact = new \stdClass();
102
- $calderaContact->isFormSubmission = true;
103
-
104
- $entryData = $wpdb->get_results($wpdb->prepare("SELECT slug, `value` FROM wp_cf_form_entry_values WHERE entry_id = {$entryid}"));
105
- $nameValues = $this->GetNameFromForm($entryData);
106
- $calderaContact->firstname = array_key_exists("firstname", $nameValues) ? $nameValues["firstname"] : null;
107
- $calderaContact->lastname = array_key_exists("lastname", $nameValues) ? $nameValues["lastname"] : null;
108
-
109
- //get additional form values and add to the contact
110
- $this->FindFormValues($entryData, $calderaContact);
111
-
112
- if (empty($calderaContact->email)) {
113
- return;
114
- }
115
- $this->upsertContact($this->convertToContactModel($calderaContact));
116
- } catch (\Exception $exception) {
117
- RaygunManager::get_instance()->exception_handler($exception);
118
- }
119
- }
120
-
121
- public function registerHooks()
122
- {
123
- add_action('caldera_forms_submit_complete', array($this, 'ceHandleCalderaFormSubmission'), 60, 4); //make sure the prio is set as to run after caldera itself otherwise data is not present in db
124
- }
125
-
126
- public function unregisterHooks()
127
- {
128
- remove_action('caldera_forms_submit_complete', array($this, 'ceHandleCalderaFormSubmission'));
129
- }
130
-
131
- public function get_contacts($limit = null)
132
- {
133
- if (!is_int($limit) || $limit <= 0) {
134
- $limit = null;
135
- }
136
-
137
- // Relies on plugin => GravityForms
138
- if (in_array('caldera-forms/caldera-core.php', apply_filters('active_plugins', get_option('active_plugins'))) && defined('CFCORE_VER')) {
139
- global $wpdb;
140
-
141
- $contactsArray = array();
142
- $entryIds = $wpdb->get_results($wpdb->prepare("SELECT id FROM wp_cf_form_entries WHERE status = 'active'"));
143
-
144
- //loop through the entries and extract necessary data
145
- foreach ($entryIds as $entry) {
146
- $contact = new \stdClass();
147
- $contact->isFormSubmission = false;
148
- $entryData = $wpdb->get_results($wpdb->prepare("SELECT slug, `value` FROM wp_cf_form_entry_values WHERE entry_id = {$entry->id}"));
149
-
150
- //get form values
151
- $this->FindFormValues($entryData, $contact);
152
-
153
- if (empty($contact->email)) {
154
- continue;
155
- }
156
-
157
- $nameValues = $this->GetNameFromForm($entryData);
158
- $contact->firstname = array_key_exists("firstname", $nameValues) ? $nameValues["firstname"] : null;
159
- $contact->lastname = array_key_exists("lastname", $nameValues) ? $nameValues["lastname"] : null;
160
-
161
- //contact opt in is true on sync
162
- $contact->consent = true;
163
-
164
- //Convert to contactModel
165
- $contactModel = null;
166
- try {
167
- $contactModel = $this->convertToContactModel($contact);
168
- } catch (\Exception $exception) {
169
- RaygunManager::get_instance()->exception_handler($exception);
170
- continue;
171
- }
172
-
173
- if (!empty($contactModel)) {
174
- array_push($contactsArray, $contactModel);
175
- }
176
-
177
- if (isset($limit) && count($contactsArray) >= $limit) {
178
- break;
179
- }
180
- }
181
-
182
- if (!empty($contactsArray)) {
183
- return $contactsArray;
184
- }
185
-
186
- }
187
-
188
- return null;
189
- }
190
  }
7
  use CreativeMail\Managers\RaygunManager;
8
  use CreativeMail\Modules\Contacts\Models\ContactModel;
9
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
10
+ use Exception;
11
+ use stdClass;
12
+
13
+ class CalderaPluginHandler extends BaseContactFormPluginHandler {
14
+
15
+ private function GetCalderaPhoneFields() {
16
+ return array_merge($this->phoneFields, array( 'phone_better' ));
17
+ }
18
+
19
+ private function GetNameFromForm( $entry ) {
20
+ if ( $this->isNullOrEmpty($entry) ) {
21
+ return null;
22
+ }
23
+
24
+ $name = null;
25
+ foreach ( $entry as $field ) {
26
+ if ( 'first_name' === $field->slug ) {
27
+ $name['firstname'] = $field->value;
28
+ continue;
29
+ }
30
+ if ( 'last_name' === $field->slug ) {
31
+ $name['lastname'] = $field->value;
32
+ return $name;
33
+ }
34
+ }
35
+ return $name;
36
+ }
37
+
38
+ private function FindFormValues( $entry, $calderaContact ) {
39
+ if ( $this->isNullOrEmpty($entry) ) {
40
+ return null;
41
+ }
42
+ $calderaPhoneFields = $this->GetCalderaPhoneFields();
43
+ foreach ( $entry as $field ) {
44
+ $slug = strtolower($field->slug);
45
+ if ( in_array($slug, $calderaPhoneFields, true) ) {
46
+ $calderaContact->phone = $field->value;
47
+ } elseif ( in_array($slug, $this->birthdayFields, true) ) {
48
+ $calderaContact->birthday = $field->value;
49
+ } elseif ( 'email_address' == $slug ) {
50
+ $calderaContact->email = $field->value;
51
+ } elseif ( 'consent' == $slug ) {
52
+ $calderaContact->consent = $field->value;
53
+ }
54
+ }
55
+ }
56
+
57
+ public function convertToContactModel( $contact ) {
58
+ $email = $contact->email;
59
+ if ( $this->isNullOrEmpty($email) ) {
60
+ return null;
61
+ }
62
+
63
+ $contactModel = new ContactModel();
64
+
65
+ $contactModel->setEventType(CE4WP_CAL_EVENTTYPE);
66
+ $contactModel->setOptOut(false);
67
+
68
+ // If it's a form submission we take the opt_in value and set action to visitor.
69
+ if ( $contact->isFormSubmission ) {
70
+ $contactModel->setOptIn(boolval($contact->consent));
71
+ $contactModel->setOptActionBy(OptActionBy::VISITOR);
72
+ } else {
73
+ $contactModel->setOptIn(true);
74
+ $contactModel->setOptActionBy(OptActionBy::OWNER);
75
+ }
76
+
77
+ $contactModel->setEmail($email);
78
+
79
+ if ( ! empty($contact->firstname) ) {
80
+ $contactModel->setFirstName($contact->firstname);
81
+ }
82
+ if ( ! empty($contact->lastname) ) {
83
+ $contactModel->setLastName($contact->lastname);
84
+ }
85
+ if ( ! empty($contact->phone) ) {
86
+ $contactModel->setPhone($contact->phone);
87
+ }
88
+ if ( ! empty($contact->birthday) ) {
89
+ $contactModel->setBirthday($contact->birthday);
90
+ }
91
+
92
+ return $contactModel;
93
+ }
94
+
95
+ public function ceHandleCalderaFormSubmission( $form, $referrer, $process_id, $entryid ) {
96
+ try {
97
+ global $wpdb;
98
+ $calderaContact = new stdClass();
99
+ $calderaContact->isFormSubmission = true;
100
+
101
+ $entryData = $wpdb->get_results($wpdb->prepare('SELECT slug, `value` FROM wp_cf_form_entry_values WHERE entry_id = %s', $entryid));
102
+ $nameValues = $this->GetNameFromForm($entryData);
103
+ $calderaContact->firstname = array_key_exists('firstname', $nameValues) ? $nameValues['firstname'] : null;
104
+ $calderaContact->lastname = array_key_exists('lastname', $nameValues) ? $nameValues['lastname'] : null;
105
+
106
+ // Get additional form values and add to the contact.
107
+ $this->FindFormValues($entryData, $calderaContact);
108
+
109
+ if ( empty($calderaContact->email) ) {
110
+ return;
111
+ }
112
+ $this->upsertContact($this->convertToContactModel($calderaContact));
113
+ } catch ( Exception $exception ) {
114
+ RaygunManager::get_instance()->exception_handler($exception);
115
+ }
116
+ }
117
+
118
+ public function registerHooks() {
119
+ // Make sure the prior is set as to run after caldera itself otherwise data is not present in db.
120
+ add_action('caldera_forms_submit_complete', array( $this, 'ceHandleCalderaFormSubmission' ), 60, 4);
121
+ }
122
+
123
+ public function unregisterHooks() {
124
+ remove_action('caldera_forms_submit_complete', array( $this, 'ceHandleCalderaFormSubmission' ));
125
+ }
126
+
127
+ public function get_contacts( $limit = null ) {
128
+ if ( ! is_int($limit) || $limit <= 0 ) {
129
+ $limit = null;
130
+ }
131
+
132
+ // Relies on plugin => GravityForms.
133
+ if ( in_array('caldera-forms/caldera-core.php', apply_filters('active_plugins', get_option('active_plugins')), true) && defined('CFCORE_VER') ) {
134
+ global $wpdb;
135
+
136
+ $contactsArray = array();
137
+ $entryIds = $wpdb->get_results($wpdb->prepare("SELECT id FROM wp_cf_form_entries WHERE status = 'active'"));
138
+
139
+ // Loop through the entries and extract necessary data.
140
+ foreach ( $entryIds as $entry ) {
141
+ $contact = new stdClass();
142
+ $contact->isFormSubmission = false;
143
+ $entryData = $wpdb->get_results($wpdb->prepare('SELECT slug, `value` FROM wp_cf_form_entry_values WHERE entry_id = %s', $entry->id));
144
+
145
+ // Get form values.
146
+ $this->FindFormValues($entryData, $contact);
147
+
148
+ if ( empty($contact->email) ) {
149
+ continue;
150
+ }
151
+
152
+ $nameValues = $this->GetNameFromForm($entryData);
153
+ $contact->firstname = array_key_exists('firstname', $nameValues) ? $nameValues['firstname'] : null;
154
+ $contact->lastname = array_key_exists('lastname', $nameValues) ? $nameValues['lastname'] : null;
155
+
156
+ // Contact opt in is true on sync.
157
+ $contact->consent = true;
158
+
159
+ // Convert to contactModel.
160
+ $contactModel = null;
161
+ try {
162
+ $contactModel = $this->convertToContactModel($contact);
163
+ } catch ( Exception $exception ) {
164
+ RaygunManager::get_instance()->exception_handler($exception);
165
+ continue;
166
+ }
167
+
168
+ if ( ! empty($contactModel) ) {
169
+ array_push($contactsArray, $contactModel);
170
+ }
171
+
172
+ if ( isset($limit) && count($contactsArray) >= $limit ) {
173
+ break;
174
+ }
175
+ }
176
+
177
+ if ( ! empty($contactsArray) ) {
178
+ return $contactsArray;
179
+ }
180
+ }
181
+
182
+ return null;
183
+ }
 
 
 
 
 
 
184
  }
src/Modules/Contacts/Handlers/ContactFormSevenPluginHandler.php CHANGED
@@ -9,220 +9,213 @@ use CreativeMail\Modules\Contacts\Models\ContactFormSevenSubmission;
9
  use CreativeMail\Modules\Contacts\Models\ContactModel;
10
  use CreativeMail\Modules\Contacts\Models\ContactAddressModel;
11
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
12
-
13
- class ContactFormSevenPluginHandler extends BaseContactFormPluginHandler
14
- {
15
- private function findValue($data, $fieldOptions)
16
- {
17
- foreach ($fieldOptions as $fieldOption) {
18
- $value = $data->get_posted_data($fieldOption);
19
- if (isset($value) && !empty($value)) {
20
- return $value;
21
- }
22
- }
23
-
24
- return null;
25
- }
26
-
27
- private function findValueFromDb($formData, $fieldOptions)
28
- {
29
- foreach ($fieldOptions as $fieldOption) {
30
- if (array_key_exists($fieldOption, $formData)) {
31
- $value = $formData[$fieldOption];
32
- if (!empty($value)) {
33
- return $value;
34
- }
35
- }
36
- }
37
- return null;
38
- }
39
-
40
- public function convertToContactModel($contactForm)
41
- {
42
- $contactForm = ContactFormSevenSubmission::get_instance(null, array('skip_mail' => true));
43
-
44
- // convert
45
- $contactModel = new ContactModel();
46
- $email = $this->findValue($contactForm, $this->emailFields);
47
- if (!empty($email)) {
48
- $contactModel->setEmail($email);
49
- }
50
-
51
- $firstName = $this->findValue($contactForm, $this->firstnameFields);
52
- if (!empty($firstName)) {
53
- $contactModel->setFirstName($firstName);
54
- }
55
-
56
- $lastName = $this->findValue($contactForm, $this->lastnameFields);
57
- if (!empty($lastName)) {
58
- $contactModel->setLastName($lastName);
59
- }
60
-
61
- $phone = $this->findValue($contactForm, $this->phoneFields);
62
- if (empty($phone)) {
63
- $phone = $this->GetValueBySubstring($contactForm->get_posted_data(), $this->phoneFields);
64
- }
65
- if (!empty($phone)) {
66
- $contactModel->setPhone($phone);
67
- }
68
-
69
- $birthday = $this->findValue($contactForm, $this->birthdayFields);
70
- if (!empty($birthday)) {
71
- $contactModel->setBirthday($birthday);
72
- }
73
-
74
- $consent = $this->GetValueBySubstring($contactForm->get_posted_data(), $this->consentFields);
75
- if ($consent === "1") {
76
- $contactModel->setOptIn(true);
77
- $contactModel->setOptOut(false);
78
- $contactModel->setOptActionBy(OptActionBy::Visitor);
79
- }
80
-
81
- $contactAddress = $this->getContactAddressFromForm($contactForm);
82
-
83
- if (!empty($contactAddress)) {
84
- $contactModel->setContactAddress($contactAddress);
85
- }
86
-
87
- $contactModel->setEventType(CE4WP_CF7_EVENTTYPE);
88
-
89
- return $contactModel;
90
- }
91
-
92
- function getContactAddressFromForm($contactForm)
93
- {
94
- $contactAddress = new ContactAddressModel();
95
-
96
- if (isset($contactForm)) {
97
- $city = $this->findValue($contactForm, $this->cityFields);
98
- if (!empty($city)) {
99
- $contactAddress->setCity($city);
100
- }
101
-
102
- $zip = $this->findValue($contactForm, $this->zipFields);
103
- if (!empty($zip)) {
104
- $contactAddress->setPostalCode($zip);
105
- }
106
-
107
- $state = $this->findValue($contactForm, $this->stateFields);
108
- if (!empty($state) AND !empty($state[0])) {
109
- $contactAddress->setStateCode($state[0]);
110
- }
111
-
112
- $country = $this->findValue($contactForm, $this->countryFields);
113
- if (!empty($country) AND !empty($country[0])) {
114
- $contactAddress->setCountryCode($country[0]);
115
- }
116
- }
117
- return $contactAddress;
118
- }
119
-
120
- public function registerHooks()
121
- {
122
- add_action('wpcf7_mail_sent', array($this, 'ceHandleContactFormSevenSubmit'));
123
- }
124
-
125
- public function unregisterHooks()
126
- {
127
- remove_action('wpcf7_mail_sent', array($this, 'ceHandleContactFormSevenSubmit'));
128
- }
129
-
130
- public function get_contacts($limit = null)
131
- {
132
- if (!is_int($limit) || $limit <= 0) {
133
- $limit = null;
134
- }
135
-
136
- // Relies on plugin => Contact Form CFDB7
137
- if (in_array('contact-form-cfdb7/contact-form-cfdb-7.php', apply_filters('active_plugins', get_option('active_plugins')))) {
138
- global $wpdb;
139
-
140
- $cfdb = apply_filters('cfdb7_database', $wpdb);
141
- $cfdbtable = $cfdb->prefix . 'db7_forms';
142
- $cfdbQuery = "SELECT form_id, form_post_id, form_value FROM $cfdbtable";
143
-
144
- // Do we need to limit the number of results
145
- if ($limit != null) {
146
- $cfdbQuery .= " LIMIT %d";
147
- $cfdbQuery = $cfdb->prepare($cfdbQuery, $limit);
148
- } else {
149
- $cfdbQuery = $cfdb->prepare($cfdbQuery);
150
- }
151
-
152
- $results = $cfdb->get_results($cfdbQuery, OBJECT);
153
- $contactsArray = array();
154
-
155
- foreach ($results as $formSubmission) {
156
- $form_data = unserialize($formSubmission->form_value);
157
- $contactModel = new ContactModel();
158
- $contactModel->setOptIn(true);
159
- $contactModel->setOptOut(false);
160
- $contactModel->setOptActionBy(OptActionBy::Owner);
161
-
162
- try {
163
- $email = $this->findValueFromDb($form_data, $this->emailFields);
164
- if (!empty($email)) {
165
- $contactModel->setEmail($email);
166
- }
167
- $firstname = $this->findValueFromDb($form_data, $this->firstnameFields);
168
- if (!empty($firstname)) {
169
- $contactModel->setFirstName($firstname);
170
- }
171
- $lastname = $this->findValueFromDb($form_data, $this->lastnameFields);
172
- if (!empty($lastname)) {
173
- $contactModel->setLastName($lastname);
174
- }
175
- $phone = $this->findValueFromDb($form_data, $this->phoneFields);
176
- if (!empty($phone)) {
177
- $contactModel->setPhone($phone);
178
- }
179
- $birthday = $this->findValueFromDb($form_data, $this->birthdayFields);
180
- if (!empty($birthday)) {
181
- $contactModel->setBirthday($birthday);
182
- }
183
- } catch (\Exception $exception) {
184
- RaygunManager::get_instance()->exception_handler($exception);
185
- continue;
186
- }
187
-
188
- if (!empty($contactModel->getEmail())) {
189
- $contactModel->setEventType(CE4WP_CF7_EVENTTYPE);
190
- array_push($contactsArray, $contactModel);
191
- }
192
- }
193
-
194
- if (!empty($contactsArray)) {
195
- return $contactsArray;
196
- }
197
- }
198
-
199
- return null;
200
- }
201
-
202
- function ceHandleContactFormSevenSubmit($contact_form)
203
- {
204
- try {
205
- $this->upsertContact($this->convertToContactModel($contact_form));
206
- } catch (\Exception $exception) {
207
- RaygunManager::get_instance()->exception_handler($exception);
208
- }
209
- }
210
-
211
- function __construct()
212
- {
213
- parent::__construct();
214
- }
215
-
216
- private function GetValueBySubstring($form_values, $possible_values)
217
- {
218
- foreach ($form_values as $form_key => $form_value) {
219
- foreach ($possible_values as $possible_value) {
220
- // If the name of the form_key contains the possible_value then we return its value
221
- if (mb_strpos(strtolower($form_key), $possible_value) !== false)
222
- {
223
- return $form_value;
224
- }
225
- }
226
- }
227
- }
228
  }
9
  use CreativeMail\Modules\Contacts\Models\ContactModel;
10
  use CreativeMail\Modules\Contacts\Models\ContactAddressModel;
11
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
12
+ use Exception;
13
+
14
+ class ContactFormSevenPluginHandler extends BaseContactFormPluginHandler {
15
+
16
+ private function findValue( $data, $fieldOptions ) {
17
+ foreach ( $fieldOptions as $fieldOption ) {
18
+ $value = $data->get_posted_data($fieldOption);
19
+ if ( isset($value) && ! empty($value) ) {
20
+ return $value;
21
+ }
22
+ }
23
+
24
+ return null;
25
+ }
26
+
27
+ private function findValueFromDb( $formData, $fieldOptions ) {
28
+ foreach ( $fieldOptions as $fieldOption ) {
29
+ if ( array_key_exists($fieldOption, $formData) ) {
30
+ $value = $formData[ $fieldOption ];
31
+ if ( ! empty($value) ) {
32
+ return $value;
33
+ }
34
+ }
35
+ }
36
+ return null;
37
+ }
38
+
39
+ public function convertToContactModel( $contactForm ) {
40
+ $contactForm = ContactFormSevenSubmission::get_instance(null, array( 'skip_mail' => true ));
41
+
42
+ // Convert.
43
+ $contactModel = new ContactModel();
44
+ $email = $this->findValue($contactForm, $this->emailFields);
45
+ if ( ! empty($email) ) {
46
+ $contactModel->setEmail($email);
47
+ }
48
+
49
+ $firstName = $this->findValue($contactForm, $this->firstnameFields);
50
+ if ( ! empty($firstName) ) {
51
+ $contactModel->setFirstName($firstName);
52
+ }
53
+
54
+ $lastName = $this->findValue($contactForm, $this->lastnameFields);
55
+ if ( ! empty($lastName) ) {
56
+ $contactModel->setLastName($lastName);
57
+ }
58
+
59
+ $phone = $this->findValue($contactForm, $this->phoneFields);
60
+ if ( empty($phone) ) {
61
+ $phone = $this->GetValueBySubstring($contactForm->get_posted_data(), $this->phoneFields);
62
+ }
63
+ if ( ! empty($phone) ) {
64
+ $contactModel->setPhone($phone);
65
+ }
66
+
67
+ $birthday = $this->findValue($contactForm, $this->birthdayFields);
68
+ if ( ! empty($birthday) ) {
69
+ $contactModel->setBirthday($birthday);
70
+ }
71
+
72
+ $consent = $this->GetValueBySubstring($contactForm->get_posted_data(), $this->consentFields);
73
+ if ( '1' === $consent ) {
74
+ $contactModel->setOptIn(true);
75
+ $contactModel->setOptOut(false);
76
+ $contactModel->setOptActionBy(OptActionBy::VISITOR);
77
+ }
78
+
79
+ $contactAddress = $this->getContactAddressFromForm($contactForm);
80
+
81
+ if ( ! empty($contactAddress) ) {
82
+ $contactModel->setContactAddress($contactAddress);
83
+ }
84
+
85
+ $contactModel->setEventType(CE4WP_CF7_EVENTTYPE);
86
+
87
+ return $contactModel;
88
+ }
89
+
90
+ public function getContactAddressFromForm( $contactForm ) {
91
+ $contactAddress = new ContactAddressModel();
92
+
93
+ if ( isset($contactForm) ) {
94
+ $city = $this->findValue($contactForm, $this->cityFields);
95
+ if ( ! empty($city) ) {
96
+ $contactAddress->setCity($city);
97
+ }
98
+
99
+ $zip = $this->findValue($contactForm, $this->zipFields);
100
+ if ( ! empty($zip) ) {
101
+ $contactAddress->setPostalCode($zip);
102
+ }
103
+
104
+ $state = $this->findValue($contactForm, $this->stateFields);
105
+ if ( ! empty($state) && ! empty($state[0]) ) {
106
+ $contactAddress->setStateCode($state[0]);
107
+ }
108
+
109
+ $country = $this->findValue($contactForm, $this->countryFields);
110
+ if ( ! empty($country) && ! empty($country[0]) ) {
111
+ $contactAddress->setCountryCode($country[0]);
112
+ }
113
+ }
114
+ return $contactAddress;
115
+ }
116
+
117
+ public function registerHooks() {
118
+ add_action('wpcf7_mail_sent', array( $this, 'ceHandleContactFormSevenSubmit' ));
119
+ }
120
+
121
+ public function unregisterHooks() {
122
+ remove_action('wpcf7_mail_sent', array( $this, 'ceHandleContactFormSevenSubmit' ));
123
+ }
124
+
125
+ public function get_contacts( $limit = null ) {
126
+ if ( ! is_int($limit) || $limit <= 0 ) {
127
+ $limit = null;
128
+ }
129
+
130
+ // Relies on plugin => Contact Form CFDB7.
131
+ if ( in_array('contact-form-cfdb7/contact-form-cfdb-7.php',
132
+ apply_filters('active_plugins', get_option('active_plugins')),
133
+ true)
134
+ ) {
135
+ global $wpdb;
136
+
137
+ $cfdb = apply_filters('cfdb7_database', $wpdb);
138
+ $cfdbtable = $cfdb->prefix . 'db7_forms';
139
+ $cfdbQuery = "SELECT form_id, form_post_id, form_value FROM $cfdbtable";
140
+
141
+ // Do we need to limit the number of results?
142
+ if ( null != $limit ) {
143
+ $cfdbQuery .= ' LIMIT %d';
144
+ $cfdbQuery = $cfdb->prepare($cfdbQuery, $limit);
145
+ } else {
146
+ $cfdbQuery = $cfdb->prepare($cfdbQuery);
147
+ }
148
+
149
+ $results = $cfdb->get_results($cfdbQuery, OBJECT);
150
+ $contactsArray = array();
151
+
152
+ foreach ( $results as $formSubmission ) {
153
+ $form_data = unserialize($formSubmission->form_value);
154
+ $contactModel = new ContactModel();
155
+ $contactModel->setOptIn(true);
156
+ $contactModel->setOptOut(false);
157
+ $contactModel->setOptActionBy(OptActionBy::OWNER);
158
+
159
+ try {
160
+ $email = $this->findValueFromDb($form_data, $this->emailFields);
161
+ if ( ! empty($email) ) {
162
+ $contactModel->setEmail($email);
163
+ }
164
+ $firstname = $this->findValueFromDb($form_data, $this->firstnameFields);
165
+ if ( ! empty($firstname) ) {
166
+ $contactModel->setFirstName($firstname);
167
+ }
168
+ $lastname = $this->findValueFromDb($form_data, $this->lastnameFields);
169
+ if ( ! empty($lastname) ) {
170
+ $contactModel->setLastName($lastname);
171
+ }
172
+ $phone = $this->findValueFromDb($form_data, $this->phoneFields);
173
+ if ( ! empty($phone) ) {
174
+ $contactModel->setPhone($phone);
175
+ }
176
+ $birthday = $this->findValueFromDb($form_data, $this->birthdayFields);
177
+ if ( ! empty($birthday) ) {
178
+ $contactModel->setBirthday($birthday);
179
+ }
180
+ } catch ( Exception $exception ) {
181
+ RaygunManager::get_instance()->exception_handler($exception);
182
+ continue;
183
+ }
184
+
185
+ if ( ! empty($contactModel->getEmail()) ) {
186
+ $contactModel->setEventType(CE4WP_CF7_EVENTTYPE);
187
+ array_push($contactsArray, $contactModel);
188
+ }
189
+ }
190
+
191
+ if ( ! empty($contactsArray) ) {
192
+ return $contactsArray;
193
+ }
194
+ }
195
+
196
+ return null;
197
+ }
198
+
199
+ public function ceHandleContactFormSevenSubmit( $contact_form ) {
200
+ try {
201
+ $this->upsertContact($this->convertToContactModel($contact_form));
202
+ } catch ( Exception $exception ) {
203
+ RaygunManager::get_instance()->exception_handler($exception);
204
+ }
205
+ }
206
+
207
+ public function __construct() {
208
+ parent::__construct();
209
+ }
210
+
211
+ private function GetValueBySubstring( $form_values, $possible_values ) {
212
+ foreach ( $form_values as $form_key => $form_value ) {
213
+ foreach ( $possible_values as $possible_value ) {
214
+ // If the name of the form_key contains the possible_value then we return its value.
215
+ if ( mb_strpos(strtolower($form_key), $possible_value) !== false ) {
216
+ return $form_value;
217
+ }
218
+ }
219
+ }
220
+ }
 
 
 
 
 
 
 
221
  }
src/Modules/Contacts/Handlers/CreativeMailPluginHandler.php CHANGED
@@ -9,93 +9,86 @@ use CreativeMail\Modules\Contacts\Models\ContactModel;
9
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
10
  use Exception;
11
 
12
- class CreativeMailPluginHandler extends BaseContactFormPluginHandler
13
- {
14
- public function convertToContactModel($contact)
15
- {
16
- $contactModel = new ContactModel();
17
 
18
- $contactModel->setEventType(CE4WP_CE_EVENTTYPE);
 
19
 
20
- $contactModel->setOptIn(false);
21
- $contactModel->setOptOut(false);
22
- if (!empty($contact['consent'])) {
23
- $consent_bool = $contact['consent'] == 'true';
24
- $contactModel->setOptIn($consent_bool);
25
- }
26
- $contactModel->setOptActionBy(OptActionBy::Visitor);
27
 
28
- if (!empty($contact['email'])) {
29
- $contactModel->setEmail($contact['email']);
30
- }
31
- if (!empty($contact['first_name'])) {
32
- $contactModel->setFirstName($contact['first_name']);
33
- }
34
- if (!empty($contact['last_name'])) {
35
- $contactModel->setLastName($contact['last_name']);
36
- }
37
- if (!empty($contact['telephone'])) {
38
- $contactModel->setPhone($contact['telephone']);
39
- }
40
- if (!empty($contact['list_id'])) {
41
- $contactModel->setListId((int)$contact['list_id']);
42
- }
43
- return $contactModel;
44
- }
45
 
46
- public function ceHandleCreativeEmailSubmission($data)
47
- {
48
- try {
49
- $this->upsertContact($this->convertToContactModel($data));
50
- } catch (Exception $exception) {
51
- RaygunManager::get_instance()->exception_handler($exception);
52
- }
53
- }
 
 
 
 
 
 
 
 
 
54
 
55
- public function registerHooks()
56
- {
57
- add_action('ce4wp_contact_submission', array($this, 'ceHandleCreativeEmailSubmission'), 10, 1);
58
- }
 
 
 
59
 
60
- public function unregisterHooks()
61
- {
62
- remove_action('ce4wp_contact_submission', array($this, 'ceHandleCreativeEmailSubmission'));
63
- }
64
 
65
- public function get_contacts($limit = null)
66
- {
67
- if (!is_int($limit) || $limit <= 0) {
68
- $limit = null;
69
- }
70
- //Get form submissions from the wp_ce4wp_contacts table
71
- global $wpdb;
72
- $contactsArray = array();
73
 
74
- // Get contacts.
75
- $contactsQuery = 'SELECT * FROM wp_ce4wp_contacts';
76
- $contactsResult = $wpdb->get_results($wpdb->prepare($contactsQuery));
 
 
 
 
77
 
78
- foreach ($contactsResult as $contact) {
79
- try {
80
- $contact = $this->convertToContactModel(json_decode(
81
- (string) json_encode($contact),
82
- true)
83
- );
84
- if (!empty($contact->getEmail())) {
85
- array_push($contactsArray, $contact);
86
- }
87
 
88
- } catch (Exception $exception) {
89
- RaygunManager::get_instance()->exception_handler($exception);
90
- continue;
91
- }
92
- if (isset($limit) && count($contactsArray) >= $limit) {
93
- break;
94
- }
95
- }
96
- if (!empty($contactsArray)) {
97
- return $contactsArray;
98
- }
99
- return null;
100
- }
 
 
 
 
 
 
 
 
 
101
  }
9
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
10
  use Exception;
11
 
12
+ class CreativeMailPluginHandler extends BaseContactFormPluginHandler {
 
 
 
 
13
 
14
+ public function convertToContactModel( $contact ) {
15
+ $contactModel = new ContactModel();
16
 
17
+ $contactModel->setEventType(CE4WP_CE_EVENTTYPE);
 
 
 
 
 
 
18
 
19
+ $contactModel->setOptIn(false);
20
+ $contactModel->setOptOut(false);
21
+ if ( ! empty($contact['consent']) ) {
22
+ $consent_bool = 'true' == $contact['consent'];
23
+ $contactModel->setOptIn($consent_bool);
24
+ }
25
+ $contactModel->setOptActionBy(OptActionBy::VISITOR);
 
 
 
 
 
 
 
 
 
 
26
 
27
+ if ( ! empty($contact['email']) ) {
28
+ $contactModel->setEmail($contact['email']);
29
+ }
30
+ if ( ! empty($contact['first_name']) ) {
31
+ $contactModel->setFirstName($contact['first_name']);
32
+ }
33
+ if ( ! empty($contact['last_name']) ) {
34
+ $contactModel->setLastName($contact['last_name']);
35
+ }
36
+ if ( ! empty($contact['telephone']) ) {
37
+ $contactModel->setPhone($contact['telephone']);
38
+ }
39
+ if ( ! empty($contact['list_id']) ) {
40
+ $contactModel->setListId( (int) $contact['list_id']);
41
+ }
42
+ return $contactModel;
43
+ }
44
 
45
+ public function ceHandleCreativeEmailSubmission( $data ) {
46
+ try {
47
+ $this->upsertContact($this->convertToContactModel($data));
48
+ } catch ( Exception $exception ) {
49
+ RaygunManager::get_instance()->exception_handler($exception);
50
+ }
51
+ }
52
 
53
+ public function registerHooks() {
54
+ add_action('ce4wp_contact_submission', array( $this, 'ceHandleCreativeEmailSubmission' ), 10, 1);
55
+ }
 
56
 
57
+ public function unregisterHooks() {
58
+ remove_action('ce4wp_contact_submission', array( $this, 'ceHandleCreativeEmailSubmission' ));
59
+ }
 
 
 
 
 
60
 
61
+ public function get_contacts( $limit = null ) {
62
+ if ( ! is_int($limit) || $limit <= 0 ) {
63
+ $limit = null;
64
+ }
65
+ // Get form submissions from the wp_ce4wp_contacts table.
66
+ global $wpdb;
67
+ $contactsArray = array();
68
 
69
+ // Get contacts.
70
+ $contactsResult = $wpdb->get_results( 'SELECT * FROM wp_ce4wp_contacts' );
 
 
 
 
 
 
 
71
 
72
+ foreach ( $contactsResult as $contact ) {
73
+ try {
74
+ $contact = $this->convertToContactModel(json_decode(
75
+ (string) wp_json_encode($contact),
76
+ true)
77
+ );
78
+ if ( ! empty($contact->getEmail()) ) {
79
+ array_push($contactsArray, $contact);
80
+ }
81
+ } catch ( Exception $exception ) {
82
+ RaygunManager::get_instance()->exception_handler($exception);
83
+ continue;
84
+ }
85
+ if ( isset($limit) && count($contactsArray) >= $limit ) {
86
+ break;
87
+ }
88
+ }
89
+ if ( ! empty($contactsArray) ) {
90
+ return $contactsArray;
91
+ }
92
+ return null;
93
+ }
94
  }
src/Modules/Contacts/Handlers/ElementorPluginHandler.php CHANGED
@@ -7,103 +7,97 @@ define('CE4WP_EL_EVENTTYPE', 'WordPress - Elementor');
7
  use CreativeMail\Managers\RaygunManager;
8
  use CreativeMail\Modules\Contacts\Models\ContactModel;
9
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
10
-
11
- class ElementorPluginHandler extends BaseContactFormPluginHandler
12
- {
13
- function __construct()
14
- {
15
- parent::__construct();
16
- }
17
-
18
- private function GetNameFromForm($fields)
19
- {
20
- foreach ($fields as $field) {
21
- //Try to find a name value based on the default Elementor form with name field
22
- if (array_key_exists('type', $field) && ($field['type'] === "text" && $field['id'] === "name")) {
23
- return $field["value"];
24
- }
25
- }
26
- return null;
27
- }
28
-
29
- private function FindFormData($elemContact, $fields)
30
- {
31
- foreach ($fields as $field) {
32
- if (array_key_exists('type', $field) && in_array($field['type'], $this->emailFields)) {
33
- $elemContact->email = $field["value"];
34
- } elseif (array_key_exists('type', $field) && in_array($field['type'], $this->phoneFields)) {
35
- $elemContact->phone = $field["value"];
36
- } elseif (array_key_exists('type', $field) && $field['type'] === 'date' && in_array(strtolower($field['title']), $this->birthdayFields)) {
37
- $elemContact->birthday = $field["value"];
38
- }
39
- }
40
- }
41
-
42
- public function convertToContactModel($contact)
43
- {
44
- $contactModel = new ContactModel();
45
-
46
- $contactModel->setEventType(CE4WP_EL_EVENTTYPE);
47
-
48
- $contactModel->setOptIn(true);
49
- $contactModel->setOptOut(false);
50
- $contactModel->setOptActionBy(OptActionBy::Visitor);
51
-
52
- if (!empty($contact->email)) {
53
- $contactModel->setEmail($contact->email);
54
- }
55
-
56
- $values = explode(' ', $contact->name);
57
- $firstName = array_shift($values);
58
- $lastName = implode(' ', $values);
59
-
60
- if (!empty($firstName)) {
61
- $contactModel->setFirstName($firstName);
62
- }
63
- if (!empty($lastName)) {
64
- $contactModel->setLastName($lastName);
65
- }
66
- if (!empty($contact->phone)) {
67
- $contactModel->setPhone($contact->phone);
68
- }
69
- if (!empty($contact->birthday)) {
70
- $contactModel->setBirthday($contact->birthday);
71
- }
72
- return $contactModel;
73
- }
74
-
75
- public function ceHandleElementorFormSubmission($settings, $record)
76
- {
77
- try {
78
- $fields = $record->get("fields");
79
- $elemContact = new \stdClass();
80
- $elemContact->name = $this->GetNameFromForm($fields);
81
-
82
- //attempt to get additional data
83
- $this->FindFormData($elemContact, $fields);
84
- if (empty($elemContact->email)) {
85
- return;
86
- }
87
-
88
- $this->upsertContact($this->convertToContactModel($elemContact));
89
- } catch (\Exception $exception) {
90
- RaygunManager::get_instance()->exception_handler($exception);
91
- }
92
- }
93
-
94
- public function registerHooks()
95
- {
96
- add_action('elementor_pro/forms/mail_sent', array($this, 'ceHandleElementorFormSubmission'), 10, 2);
97
- }
98
-
99
- public function unregisterHooks()
100
- {
101
- remove_action('elementor_pro/forms/mail_sent', array($this, 'ceHandleElementorFormSubmission'));
102
- }
103
-
104
- public function get_contacts($limit = null)
105
- {
106
- //Elementor seems to not store form submissions locally
107
- return null;
108
- }
109
  }
7
  use CreativeMail\Managers\RaygunManager;
8
  use CreativeMail\Modules\Contacts\Models\ContactModel;
9
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
10
+ use Exception;
11
+ use stdClass;
12
+
13
+ class ElementorPluginHandler extends BaseContactFormPluginHandler {
14
+
15
+ public function __construct() {
16
+ parent::__construct();
17
+ }
18
+
19
+ private function GetNameFromForm( $fields ) {
20
+ foreach ( $fields as $field ) {
21
+ // Try to find a name value based on the default Elementor form with name field.
22
+ if ( array_key_exists('type', $field) && ( 'text' === $field['type'] && 'name' === $field['id'] ) ) {
23
+ return $field['value'];
24
+ }
25
+ }
26
+ return null;
27
+ }
28
+
29
+ private function FindFormData( $elemContact, $fields ) {
30
+ foreach ( $fields as $field ) {
31
+ if ( array_key_exists('type', $field) && in_array($field['type'], $this->emailFields, true) ) {
32
+ $elemContact->email = $field['value'];
33
+ } elseif ( array_key_exists('type', $field) && in_array($field['type'], $this->phoneFields, true) ) {
34
+ $elemContact->phone = $field['value'];
35
+ } elseif ( array_key_exists('type', $field) && 'date' === $field['type'] && in_array(strtolower($field['title']), $this->birthdayFields, true) ) {
36
+ $elemContact->birthday = $field['value'];
37
+ }
38
+ }
39
+ }
40
+
41
+ public function convertToContactModel( $contact ) {
42
+ $contactModel = new ContactModel();
43
+
44
+ $contactModel->setEventType(CE4WP_EL_EVENTTYPE);
45
+
46
+ $contactModel->setOptIn(true);
47
+ $contactModel->setOptOut(false);
48
+ $contactModel->setOptActionBy(OptActionBy::VISITOR);
49
+
50
+ if ( ! empty($contact->email) ) {
51
+ $contactModel->setEmail($contact->email);
52
+ }
53
+
54
+ $values = explode(' ', $contact->name);
55
+ $firstName = array_shift($values);
56
+ $lastName = implode(' ', $values);
57
+
58
+ if ( ! empty($firstName) ) {
59
+ $contactModel->setFirstName($firstName);
60
+ }
61
+ if ( ! empty($lastName) ) {
62
+ $contactModel->setLastName($lastName);
63
+ }
64
+ if ( ! empty($contact->phone) ) {
65
+ $contactModel->setPhone($contact->phone);
66
+ }
67
+ if ( ! empty($contact->birthday) ) {
68
+ $contactModel->setBirthday($contact->birthday);
69
+ }
70
+ return $contactModel;
71
+ }
72
+
73
+ public function ceHandleElementorFormSubmission( $settings, $record ) {
74
+ try {
75
+ $fields = $record->get('fields');
76
+ $elemContact = new stdClass();
77
+ $elemContact->name = $this->GetNameFromForm($fields);
78
+
79
+ // Attempt to get additional data.
80
+ $this->FindFormData($elemContact, $fields);
81
+ if ( empty($elemContact->email) ) {
82
+ return;
83
+ }
84
+
85
+ $this->upsertContact($this->convertToContactModel($elemContact));
86
+ } catch ( Exception $exception ) {
87
+ RaygunManager::get_instance()->exception_handler($exception);
88
+ }
89
+ }
90
+
91
+ public function registerHooks() {
92
+ add_action('elementor_pro/forms/mail_sent', array( $this, 'ceHandleElementorFormSubmission' ), 10, 2);
93
+ }
94
+
95
+ public function unregisterHooks() {
96
+ remove_action('elementor_pro/forms/mail_sent', array( $this, 'ceHandleElementorFormSubmission' ));
97
+ }
98
+
99
+ public function get_contacts( $limit = null ) {
100
+ // Elementor seems to not store form submissions locally.
101
+ return null;
102
+ }
 
 
 
 
 
 
103
  }
src/Modules/Contacts/Handlers/FormidablePluginHandler.php CHANGED
@@ -6,180 +6,175 @@ define('CE4WP_FRM_EVENTTYPE', 'WordPress - Formidable');
6
 
7
  use CreativeMail\Managers\RaygunManager;
8
  use CreativeMail\Modules\Contacts\Models\ContactModel;
 
9
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
10
  use Exception;
11
- use FrmField; // Formidable Field Class
12
- use FrmForm; // Formidable Forms Class
13
  use stdClass;
14
 
15
- class FormidablePluginHandler extends BaseContactFormPluginHandler
16
- {
17
- function __construct()
18
- {
19
- parent::__construct();
20
- }
21
-
22
- private function FindEntryValues($entry, $formidableContact)
23
- {
24
- if ($this->isNullOrEmpty($entry)) {
25
- return null;
26
- }
27
- foreach ($entry as $field) {
28
- $fieldName = strtolower($field->fieldName);
29
- if ($field->fieldType == 'phone' || in_array($fieldName, $this->phoneFields)) {
30
- $formidableContact->phone = $field->entryValue;
31
- } elseif ($field->fieldType == 'text' && in_array($fieldName, $this->firstnameFields)) {
32
- $formidableContact->firstName = $field->entryValue;
33
- } elseif ($field->fieldType == 'text' && in_array($fieldName, $this->lastnameFields)) {
34
- $formidableContact->lastName = $field->entryValue;
35
- } elseif ($field->fieldType == 'date' && in_array($fieldName, $this->birthdayFields)) {
36
- $formidableContact->birthday = $field->entryValue;
37
- } elseif ($field->fieldType == 'email') {
38
- $formidableContact->email = $field->entryValue;
39
- }
40
- }
41
- }
42
-
43
- public function convertToContactModel($contact)
44
- {
45
- $contactModel = new ContactModel();
46
-
47
- $contactModel->setEventType(CE4WP_FRM_EVENTTYPE);
48
-
49
- if (isset($contact->isSync) && $contact->isSync) {
50
- $contactModel->setOptIn(true);
51
- $contactModel->setOptOut(false);
52
- $contactModel->setOptActionBy(OptActionBy::Owner);
53
- }
54
-
55
- //Formidable doesn't seem to have a consent checkbox
56
-
57
- if (!empty($contact->email)) {
58
- $contactModel->setEmail($contact->email);
59
- }
60
-
61
- if (!empty($contact->firstName)) {
62
- $contactModel->setFirstName($contact->firstName);
63
- }
64
-
65
- if (!empty($contact->lastName)) {
66
- $contactModel->setLastName($contact->lastName);
67
- }
68
-
69
- if (!empty($contact->phone)) {
70
- $contactModel->setPhone($contact->phone);
71
- }
72
- if (!empty($contact->birthday)) {
73
- $contactModel->setBirthday($contact->birthday);
74
- }
75
- return $contactModel;
76
- }
77
-
78
- public function ceHandleFormidableFormSubmission($entry_id, $form_id)
79
- {
80
- try {
81
- //map entry values to the field meta
82
- $entry = FrmField::get_all_for_form($form_id);
83
- $entryFieldData = $_POST["item_meta"];
84
- foreach ($entry as $field) {
85
- if (!empty($entryFieldData[$field->id])) {
86
- $field->entryValue = $entryFieldData[$field->id];
87
- $field->fieldType = $field->type;
88
- $field->fieldName = $field->name;
89
- }
90
- }
91
- $formidableContact = new stdClass();
92
-
93
- //Convert to contactModel
94
- $this->FindEntryValues($entry, $formidableContact);
95
-
96
- if (empty($formidableContact->email)) {
97
- return;
98
- }
99
- $this->upsertContact($this->convertToContactModel($formidableContact));
100
- } catch (Exception $exception) {
101
- RaygunManager::get_instance()->exception_handler($exception);
102
- }
103
- }
104
-
105
- public function registerHooks()
106
- {
107
- add_action('frm_after_create_entry', array($this, 'ceHandleFormidableFormSubmission'), 30, 2);
108
- }
109
-
110
- public function unregisterHooks()
111
- {
112
- remove_action('frm_after_create_entry', array($this, 'ceHandleFormidableFormSubmission'));
113
- }
114
-
115
- public function get_contacts($limit = null)
116
- {
117
- if (!is_int($limit) || $limit <= 0) {
118
- $limit = null;
119
- }
120
-
121
- if (in_array('formidable/formidable.php', apply_filters('active_plugins', get_option('active_plugins')))) {
122
- global $wpdb;
123
- $contactsArray = array();
124
-
125
- $forms = FrmForm::getAll();
126
- if (is_array($forms)) {
127
- foreach ($forms as $form) {
128
- $entriesQuery = "SELECT e.item_id AS entryId, e.meta_value AS entryValue, f.name AS fieldName, f.description AS fieldDescription, f.type AS fieldType
129
  FROM wp_frm_item_metas e
130
- INNER JOIN wp_frm_fields f ON f.id = e.field_id WHERE f.form_id = {$form->id} ORDER BY e.item_id";
131
-
132
- $entryResults = $wpdb->get_results($wpdb->prepare($entriesQuery));
133
- if (empty($entryResults)) {
134
- continue;
135
- }
136
-
137
- $mappedEntries = $this->CombineEntryData($entryResults);
138
-
139
- // Get the contact data for each entry.
140
- foreach ($mappedEntries as $entry) {
141
- $formidableContact = new stdClass();
142
-
143
- // Convert to contactModel.
144
- $this->FindEntryValues($entry, $formidableContact);
145
-
146
- if (empty($formidableContact->email)) {
147
- continue;
148
- }
149
- $formidableContact->isSync = true;
150
- try {
151
- $contactModel = null;
152
- $contactModel = $this->convertToContactModel($formidableContact);
153
- } catch (Exception $exception) {
154
- RaygunManager::get_instance()->exception_handler($exception);
155
- continue;
156
- }
157
- if (!empty($contactModel->email)) {
158
- array_push($contactsArray, $contactModel);
159
- }
160
- if (isset($limit) && count($contactsArray) >= $limit) {
161
- break;
162
- }
163
- }
164
- }
165
- }
166
- if (!empty($contactsArray)) {
167
- return $contactsArray;
168
- }
169
- return null;
170
- }
171
- }
172
-
173
- private function CombineEntryData(array $entryResults)
174
- {
175
- $entries = array();
176
- foreach ($entryResults as $entryRow) {
177
- if (isset($entryRow->entryId)) {
178
- $entries[$entryRow->entryId][] = $entryRow;
179
- } elseif (isset($entryRow->id)) {
180
- $entries[$entryRow->id][] = $entryRow;
181
- }
182
- }
183
- return $entries;
184
- }
185
  }
6
 
7
  use CreativeMail\Managers\RaygunManager;
8
  use CreativeMail\Modules\Contacts\Models\ContactModel;
9
+ use CreativeMail\Modules\Contacts\Models\FormidableContactForm;
10
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
11
  use Exception;
12
+ use FrmField; // Formidable Field Class.
13
+ use FrmForm; // Formidable Forms Class.
14
  use stdClass;
15
 
16
+ class FormidablePluginHandler extends BaseContactFormPluginHandler {
17
+
18
+ public function __construct() {
19
+ parent::__construct();
20
+ }
21
+
22
+ private function FindEntryValues( $entry, $formidableContact ) {
23
+ if ( $this->isNullOrEmpty($entry) ) {
24
+ return null;
25
+ }
26
+ foreach ( $entry as $field ) {
27
+ $fieldName = strtolower($field->fieldName);
28
+ if ( 'phone' == $field->fieldType || in_array($fieldName, $this->phoneFields, true) ) {
29
+ $formidableContact->phone = $field->entryValue;
30
+ } elseif ( 'text' == $field->fieldType && in_array($fieldName, $this->firstnameFields, true) ) {
31
+ $formidableContact->firstName = $field->entryValue;
32
+ } elseif ( 'text' == $field->fieldType && in_array($fieldName, $this->lastnameFields, true) ) {
33
+ $formidableContact->lastName = $field->entryValue;
34
+ } elseif ( 'date' == $field->fieldType && in_array($fieldName, $this->birthdayFields, true) ) {
35
+ $formidableContact->birthday = $field->entryValue;
36
+ } elseif ( 'email' == $field->fieldType ) {
37
+ $formidableContact->email = $field->entryValue;
38
+ }
39
+ }
40
+ }
41
+
42
+ public function convertToContactModel( $contact ) {
43
+ $contactModel = new ContactModel();
44
+ $contactModel->setEventType(CE4WP_FRM_EVENTTYPE);
45
+
46
+ if ( isset($contact->isSync) && $contact->isSync ) {
47
+ $contactModel->setOptIn(true);
48
+ $contactModel->setOptOut(false);
49
+ $contactModel->setOptActionBy(OptActionBy::OWNER);
50
+ }
51
+
52
+ // Formidable doesn't seem to have a consent checkbox.
53
+ if ( ! empty($contact->email) ) {
54
+ $contactModel->setEmail($contact->email);
55
+ }
56
+ if ( ! empty($contact->firstName) ) {
57
+ $contactModel->setFirstName($contact->firstName);
58
+ }
59
+ if ( ! empty($contact->lastName) ) {
60
+ $contactModel->setLastName($contact->lastName);
61
+ }
62
+ if ( ! empty($contact->phone) ) {
63
+ $contactModel->setPhone($contact->phone);
64
+ }
65
+ if ( ! empty($contact->birthday) ) {
66
+ $contactModel->setBirthday($contact->birthday);
67
+ }
68
+ return $contactModel;
69
+ }
70
+
71
+ public function ceHandleFormidableFormSubmission( $entry_id, $form_id ) {
72
+ try {
73
+ $formidableContact = new FormidableContactForm();
74
+ // Map entry values to the field meta.
75
+ $entry = FrmField::get_all_for_form($form_id);
76
+
77
+ if ( isset ( $_POST['frm_submit_entry_2'] )
78
+ && wp_verify_nonce(
79
+ sanitize_text_field( wp_unslash( $_POST['frm_submit_entry_2']) ),
80
+ 'frm_submit_entry_nonce' )
81
+ ) {
82
+ if ( isset ($_POST['item_meta']) ) {
83
+ $entryFieldData = array_map( 'sanitize_text_field', wp_unslash( $_POST['item_meta'] ) );
84
+ }
85
+ }
86
+ foreach ( $entry as $field ) {
87
+ if ( ! empty($entryFieldData[ $field->id ]) ) {
88
+ $field->entryValue = $entryFieldData[ $field->id ];
89
+ $field->fieldType = $field->type;
90
+ $field->fieldName = $field->name;
91
+ }
92
+ }
93
+
94
+ // Convert to contactModel.
95
+ $this->FindEntryValues($entry, $formidableContact);
96
+
97
+ if ( empty($formidableContact->email) ) {
98
+ return;
99
+ }
100
+ $this->upsertContact($this->convertToContactModel($formidableContact));
101
+ } catch ( Exception $exception ) {
102
+ RaygunManager::get_instance()->exception_handler($exception);
103
+ }
104
+ }
105
+
106
+ public function registerHooks() {
107
+ add_action('frm_after_create_entry', array( $this, 'ceHandleFormidableFormSubmission' ), 30, 2);
108
+ }
109
+
110
+ public function unregisterHooks() {
111
+ remove_action('frm_after_create_entry', array( $this, 'ceHandleFormidableFormSubmission' ));
112
+ }
113
+
114
+ public function get_contacts( $limit = null ) {
115
+ if ( ! is_int($limit) || $limit <= 0 ) {
116
+ $limit = null;
117
+ }
118
+
119
+ if ( in_array('formidable/formidable.php', apply_filters('active_plugins', get_option('active_plugins')), true) ) {
120
+ global $wpdb;
121
+ $contactsArray = array();
122
+
123
+ $forms = FrmForm::getAll();
124
+ if ( is_array($forms) ) {
125
+ foreach ( $forms as $form ) {
126
+ $entryResults = $wpdb->get_results($wpdb->prepare('SELECT e.item_id AS entryId, e.meta_value AS entryValue, f.name AS fieldName, f.description AS fieldDescription, f.type AS fieldType
 
 
 
127
  FROM wp_frm_item_metas e
128
+ INNER JOIN wp_frm_fields f ON f.id = e.field_id WHERE f.form_id = %s ORDER BY e.item_id', $form->id));
129
+ if ( empty($entryResults) ) {
130
+ continue;
131
+ }
132
+
133
+ $mappedEntries = $this->CombineEntryData($entryResults);
134
+
135
+ // Get the contact data for each entry.
136
+ foreach ( $mappedEntries as $entry ) {
137
+ $formidableContact = new stdClass();
138
+
139
+ // Convert to contactModel.
140
+ $this->FindEntryValues($entry, $formidableContact);
141
+
142
+ if ( empty($formidableContact->email) ) {
143
+ continue;
144
+ }
145
+ $formidableContact->isSync = true;
146
+ try {
147
+ $contactModel = null;
148
+ $contactModel = $this->convertToContactModel($formidableContact);
149
+ } catch ( Exception $exception ) {
150
+ RaygunManager::get_instance()->exception_handler($exception);
151
+ continue;
152
+ }
153
+ if ( ! empty($contactModel->email) ) {
154
+ array_push($contactsArray, $contactModel);
155
+ }
156
+ if ( isset($limit) && count($contactsArray) >= $limit ) {
157
+ break;
158
+ }
159
+ }
160
+ }
161
+ }
162
+ if ( ! empty($contactsArray) ) {
163
+ return $contactsArray;
164
+ }
165
+ return null;
166
+ }
167
+ }
168
+
169
+ private function CombineEntryData( array $entryResults ) {
170
+ $entries = array();
171
+ foreach ( $entryResults as $entryRow ) {
172
+ if ( isset($entryRow->entryId) ) {
173
+ $entries[ $entryRow->entryId ][] = $entryRow;
174
+ } elseif ( isset($entryRow->id) ) {
175
+ $entries[ $entryRow->id ][] = $entryRow;
176
+ }
177
+ }
178
+ return $entries;
179
+ }
 
 
 
180
  }
src/Modules/Contacts/Handlers/GravityFormsPluginHandler.php CHANGED
@@ -8,233 +8,260 @@ use CreativeMail\Managers\RaygunManager;
8
  use CreativeMail\Modules\Contacts\Models\ContactModel;
9
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
10
  use Exception;
11
-
12
- class GravityFormsPluginHandler extends BaseContactFormPluginHandler
13
- {
14
- private $textFormFields = array('text', 'textarea');
15
-
16
- public function convertToContactModel($user)
17
- {
18
- $contactModel = new ContactModel();
19
-
20
- $contactModel->setEventType(CE4WP_GF_EVENTTYPE);
21
-
22
- // If it's a DB sync we set optin on true, action by owner.
23
- if ($user->isSync) {
24
- $contactModel->setOptIn(true);
25
- $contactModel->setOptOut(false);
26
- $contactModel->setOptActionBy(OptActionBy::Owner);
27
- } else {
28
- // Get contact data from submission.
29
- $contactModel->setOptIn(boolval($user->consent));
30
- $contactModel->setOptActionBy(OptActionBy::Visitor);
31
- }
32
-
33
- $email = $user->email;
34
- if (!empty($email)) {
35
- $contactModel->setEmail($email);
36
- }
37
-
38
- $firstName = isset($user->name['firstName']) ? $user->name['firstName'] : null;
39
- $insertion = isset($user->name['insertion']) ? $user->name['insertion'] : null;
40
- $lastName = isset($user->name['lastName']) ? $user->name['lastName'] : null;
41
-
42
- if (!empty($firstName)) {
43
- $contactModel->setFirstName($firstName);
44
- }
45
-
46
- if (!empty($lastName)) {
47
- if (!empty($insertion)) {
48
- $lastName = implode(' ', [$insertion, $lastName]);
49
- }
50
- $contactModel->setLastName($lastName);
51
- }
52
- if (!empty($user->phone)) {
53
- $contactModel->setPhone($user->phone);
54
- }
55
- if (!empty($user->birthday)) {
56
- $contactModel->setBirthday($user->birthday);
57
- }
58
-
59
- return $contactModel;
60
- }
61
-
62
- /**
63
- * Gets the first name, optional insertion and last name from the Contact Form
64
- *
65
- * @param $entry (The form submission)
66
- * @param $form (The form used)
67
- *
68
- * @return array (concatenated firstname, insertion and lastname) Returns the concatenated name
69
- */
70
- private function GetNameValuesFromForm($entry, $form)
71
- {
72
- $name_values = array();
73
- foreach ($form['fields'] as $field) {
74
- if ($field["type"] == "name") {
75
- $values = $field["inputs"];
76
- $name_values["firstName"] = rgar($entry, $values[1]["id"]);
77
- $name_values["insertion"] = rgar($entry, $values[2]["id"]);
78
- $name_values["lastName"] = rgar($entry, $values[3]["id"]);
79
- }
80
- }
81
- return $name_values;
82
- }
83
-
84
- /**
85
- * Attempts to get the email from the email field if present,
86
- * otherwise searches text fields for email labels and values
87
- * Returns the value of the email field or the first valid email found in an "email" labelled text field, or NULL
88
- *
89
- * @param $entry (The form submission)
90
- * @param $form (The form used)
91
- *
92
- * @return string (either a validated email or NULL)
93
- */
94
- private function GetEmailFromForm($entry, $form)
95
- {
96
- $email = null;
97
- // Check for email type in form.
98
- foreach ($form['fields'] as $field) {
99
- if ($field["type"] == "email") {
100
- $email = rgar($entry, $field["id"]);
101
- //Check if the values is a valid email
102
- if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
103
- return $email;
104
- }
105
- }
106
- }
107
- // Else check if we can find an email value in text fields.
108
- foreach ($form['fields'] as $field) {
109
- if (in_array(strtolower($field["type"]), $this->textFormFields) && in_array(strtolower($field["label"]), $this->emailFields)) {
110
- $possibleEmail = rgar($entry, $field["id"]);
111
- if (filter_var($possibleEmail, FILTER_VALIDATE_EMAIL)) {
112
- return $possibleEmail;
113
- }
114
- }
115
- }
116
- return $email;
117
- }
118
-
119
- private function FindFormData($contact, $entry, $form)
120
- {
121
- foreach ($form['fields'] as $field) {
122
- if (strtolower($field["type"]) === 'phone') {
123
- $contact->phone = rgar($entry, $field["id"]);
124
- } elseif (strtolower($field["type"]) === 'date' && in_array(strtolower($field["label"]), $this->birthdayFields)) {
125
- $contact->birthday = rgar($entry, $field["id"]);
126
- } elseif (strtolower($field["type"]) === 'consent' && strtolower($field["label"]) === 'consent') {
127
- $contact->consent = rgar($entry, (string)($field["id"] + .1)); //consent values in the entry are weird
128
- }
129
- }
130
- }
131
-
132
- public function ceHandleGravityFormSubmission($entry, $form)
133
- {
134
- try {
135
- $contact = new \stdClass();
136
- $contact->name = $this->GetNameValuesFromForm($entry, $form);
137
- $contact->email = $this->GetEmailFromForm($entry, $form);
138
- $this->FindFormData($contact, $entry, $form);
139
- if (empty($contact->email)) {
140
- return;
141
- }
142
-
143
- $contact->isSync = false;
144
- $this->upsertContact($this->convertToContactModel($contact));
145
- } catch (Exception $exception) {
146
- RaygunManager::get_instance()->exception_handler($exception);
147
- }
148
- }
149
-
150
- public function registerHooks()
151
- {
152
- add_action('gform_after_submission', array($this, 'ceHandleGravityFormSubmission'), 10, 2);
153
- }
154
-
155
- public function unregisterHooks()
156
- {
157
- remove_action('gform_after_submission', array($this, 'ceHandleGravityFormSubmission'));
158
- }
159
-
160
- public function get_contacts($limit = null)
161
- {
162
- if (!is_int($limit) || $limit <= 0) {
163
- $limit = null;
164
- }
165
-
166
- // Relies on plugin => GravityForms
167
- if (in_array('gravityforms/gravityforms.php', apply_filters('active_plugins', get_option('active_plugins')))) {
168
- global $wpdb;
169
-
170
- $contactsArray = array();
171
-
172
- //get the forms and their fields
173
- $formsQuery = 'SELECT form_id, display_meta FROM wp_gf_form_meta';
174
- $formsResult = $wpdb->get_results($wpdb->prepare($formsQuery));
175
-
176
- //loop through the forms and get their respective entries
177
- foreach ($formsResult as $form) {
178
- //get the entries and their meta (i think only meta is needed)
179
- $entriesQuery = 'SELECT entry_id, meta_key, meta_value FROM wp_gf_entry_meta';
180
- $entriesQuery .= " WHERE form_id = $form->form_id";
181
- $entryResults = $wpdb->get_results($entriesQuery);
182
- if (empty($entryResults)) {
183
- continue;
184
- }
185
-
186
- //combine all entry meta into their respective entries
187
- $entries = array();
188
- foreach ($entryResults as $entry) {
189
- $entries[$entry->entry_id][$entry->meta_key] = $entry->meta_value;
190
- }
191
-
192
- //Get the contact data for each entry
193
- foreach ($entries as $entry) {
194
- $contact = new \stdClass();
195
-
196
- //Get the formArray from the display_meta
197
- $formArray = json_decode($form->display_meta, true);
198
-
199
- $contact->email = $this->GetEmailFromForm($entry, $formArray);
200
- if (empty($contact->email)) {
201
- continue;
202
- }
203
- $contact->name = $this->GetNameValuesFromForm($entry, $formArray);
204
- $this->FindFormData($contact, $entry, $formArray);
205
- $contact->isSync = true;
206
-
207
- //Convert to contactModel.
208
- $contactModel = null;
209
- try {
210
- $contactModel = $this->convertToContactModel($contact);
211
- } catch (Exception $exception) {
212
- RaygunManager::get_instance()->exception_handler($exception);
213
- continue;
214
- }
215
-
216
- array_push($contactsArray, $contactModel);
217
-
218
- if (isset($limit) && count($contactsArray) >= $limit) {
219
- break;
220
- }
221
- }
222
-
223
- if (isset($limit) && count($contactsArray) >= $limit) {
224
- break;
225
- }
226
- }
227
- }
228
-
229
- if (!empty($contactsArray)) {
230
- return $contactsArray;
231
- }
232
-
233
- return null;
234
- }
235
-
236
- function __construct()
237
- {
238
- parent::__construct();
239
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
240
  }
8
  use CreativeMail\Modules\Contacts\Models\ContactModel;
9
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
10
  use Exception;
11
+ use stdClass;
12
+
13
+ final class GravityFormsPluginHandler extends BaseContactFormPluginHandler {
14
+
15
+ /**
16
+ * Save the text fields from the form.
17
+ *
18
+ * @var array<string>
19
+ */
20
+ private $textFormFields = array( 'text', 'textarea' );
21
+
22
+ public function __construct() {
23
+ parent::__construct();
24
+ }
25
+
26
+ /**
27
+ * Converts to contact model.
28
+ *
29
+ * @param object $user The user.
30
+ *
31
+ * @return ContactModel
32
+ *
33
+ * @throws Exception
34
+ */
35
+ public function convertToContactModel( $user ) {
36
+ $contactModel = new ContactModel();
37
+ $contactModel->setEventType(CE4WP_GF_EVENTTYPE);
38
+
39
+ // If it's a DB sync we set optin on true, action by owner.
40
+ if ( $user->isSync ) {
41
+ $contactModel->setOptIn(true);
42
+ $contactModel->setOptOut(false);
43
+ $contactModel->setOptActionBy(OptActionBy::OWNER);
44
+ } else {
45
+ // Get contact data from submission.
46
+ $contactModel->setOptIn(boolval($user->consent));
47
+ $contactModel->setOptActionBy(OptActionBy::VISITOR);
48
+ }
49
+
50
+ $email = $user->email;
51
+ if ( ! empty($email) ) {
52
+ $contactModel->setEmail($email);
53
+ }
54
+
55
+ $firstName = isset($user->name['firstName']) ? $user->name['firstName'] : null;
56
+ $insertion = isset($user->name['insertion']) ? $user->name['insertion'] : null;
57
+ $lastName = isset($user->name['lastName']) ? $user->name['lastName'] : null;
58
+
59
+ if ( ! empty($firstName) ) {
60
+ $contactModel->setFirstName($firstName);
61
+ }
62
+
63
+ if ( ! empty($lastName) ) {
64
+ if ( ! empty($insertion) ) {
65
+ $lastName = implode(' ', array( $insertion, $lastName ));
66
+ }
67
+ $contactModel->setLastName($lastName);
68
+ }
69
+ if ( ! empty($user->phone) ) {
70
+ $contactModel->setPhone($user->phone);
71
+ }
72
+ if ( ! empty($user->birthday) ) {
73
+ $contactModel->setBirthday($user->birthday);
74
+ }
75
+
76
+ return $contactModel;
77
+ }
78
+
79
+ /**
80
+ * Gets the first name, optional insertion and last name from the Contact Form.
81
+ *
82
+ * @param mixed $entry (The form submission).
83
+ * @param array<string, mixed> $form (The form used).
84
+ *
85
+ * @return array (concatenated firstname, insertion and lastname) Returns the concatenated name.
86
+ */
87
+ private function GetNameValuesFromForm( $entry, $form ): array {
88
+ $name_values = array();
89
+
90
+ foreach ( $form['fields'] as $field ) {
91
+ if ( 'name' == $field['type'] ) {
92
+ $values = $field['inputs'];
93
+ $name_values['firstName'] = rgar($entry, $values[1]['id']);
94
+ $name_values['insertion'] = rgar($entry, $values[2]['id']);
95
+ $name_values['lastName'] = rgar($entry, $values[3]['id']);
96
+ }
97
+ }
98
+
99
+ return $name_values;
100
+ }
101
+
102
+ /**
103
+ * Attempts to get the email from the email field if present,
104
+ * otherwise searches text fields for email labels and values
105
+ * Returns the value of the email field or the first valid email found in an "email" labelled text field, or NULL
106
+ *
107
+ * @param mixed $entry The form submission.
108
+ * @param array<string|mixed> $form The form used.
109
+ *
110
+ * @return string (either a validated email or NULL)
111
+ */
112
+ private function GetEmailFromForm( $entry, $form ): ?string {
113
+ $email = null;
114
+ // Check for email type in form.
115
+ foreach ( $form['fields'] as $field ) {
116
+ if ( 'email' == $field['type'] ) {
117
+ $email = rgar($entry, $field['id']);
118
+ // Check if the values is a valid email.
119
+ if ( filter_var($email, FILTER_VALIDATE_EMAIL) ) {
120
+ return $email;
121
+ }
122
+ }
123
+ }
124
+ // Else check if we can find an email value in text fields.
125
+ foreach ( $form['fields'] as $field ) {
126
+ if ( in_array(strtolower($field['type']), $this->textFormFields, true)
127
+ && in_array(strtolower($field['label']), $this->emailFields, true) ) {
128
+ $possibleEmail = rgar($entry, $field['id']);
129
+ if ( filter_var($possibleEmail, FILTER_VALIDATE_EMAIL) ) {
130
+ return $possibleEmail;
131
+ }
132
+ }
133
+ }
134
+ return $email;
135
+ }
136
+
137
+ /**
138
+ * Finds all the data from the form.
139
+ *
140
+ * @param mixed $contact The contact.
141
+ * @param mixed $entry The form entry.
142
+ * @param array<string|mixed> $form The form.
143
+ *
144
+ * @return void
145
+ */
146
+ private function FindFormData( $contact, $entry, $form ): void {
147
+ foreach ( $form['fields'] as $field ) {
148
+ if ( 'phone' === strtolower($field['type']) ) {
149
+ $contact->phone = rgar($entry, $field['id']);
150
+ } elseif ( strtolower($field['type']) === 'date' && in_array(strtolower($field['label']), $this->birthdayFields, true) ) {
151
+ $contact->birthday = rgar($entry, $field['id']);
152
+ } elseif ( strtolower($field['type']) === 'consent' && strtolower($field['label']) === 'consent' ) {
153
+ // Consent values in the entry are not common.
154
+ $contact->consent = rgar($entry, (string) ( $field['id'] + .1 ));
155
+ }
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Handles the form submission.
161
+ *
162
+ * @param mixed $entry The entries' submission.
163
+ * @param array<string, mixed> $form The form used.
164
+ *
165
+ * @return void
166
+ */
167
+ public function ceHandleGravityFormSubmission( $entry, $form ) {
168
+ try {
169
+ $contact = new stdClass();
170
+ $contact->name = $this->GetNameValuesFromForm($entry, $form);
171
+ $contact->email = $this->GetEmailFromForm($entry, $form);
172
+ $this->FindFormData($contact, $entry, $form);
173
+ if ( empty($contact->email) ) {
174
+ return;
175
+ }
176
+
177
+ $contact->isSync = false;
178
+ $this->upsertContact($this->convertToContactModel($contact));
179
+ } catch ( Exception $exception ) {
180
+ RaygunManager::get_instance()->exception_handler($exception);
181
+ }
182
+ }
183
+
184
+ public function registerHooks() {
185
+ add_action('gform_after_submission', array( $this, 'ceHandleGravityFormSubmission' ), 10, 2);
186
+ }
187
+
188
+ public function unregisterHooks() {
189
+ remove_action('gform_after_submission', array( $this, 'ceHandleGravityFormSubmission' ));
190
+ }
191
+
192
+ /**
193
+ * Return all the contacts.
194
+ *
195
+ * @param int|null $limit The limit of contacts to return.
196
+ *
197
+ * @return array|null
198
+ */
199
+ public function get_contacts( $limit = null ) {
200
+ if ( ! is_int($limit) || $limit <= 0 ) {
201
+ $limit = null;
202
+ }
203
+
204
+ // Relies on plugin => GravityForms.
205
+ if ( in_array('gravityforms/gravityforms.php', apply_filters('active_plugins', get_option('active_plugins')), true) ) {
206
+ global $wpdb;
207
+ $contactsArray = array();
208
+
209
+ // Get the forms and their fields.
210
+ $formsResult = $wpdb->get_results('SELECT form_id, display_meta FROM wp_gf_form_meta');
211
+
212
+ // Loop through the forms and get their respective entries.
213
+ foreach ( $formsResult as $form ) {
214
+ // Get the entries and their meta (I think only meta is needed).
215
+ $entryResults = $wpdb->get_results( $wpdb->prepare( 'SELECT entry_id, meta_key, meta_value FROM wp_gf_entry_meta WHERE form_id = %s', $form->form_id ) );
216
+ if ( empty($entryResults) ) {
217
+ continue;
218
+ }
219
+ // Combine all entry meta into their respective entries.
220
+ $entries = array();
221
+ foreach ( $entryResults as $entry ) {
222
+ $entries[ $entry->entry_id ][ $entry->meta_key ] = $entry->meta_value;
223
+ }
224
+
225
+ // Get the contact data for each entry.
226
+ foreach ( $entries as $entry ) {
227
+ $contact = new stdClass();
228
+ // Get the formArray from the display_meta.
229
+ $formArray = json_decode($form->display_meta, true);
230
+
231
+ $contact->email = $this->GetEmailFromForm($entry, $formArray);
232
+ if ( empty($contact->email) ) {
233
+ continue;
234
+ }
235
+ $contact->name = $this->GetNameValuesFromForm($entry, $formArray);
236
+ $this->FindFormData($contact, $entry, $formArray);
237
+ $contact->isSync = true;
238
+
239
+ // Convert to contactModel.
240
+ $contactModel = null;
241
+ try {
242
+ $contactModel = $this->convertToContactModel($contact);
243
+ } catch ( Exception $exception ) {
244
+ RaygunManager::get_instance()->exception_handler($exception);
245
+ continue;
246
+ }
247
+
248
+ array_push($contactsArray, $contactModel);
249
+
250
+ if ( isset($limit) && count($contactsArray) >= $limit ) {
251
+ break;
252
+ }
253
+ }
254
+
255
+ if ( isset($limit) && count($contactsArray) >= $limit ) {
256
+ break;
257
+ }
258
+ }
259
+ }
260
+
261
+ if ( ! empty($contactsArray) ) {
262
+ return $contactsArray;
263
+ }
264
+
265
+ return null;
266
+ }
267
  }
src/Modules/Contacts/Handlers/JetpackPluginHandler.php CHANGED
@@ -7,212 +7,245 @@ define('CE4WP_JP_EVENTTYPE', 'WordPress - Jetpack');
7
  use CreativeMail\Managers\RaygunManager;
8
  use CreativeMail\Modules\Contacts\Models\ContactModel;
9
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
10
-
11
- class JetpackPluginHandler extends BaseContactFormPluginHandler
12
- {
13
- function __construct()
14
- {
15
- parent::__construct();
16
- }
17
-
18
- public function convertToContactModel($contact)
19
- {
20
- $contactModel = new ContactModel();
21
-
22
- $contactModel->setEventType(CE4WP_JP_EVENTTYPE);
23
-
24
- //email_marketing_consent
25
- if ($contact->opt_in) {
26
- $contactModel->setOptIn(true);
27
- $contactModel->setOptOut(false);
28
- $contactModel->setOptActionBy(OptActionBy::Visitor);
29
- }
30
-
31
- $email = $contact->email;
32
- if (!empty($email)) {
33
- $contactModel->setEmail($email);
34
- }
35
-
36
- $values = explode(' ', $contact->name);
37
- $firstName = array_shift($values);
38
- $lastName = implode(' ', $values);
39
-
40
- if (!empty($firstName)) {
41
- $contactModel->setFirstName($firstName);
42
- }
43
- if (!empty($lastName)) {
44
- $contactModel->setLastName($lastName);
45
- }
46
- if (!empty($contact->phone)) {
47
- $contactModel->setPhone($contact->phone);
48
- }
49
- if (!empty($contact->birthday)) {
50
- $contactModel->setBirthday($contact->birthday);
51
- }
52
- return $contactModel;
53
- }
54
-
55
- private function GetNameAndEmailFromHeader($header)
56
- {
57
- $headerRegex = '/(?:^Reply-To: ")(.*)(?:" <)(.*)(?:>)/mi';
58
- preg_match($headerRegex, $header, $regexMatches);
59
- $values = null;
60
-
61
- if(count($regexMatches) == 0)
62
- {
63
- $headerRegexWithNoQuote = '/(?:^Reply-To: )(.*)(?: <)(.*)(?:>)/mi';
64
- preg_match($headerRegexWithNoQuote, $header, $regexMatches);
65
- }
66
-
67
- //Check if the name isn't an email address (happens when no name is supplied)
68
- $values["name"] = (!filter_var($regexMatches[1], FILTER_VALIDATE_EMAIL)) ? $regexMatches[1] : null;
69
- //Check if email is valid
70
- $values["email"] = (filter_var($regexMatches[2], FILTER_VALIDATE_EMAIL)) ? $regexMatches[2] : null;
71
-
72
- return $values;
73
- }
74
-
75
- public function ceHandleJetpackFormSubmission($post_id, $to, $subject, $message, $headers, $all_values, $extra_values)
76
- {
77
- try {
78
- $contact = new \stdClass();
79
- $nameAndEmail = $this->GetNameAndEmailFromHeader($headers);
80
- $contact->email = $nameAndEmail["email"];
81
- $contact->name = $nameAndEmail["name"];
82
- $contact->phone = $this->GetPhoneNumber($all_values);
83
-
84
- $contact->opt_in = boolval(isset($all_values['email_marketing_consent']) && $all_values['email_marketing_consent']);
85
-
86
- if (empty($contact->email)) {
87
- return;
88
- }
89
- $this->upsertContact($this->convertToContactModel($contact));
90
- } catch (\Exception $exception) {
91
- RaygunManager::get_instance()->exception_handler($exception);
92
- }
93
- }
94
-
95
- public function registerHooks()
96
- {
97
- add_action('grunion_after_message_sent', array($this, 'ceHandleJetpackFormSubmission'), 10, 7);
98
- }
99
-
100
- public function unregisterHooks()
101
- {
102
- remove_action('grunion_after_message_sent', array($this, 'ceHandleJetpackFormSubmission'));
103
- }
104
-
105
- public function get_contacts($limit = null)
106
- {
107
- if (!is_int($limit) || $limit <= 0) {
108
- $limit = null;
109
- }
110
-
111
- // Relies on plugin => Jetpack or Jetpack beta
112
- if (in_array('jetpack/jetpack.php', apply_filters('active_plugins', get_option('active_plugins')))
113
- || in_array('jetpack-beta-master/jetpack-beta.php', apply_filters('active_plugins', get_option('active_plugins')))
114
- ) {
115
- $authorRegex = '/(?:^AUTHOR: )(.*)/mi';
116
- $authorMailRegex = '/(?:^AUTHOR EMAIL: )(.*)/mi';
117
- $additionalFieldsRegex = '/(?:^\s{4})\[\d_(.*)\](?:.*;\s)(.*)/mi';
118
-
119
- $consentRegex = '/(?:\[email_marketing_consent] =&gt; )(.*)/mi';
120
- $contactsArray = array();
121
-
122
- //get all posts with type->feedback (i think these are all the contact forms submitted)
123
- $feedbackResults = get_posts(array('post_type' => 'feedback'));
124
-
125
- //loop through the feedbacks and get each blocks innerHTML
126
- foreach ($feedbackResults as $feedback) {
127
- foreach (parse_blocks($feedback->post_content) as $block) {
128
- $feedbackHtml = $block['innerHTML'];
129
-
130
- $author = '';
131
- //extract name, email and consent from submission
132
- preg_match($authorRegex, $feedbackHtml, $authorMatches);
133
- if (count($authorMatches) > 1) {
134
- $author = $authorMatches[1];
135
- }
136
-
137
- $authorEmail = '';
138
- preg_match($authorMailRegex, $feedbackHtml, $authorEmailMatches);
139
- if (count($authorEmailMatches) > 1) {
140
- $authorEmail = $authorEmailMatches[1];
141
- }
142
-
143
- $consentValue = false;
144
- preg_match($consentRegex, $feedbackHtml, $consentMatches);
145
- if (count($consentMatches) > 1) {
146
- $consentValue = $consentMatches[1];
147
- }
148
-
149
- $contact = new \stdClass();
150
- $contact->email = filter_var($authorEmail, FILTER_VALIDATE_EMAIL);
151
- if (empty($contact->email)) {
152
- continue;
153
- }
154
-
155
- if (!filter_var($author, FILTER_VALIDATE_EMAIL)) { //if the author field also contains an email, ignore it (this happens when no name is provided)
156
- $contact->name = $author;
157
- } else {
158
- $contact->name = null;
159
- }
160
-
161
- $contact->opt_in = boolval($consentValue);
162
-
163
- preg_match_all($additionalFieldsRegex, $feedbackHtml, $additionalFieldMatches);
164
- if (count($additionalFieldMatches) > 1) {
165
- foreach ($additionalFieldMatches[1] as $index => $label) {
166
- $fieldValue = $additionalFieldMatches[2][$index];
167
- if (in_array(strtolower($label), $this->phoneFields)) {
168
- $contact->phone = $fieldValue;
169
- } elseif (in_array(strtolower($label), $this->birthdayFields)) {
170
- $contact->birthday = $fieldValue;
171
- }
172
- }
173
- }
174
-
175
- //Convert to contactModel and push to the array
176
- $contactModel = null;
177
- try {
178
- $contactModel = $this->convertToContactModel($contact);
179
- } catch (\Exception $exception) {
180
- RaygunManager::get_instance()->exception_handler($exception);
181
- continue;
182
- }
183
-
184
- array_push($contactsArray, $contactModel);
185
-
186
- if (isset($limit) && count($contactsArray) >= $limit) {
187
- break;
188
- }
189
- }
190
-
191
- if (isset($limit) && count($contactsArray) >= $limit) {
192
- break;
193
- }
194
- }
195
-
196
- //upsert the contacts
197
- if (!empty($contactsArray)) {
198
- return $contactsArray;
199
- }
200
- }
201
-
202
- return null;
203
- }
204
-
205
- public function GetPhoneNumber($all_values)
206
- {
207
- $target_substring = "phone";
208
- // Loop through every field of the form
209
- foreach ($all_values as $key => $value) {
210
-
211
- // If the name of the key contains the substring "phone" then the value will be the phone number
212
- if (mb_strpos(strtolower($key), $target_substring) !== false)
213
- {
214
- return $value;
215
- }
216
- }
217
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  }
7
  use CreativeMail\Managers\RaygunManager;
8
  use CreativeMail\Modules\Contacts\Models\ContactModel;
9
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
10
+ use Exception;
11
+ use stdClass;
12
+
13
+ final class JetpackPluginHandler extends BaseContactFormPluginHandler {
14
+
15
+ public function __construct() {
16
+ parent::__construct();
17
+ }
18
+
19
+ /**
20
+ * Converts to contact model.
21
+ *
22
+ * @param object $contact The contact.
23
+ *
24
+ * @return ContactModel
25
+ * @throws Exception
26
+ */
27
+ public function convertToContactModel( $contact ) {
28
+ $contactModel = new ContactModel();
29
+ $contactModel->setEventType(CE4WP_JP_EVENTTYPE);
30
+
31
+ // Email Marketing Consent.
32
+ if ( $contact->opt_in ) {
33
+ $contactModel->setOptIn(true);
34
+ $contactModel->setOptOut(false);
35
+ $contactModel->setOptActionBy(OptActionBy::VISITOR);
36
+ }
37
+
38
+ $email = $contact->email;
39
+ if ( ! empty($email) ) {
40
+ $contactModel->setEmail($email);
41
+ }
42
+
43
+ $values = explode(' ', $contact->name);
44
+ $firstName = array_shift($values);
45
+ $lastName = implode(' ', $values);
46
+
47
+ if ( ! empty($firstName) ) {
48
+ $contactModel->setFirstName($firstName);
49
+ }
50
+ if ( ! empty($lastName) ) {
51
+ $contactModel->setLastName($lastName);
52
+ }
53
+ if ( ! empty($contact->phone) ) {
54
+ $contactModel->setPhone($contact->phone);
55
+ }
56
+ if ( ! empty($contact->birthday) ) {
57
+ $contactModel->setBirthday($contact->birthday);
58
+ }
59
+ return $contactModel;
60
+ }
61
+
62
+ /**
63
+ * Handles the contact form submission.
64
+ *
65
+ * @param string $header The header.
66
+ *
67
+ * @return array<string,mixed>
68
+ */
69
+ private function GetNameAndEmailFromHeader( string $header ): array {
70
+ $headerRegex = '/(?:^Reply-To: ")(.*)(?:" <)(.*)(?:>)/mi';
71
+ preg_match($headerRegex, $header, $regexMatches);
72
+ $values = null;
73
+
74
+ if ( count($regexMatches) == 0 ) {
75
+ $headerRegexWithNoQuote = '/(?:^Reply-To: )(.*)(?: <)(.*)(?:>)/mi';
76
+ preg_match($headerRegexWithNoQuote, $header, $regexMatches);
77
+ }
78
+
79
+ // Check if the name isn't an email address (happens when no name is supplied).
80
+ $values['name'] = ( ! filter_var($regexMatches[1], FILTER_VALIDATE_EMAIL) ) ? $regexMatches[1] : null;
81
+ // Check if email is valid.
82
+ $values['email'] = ( filter_var($regexMatches[2], FILTER_VALIDATE_EMAIL) ) ? $regexMatches[2] : null;
83
+
84
+ return $values;
85
+ }
86
+
87
+ /**
88
+ * Handles the contact form submission.
89
+ *
90
+ * @param int $post_id The post id.
91
+ * @param string $to The to.
92
+ * @param string $subject The subject.
93
+ * @param string $message The message.
94
+ * @param string $headers The headers.
95
+ * @param array $all_values The all values.
96
+ * @param array $extra_values The extra values.
97
+ *
98
+ * @return void
99
+ */
100
+ public function ceHandleJetpackFormSubmission( $post_id, $to, $subject, $message, $headers, $all_values, $extra_values ): void {
101
+ try {
102
+ $contact = new stdClass();
103
+ $nameAndEmail = $this->GetNameAndEmailFromHeader($headers);
104
+ $contact->email = $nameAndEmail['email'];
105
+ $contact->name = $nameAndEmail['name'];
106
+ $contact->phone = $this->GetPhoneNumber($all_values);
107
+ $contact->opt_in = boolval(isset($all_values['email_marketing_consent']) && $all_values['email_marketing_consent']);
108
+
109
+ if ( empty($contact->email) ) {
110
+ return;
111
+ }
112
+
113
+ $this->upsertContact($this->convertToContactModel($contact));
114
+ } catch ( Exception $exception ) {
115
+ RaygunManager::get_instance()->exception_handler($exception);
116
+ }
117
+ }
118
+
119
+ public function registerHooks() {
120
+ add_action('grunion_after_message_sent', array( $this, 'ceHandleJetpackFormSubmission' ), 10, 7);
121
+ }
122
+
123
+ public function unregisterHooks() {
124
+ remove_action('grunion_after_message_sent', array( $this, 'ceHandleJetpackFormSubmission' ));
125
+ }
126
+
127
+ /**
128
+ * Get all the contacts.
129
+ *
130
+ * @param int $limit The limit of contacts to be returned.
131
+ *
132
+ * @return array|null
133
+ */
134
+ public function get_contacts( $limit = null ) {
135
+ if ( ! is_int($limit) || $limit <= 0 ) {
136
+ $limit = null;
137
+ }
138
+
139
+ // Relies on plugin => Jetpack or Jetpack beta.
140
+ if ( in_array('jetpack/jetpack.php', apply_filters('active_plugins', get_option('active_plugins')), true)
141
+ || in_array('jetpack-beta-master/jetpack-beta.php', apply_filters('active_plugins', get_option('active_plugins')), true)
142
+ ) {
143
+ $authorRegex = '/(?:^AUTHOR: )(.*)/mi';
144
+ $authorMailRegex = '/(?:^AUTHOR EMAIL: )(.*)/mi';
145
+ $additionalFieldsRegex = '/(?:^\s{4})\[\d_(.*)\](?:.*;\s)(.*)/mi';
146
+
147
+ $consentRegex = '/(?:\[email_marketing_consent] =&gt; )(.*)/mi';
148
+ $contactsArray = array();
149
+
150
+ // Get all posts with type->feedback (i think these are all the contact forms submitted).
151
+ $feedbackResults = get_posts(array( 'post_type' => 'feedback' ));
152
+
153
+ // Loop through the feedbacks and get each blocks innerHTML.
154
+ foreach ( $feedbackResults as $feedback ) {
155
+ foreach ( parse_blocks($feedback->post_content) as $block ) {
156
+ $feedbackHtml = $block['innerHTML'];
157
+
158
+ // Extract name, email and consent from submission.
159
+ $author = '';
160
+ preg_match($authorRegex, $feedbackHtml, $authorMatches);
161
+ if ( count($authorMatches) > 1 ) {
162
+ $author = $authorMatches[1];
163
+ }
164
+
165
+ $authorEmail = '';
166
+ preg_match($authorMailRegex, $feedbackHtml, $authorEmailMatches);
167
+ if ( count($authorEmailMatches) > 1 ) {
168
+ $authorEmail = $authorEmailMatches[1];
169
+ }
170
+
171
+ $consentValue = false;
172
+ preg_match($consentRegex, $feedbackHtml, $consentMatches);
173
+ if ( count($consentMatches) > 1 ) {
174
+ $consentValue = $consentMatches[1];
175
+ }
176
+
177
+ $contact = new stdClass();
178
+ $contact->email = filter_var($authorEmail, FILTER_VALIDATE_EMAIL);
179
+ if ( empty($contact->email) ) {
180
+ continue;
181
+ }
182
+
183
+ // If the author field also contains an email, ignore it (this happens when no name is provided).
184
+ if ( ! filter_var($author, FILTER_VALIDATE_EMAIL) ) {
185
+ $contact->name = $author;
186
+ } else {
187
+ $contact->name = null;
188
+ }
189
+
190
+ $contact->opt_in = boolval($consentValue);
191
+
192
+ preg_match_all($additionalFieldsRegex, $feedbackHtml, $additionalFieldMatches);
193
+ if ( count($additionalFieldMatches) > 1 ) {
194
+ foreach ( $additionalFieldMatches[1] as $index => $label ) {
195
+ $fieldValue = $additionalFieldMatches[2][ $index ];
196
+ if ( in_array(strtolower($label), $this->phoneFields, true) ) {
197
+ $contact->phone = $fieldValue;
198
+ } elseif ( in_array(strtolower($label), $this->birthdayFields, true) ) {
199
+ $contact->birthday = $fieldValue;
200
+ }
201
+ }
202
+ }
203
+
204
+ // Convert to contactModel and push to the array.
205
+ $contactModel = null;
206
+ try {
207
+ $contactModel = $this->convertToContactModel($contact);
208
+ } catch ( Exception $exception ) {
209
+ RaygunManager::get_instance()->exception_handler($exception);
210
+ continue;
211
+ }
212
+
213
+ array_push($contactsArray, $contactModel);
214
+
215
+ if ( isset($limit) && count($contactsArray) >= $limit ) {
216
+ break;
217
+ }
218
+ }
219
+
220
+ if ( isset($limit) && count($contactsArray) >= $limit ) {
221
+ break;
222
+ }
223
+ }
224
+
225
+ // Upsert the contacts.
226
+ if ( ! empty($contactsArray) ) {
227
+ return $contactsArray;
228
+ }
229
+ }
230
+
231
+ return null;
232
+ }
233
+
234
+ /**
235
+ * Returns the Phone Number.
236
+ *
237
+ * @param array $all_values The array of all the values.
238
+ *
239
+ * @return void|string
240
+ */
241
+ public function GetPhoneNumber( $all_values ) {
242
+ $target_substring = 'phone';
243
+ // Loop through every field of the form.
244
+ foreach ( $all_values as $key => $value ) {
245
+ // If the name of the key contains the substring "phone" then the value will be the phone number.
246
+ if ( mb_strpos(strtolower($key), $target_substring) !== false ) {
247
+ return $value;
248
+ }
249
+ }
250
+ }
251
  }
src/Modules/Contacts/Handlers/NewsLetterContactFormPluginHandler.php CHANGED
@@ -7,119 +7,132 @@ define('CE4WP_NL_EVENTTYPE', 'WordPress - NewsLetter');
7
  use CreativeMail\Managers\RaygunManager;
8
  use CreativeMail\Modules\Contacts\Models\ContactModel;
9
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
10
-
11
- class NewsLetterContactFormPluginHandler extends BaseContactFormPluginHandler
12
- {
13
- public function convertToContactModel($user)
14
- {
15
- $contactModel = new ContactModel();
16
-
17
- $contactModel->setEventType(CE4WP_NL_EVENTTYPE);
18
- $contactModel->setOptIn(true);
19
- $contactModel->setOptActionBy(OptActionBy::Visitor);
20
-
21
- $email = $user->email;
22
- if (!empty($email)) {
23
- $contactModel->setEmail($email);
24
- }
25
-
26
- $name = $user->name;
27
- if (!empty($name)) {
28
- $contactModel->setFirstName($name);
29
- }
30
-
31
- $surname = $user->surname;
32
- if (!empty($surname)) {
33
- $contactModel->setLastName($surname);
34
- }
35
-
36
- return $contactModel;
37
- }
38
-
39
- public function ceHandleContactNewsletterSubmit($user)
40
- {
41
- try {
42
- $this->upsertContact($this->convertToContactModel($user));
43
- }
44
- catch (\Exception $exception) {
45
- RaygunManager::get_instance()->exception_handler($exception);
46
- }
47
- }
48
-
49
- public function registerHooks()
50
- {
51
- add_action('newsletter_user_confirmed', array($this, 'ceHandleContactNewsletterSubmit'));
52
- }
53
-
54
- public function unregisterHooks()
55
- {
56
- remove_action('newsletter_user_confirmed', array($this, 'ceHandleContactNewsletterSubmit'));
57
- }
58
-
59
- public function get_contacts($limit = null)
60
- {
61
- if (!is_int($limit) || $limit <= 0) {
62
- $limit = null;
63
- }
64
-
65
- global $wpdb;
66
-
67
- $query = 'select * from wp_newsletter order by id desc';
68
-
69
- if ($limit != null) {
70
- $query .= " LIMIT %d";
71
- $query = $wpdb->prepare($query, $limit);
72
- } else {
73
- $query = $wpdb->prepare($query);
74
- }
75
-
76
- $result = $wpdb->get_results($query);
77
-
78
- $backfillArray = array();
79
-
80
- if (isset($result) && !empty($result)) {
81
- foreach ($result as $contact) {
82
- $contactModel = new ContactModel();
83
- try {
84
- $contactModel->setEventType(CE4WP_NL_EVENTTYPE);
85
- $contactModel->setOptIn($contact->status !== "U");
86
- $contactModel->setOptOut($contact->status === "U");
87
- $contactModel->setOptActionBy(OptActionBy::Visitor);
88
-
89
- $email = $contact->email;
90
- if (!empty($email)) {
91
- $contactModel->setEmail($email);
92
- }
93
-
94
- $name = $contact->name;
95
- if (!empty($name)) {
96
- $contactModel->setFirstName($name);
97
- }
98
-
99
- $surname = $contact->surname;
100
- if (!empty($surname)) {
101
- $contactModel->setLastName($surname);
102
- }
103
- } catch (\Exception $exception) {
104
- RaygunManager::get_instance()->exception_handler($exception);
105
- continue;
106
- }
107
-
108
- if (!empty($contactModel->getEmail())) {
109
- array_push($backfillArray, $contactModel);
110
- }
111
- }
112
- }
113
-
114
- if (!empty($backfillArray)) {
115
- return $backfillArray;
116
- }
117
-
118
- return null;
119
- }
120
-
121
- function __construct()
122
- {
123
- parent::__construct();
124
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  }
7
  use CreativeMail\Managers\RaygunManager;
8
  use CreativeMail\Modules\Contacts\Models\ContactModel;
9
  use CreativeMail\Modules\Contacts\Models\OptActionBy;
10
+ use Exception;
11
+
12
+ final class NewsLetterContactFormPluginHandler extends BaseContactFormPluginHandler {
13
+
14
+ public function __construct() {
15
+ parent::__construct();
16
+ }
17
+
18
+ /**
19
+ * Converts to contact model.
20
+ *
21
+ * @param object $user The user.
22
+ *
23
+ * @return ContactModel
24
+ * @throws Exception
25
+ */
26
+ public function convertToContactModel( $user ) {
27
+ $contactModel = new ContactModel();
28
+ $contactModel->setEventType(CE4WP_NL_EVENTTYPE);
29
+ $contactModel->setOptIn(true);
30
+ $contactModel->setOptActionBy(OptActionBy::VISITOR);
31
+
32
+ $email = $user->email;
33
+
34
+ if ( ! empty($email) ) {
35
+ $contactModel->setEmail($email);
36
+ }
37
+
38
+ $name = $user->name;
39
+
40
+ if ( ! empty($name) ) {
41
+ $contactModel->setFirstName($name);
42
+ }
43
+
44
+ $surname = $user->surname;
45
+
46
+ if ( ! empty($surname) ) {
47
+ $contactModel->setLastName($surname);
48
+ }
49
+
50
+ return $contactModel;
51
+ }
52
+
53
+ /**
54
+ * Handles the contact form submission.
55
+ *
56
+ * @param object $user The user.
57
+ *
58
+ * @return void
59
+ */
60
+ public function ceHandleContactNewsletterSubmit( $user ) {
61
+ try {
62
+ $this->upsertContact($this->convertToContactModel($user));
63
+ } catch ( Exception $exception ) {
64
+ RaygunManager::get_instance()->exception_handler($exception);
65
+ }
66
+ }
67
+
68
+ public function registerHooks() {
69
+ add_action('newsletter_user_confirmed', array( $this, 'ceHandleContactNewsletterSubmit' ));
70
+ }
71
+
72
+ public function unregisterHooks() {
73
+ remove_action('newsletter_user_confirmed', array( $this, 'ceHandleContactNewsletterSubmit' ));
74
+ }
75
+
76
+ /**
77
+ * Get all the contacts.
78
+ *
79
+ * @param ?int $limit The limit of contacts to be sent.
80
+ *
81
+ * @return array|null
82
+ */
83
+ public function get_contacts( $limit = null ) {
84
+ global $wpdb;
85
+
86
+ $backfillArray = array();
87
+
88
+ if ( ! is_int($limit) || $limit <= 0 ) {
89
+ $limit = null;
90
+ }
91
+
92
+ if ( null != $limit ) {
93
+ $result = $wpdb->get_results($wpdb->prepare('select * from wp_newsletter order by id desc LIMIT %d', $limit));
94
+ } else {
95
+ $result = $wpdb->get_results($wpdb->prepare('select * from wp_newsletter order by id desc'));
96
+ }
97
+
98
+ if ( isset($result) && ! empty($result) ) {
99
+ foreach ( $result as $contact ) {
100
+ $contactModel = new ContactModel();
101
+ try {
102
+ $contactModel->setEventType(CE4WP_NL_EVENTTYPE);
103
+ $contactModel->setOptIn( 'U' !== $contact->status );
104
+ $contactModel->setOptOut( 'U' === $contact->status );
105
+ $contactModel->setOptActionBy(OptActionBy::VISITOR);
106
+
107
+ $email = $contact->email;
108
+ if ( ! empty($email) ) {
109
+ $contactModel->setEmail($email);
110
+ }
111
+
112
+ $name = $contact->name;
113
+ if ( ! empty($name) ) {
114
+ $contactModel->setFirstName($name);
115
+ }
116
+
117
+ $surname = $contact->surname;
118
+ if ( ! empty($surname) ) {
119
+ $contactModel->setLastName($surname);
120
+ }
121
+ } catch ( Exception $exception ) {
122
+ RaygunManager::get_instance()->exception_handler($exception);
123
+ continue;
124
+ }
125
+
126
+ if ( ! empty($contactModel->getEmail()) ) {
127
+ array_push($backfillArray, $contactModel);
128
+ }
129
+ }
130
+ }
131
+
132
+ if ( ! empty($backfillArray) ) {
133
+ return $backfillArray;
134
+ }
135
+
136
+ return null;
137
+ }
138
  }
src/Modules/Contacts/Handlers/NinjaFormsPluginHandler.php CHANGED
@@ -10,249 +10,280 @@ use CreativeMail\Modules\Contacts\Models\OptActionBy;
10
  use Exception;
11
  use stdClass;
12
 
13
- class NinjaFormsPluginHandler extends BaseContactFormPluginHandler
14
- {
15
- function __construct()
16
- {
17
- parent::__construct();
18
- }
19
 
20
- private function getNameFromForm($fields)
21
- {
22
- $name = null;
23
- foreach ($fields as $field) {
24
- if ($field["key"] == "name" || $field["type"] == "name" || strpos($field["key"], "full_name") !== false) {
25
- return $field["value"];
26
- }
27
- if ($field["type"] == "firstname" || strpos($field["key"], "first_name") !== false) {
28
- $name = $field["value"];
29
- continue;
30
- }
31
- if ($field["type"] == "lastname" || strpos($field["key"], "last_name") !== false) {
32
- return implode(' ', array($name, $field["value"]));
33
- }
34
- }
35
- return !empty($name) ? $name : null;
36
- }
37
 
38
- private function FindFormValues($contact, $fields)
39
- {
40
- foreach ($fields as $field) {
41
- if (in_array($field["key"], $this->emailFields) || in_array($field["type"], $this->emailFields)) {
42
- $contact->email = $field["value"];
43
- } elseif (in_array($field["key"], $this->phoneFields) || in_array($field["type"], $this->phoneFields)) {
44
- $contact->phone = $field["value"];
45
- } elseif (in_array($field["key"], $this->birthdayFields) || in_array(strtolower($field["label"]), $this->birthdayFields)) {
46
- $contact->birthday = $field["value"];
47
- }
48
- }
49
- }
50
 
51
- public function convertToContactModel($contact)
52
- {
53
- $contactModel = new ContactModel();
 
 
 
 
 
 
 
 
 
54
 
55
- $contactModel->setEventType(CE4WP_NF_EVENTTYPE);
56
- //optin true on sync, false on form submission
57
- $contactModel->setOptIn($contact->opt_in);
58
- $contactModel->setOptOut(false);
59
- $contactModel->setOptActionBy(OptActionBy::Visitor);
60
 
61
- if (isset($contact->optinByOwner)) {
62
- $contactModel->setOptActionBy(OptActionBy::Owner);
63
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
- $email = $contact->email;
66
- if (!empty($email)) {
67
- $contactModel->setEmail($email);
68
- }
 
 
 
 
 
 
 
69
 
70
- $name = !empty($contact->name) ? $contact->name : null;
71
- $firstName = null;
72
- $lastName = null;
73
- if (!empty($name)) {
74
- $values = explode(' ', $contact->name);
75
- $firstName = array_shift($values);
76
- $lastName = implode(' ', $values);
77
- } else {
78
- $firstName = isset($contact->firstName) ? $contact->firstName : null;
79
- $lastName = isset($contact->lastName) ? $contact->lastName : null;
80
- }
81
 
82
- if (!empty($firstName)) {
83
- $contactModel->setFirstName($firstName);
84
- }
85
- if (!empty($lastName)) {
86
- $contactModel->setLastName($lastName);
87
- }
88
- if (!empty($contact->phone)) {
89
- $contactModel->setPhone($contact->phone);
90
- }
91
- if (!empty($contact->birthday)) {
92
- $contactModel->setBirthday($contact->birthday);
93
- }
94
 
95
- return $contactModel;
96
- }
 
 
97
 
98
- public function attemptAdditionalNameExtraction($contact, $field_key, $field_values)
99
- {
100
- //Attempt additional checking for name in an attempt to get custom form fields for names
101
- $name = null;
102
- if (!isset($field_values[$field_key])) {
103
- return null;
104
- }
105
- if (strpos($field_key, "full_name") !== false || isset($field_values["name"])) {
106
- $contact->name = $field_values[$field_key];
107
- return;
108
- }
109
- if (strpos($field_key, "first_name") !== false || isset($field_values["firstname"])) {
110
- $contact->firstName = $field_values[$field_key];
111
- return;
112
- }
113
- if (strpos($field_key, "last_name") !== false || isset($field_values["lastname"])) {
114
- $contact->lastName = $field_values[$field_key];
115
- return;
116
- }
117
- }
118
 
119
- public function ceHandleNinjaFormSubmission($form_data)
120
- {
121
- try {
122
- $ninjaContact = new stdClass();
123
- $this->FindFormValues($ninjaContact, $form_data["fields_by_key"]);
124
- if (empty($ninjaContact->email)) {
125
- return;
126
- };
127
- $ninjaContact->name = $this->getNameFromForm($form_data["fields_by_key"]);
128
- $ninjaContact->opt_in = false;
129
- $this->upsertContact($this->convertToContactModel($ninjaContact));
130
- } catch (Exception $exception) {
131
- RaygunManager::get_instance()->exception_handler($exception);
132
- }
133
- }
134
 
135
- public function registerHooks()
136
- {
137
- add_action('ninja_forms_after_submission', array($this, 'ceHandleNinjaFormSubmission'), 10, 1);
138
- }
139
 
140
- public function unregisterHooks()
141
- {
142
- remove_action('ninja_forms_after_submission', array($this, 'ceHandleNinjaFormSubmission'));
143
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
 
145
- public function get_contacts($limit = null)
146
- {
147
- $fields = null;
148
- $submissions = null;
 
 
 
 
 
 
 
149
 
150
- if (!is_int($limit) || $limit <= 0) {
151
- $limit = null;
152
- }
153
- try {
154
- // Relies on plugin => NinjaForms.
155
- if (in_array('ninja-forms/ninja-forms.php', apply_filters('active_plugins', get_option('active_plugins')))) {
156
- $contactsArray = array();
157
- // Get an array of Form Models for All Forms.
158
- $forms = Ninja_Forms()->form()->get_forms();
159
- if ( is_array($forms) ) {
160
- foreach ($forms as $form) {
161
- $formId = $form->get_id();
162
- // Get all form fields and submissions for the form.
163
- if (!empty($formId)) {
164
- $fields = Ninja_Forms()->form($formId)->get_fields();
165
- $submissions = Ninja_Forms()->form($formId)->get_subs();
166
- }
167
- if (!empty($submissions)) {
168
- foreach ($submissions as $submission) {
169
- $contact = new stdClass();
170
- // Get all values for a submission.
171
- $field_values = $submission->get_field_values();
172
 
173
- if (!empty($fields)) {
174
- foreach ($fields as $field) {
175
- // Get field settings, so we can map the values with its field type.
176
- $field_settings = $field->get_settings();
177
- $field_key = $field_settings["key"];
178
- $field_type = $field_settings["type"];
179
- $field_value = $field_values[$field_key] ?? null; // This prevents undefined index on altered forms.
180
- switch ($field_type) {
181
- case 'email';
182
- $email = $field_value;
183
- if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
184
- $contact->email = $email;
185
- }
186
- break;
187
- case 'phone';
188
- $contact->phone = $field_value;
189
- break;
190
- case 'date';
191
- if (in_array(strtolower($field_settings['label']), $this->birthdayFields)) {
192
- $contact->birthday = $field_value;
193
- }
194
- break;
195
- case 'name';
196
- case 'full_name';
197
- $contact->name = $field_value;
198
- break;
199
- case 'firstname';
200
- case 'first_name';
201
- $contact->firstName = $field_value;
202
- break;
203
- case 'lastname';
204
- case 'last_name';
205
- $contact->lastName = $field_value;
206
- break;
207
- case 'textbox';
208
- case 'text';
209
- if (empty($contact->name) && (empty($contact->firstName) || empty($contact->lastName))) {
210
- $this->attemptAdditionalNameExtraction($contact, $field_key, $field_values);
211
- }
212
- break;
213
- default;
214
- break;
215
- }
216
- }
217
- }
218
 
219
- if (!empty($contact->email) && $contact->email != null) {
220
- // Set optin by owner on db sync.
221
- $contact->optinByOwner = true;
222
- $contact->opt_in = true;
 
223
 
224
- // Convert to contactModel and push to the array.
225
- $contactModel = null;
226
- try {
227
- $contactModel = $this->convertToContactModel($contact);
228
- if (!empty($contactModel->getEmail())) {
229
- array_push($contactsArray, $contactModel);
230
- }
231
- } catch (Exception $exception) {
232
- RaygunManager::get_instance()->exception_handler($exception);
233
- continue;
234
- }
235
- if (isset($limit) && count($contactsArray) >= $limit) {
236
- break;
237
- }
238
- }
239
- }
240
- }
241
- if (isset($limit) && count($contactsArray) >= $limit) {
242
- break;
243
- }
244
- }
245
- }
246
 
247
- // Upsert the contacts.
248
- if (!empty($contactsArray)) {
249
- return $contactsArray;
250
- }
251
- }
252
- } catch (Exception $exception) {
253
- RaygunManager::get_instance()->exception_handler($exception);
254
- }
255
 
256
- return null;
257
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  }
10
  use Exception;
11
  use stdClass;
12
 
13
+ final class NinjaFormsPluginHandler extends BaseContactFormPluginHandler {
 
 
 
 
 
14
 
15
+ public function __construct() {
16
+ parent::__construct();
17
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
+ /**
20
+ * Get the name from the form.
21
+ *
22
+ * @param array $fields The fields.
23
+ *
24
+ * @return string|null
25
+ */
26
+ private function getNameFromForm( $fields ): ?string {
27
+ $name = null;
 
 
 
28
 
29
+ foreach ( $fields as $field ) {
30
+ if ( 'name' == $field['key'] || 'name' == $field['type'] || strpos($field['key'], 'full_name') !== false ) {
31
+ return $field['value'];
32
+ }
33
+ if ( 'firstname' == $field['type'] || strpos($field['key'], 'first_name') !== false ) {
34
+ $name = $field['value'];
35
+ continue;
36
+ }
37
+ if ( 'lastname' == $field['type'] || strpos($field['key'], 'last_name') !== false ) {
38
+ return implode(' ', array( $name, $field['value'] ));
39
+ }
40
+ }
41
 
42
+ return ! empty($name) ? $name : null;
43
+ }
 
 
 
44
 
45
+ /**
46
+ * Finds the Form Values
47
+ *
48
+ * @param object $contact The contact.
49
+ * @param array $fields The fields.
50
+ *
51
+ * @return void
52
+ */
53
+ private function FindFormValues( $contact, $fields ): void {
54
+ foreach ( $fields as $field ) {
55
+ if ( in_array($field['key'], $this->emailFields, true) || in_array($field['type'], $this->emailFields, true) ) {
56
+ $contact->email = $field['value'];
57
+ } elseif ( in_array($field['key'], $this->phoneFields, true) || in_array($field['type'], $this->phoneFields, true) ) {
58
+ $contact->phone = $field['value'];
59
+ } elseif ( in_array($field['key'], $this->birthdayFields, true) || in_array(strtolower($field['label']), $this->birthdayFields, true) ) {
60
+ $contact->birthday = $field['value'];
61
+ }
62
+ }
63
+ }
64
 
65
+ /**
66
+ * Convert to Contact Model.
67
+ *
68
+ * @param object $contact The contact.
69
+ *
70
+ * @return ContactModel The contact model.
71
+ *
72
+ * @throws Exception The exception.
73
+ */
74
+ public function convertToContactModel( $contact ) {
75
+ $contactModel = new ContactModel();
76
 
77
+ $contactModel->setEventType(CE4WP_NF_EVENTTYPE);
78
+ // OptIn true on sync, false on form submission.
79
+ $contactModel->setOptIn($contact->opt_in);
80
+ $contactModel->setOptOut(false);
81
+ $contactModel->setOptActionBy(OptActionBy::VISITOR);
 
 
 
 
 
 
82
 
83
+ if ( isset($contact->optinByOwner) ) {
84
+ $contactModel->setOptActionBy(OptActionBy::OWNER);
85
+ }
 
 
 
 
 
 
 
 
 
86
 
87
+ $email = $contact->email;
88
+ if ( ! empty($email) ) {
89
+ $contactModel->setEmail($email);
90
+ }
91
 
92
+ $name = ! empty($contact->name) ? $contact->name : null;
93
+ $firstName = null;
94
+ $lastName = null;
95
+ if ( ! empty($name) ) {
96
+ $values = explode(' ', $contact->name);
97
+ $firstName = array_shift($values);
98
+ $lastName = implode(' ', $values);
99
+ } else {
100
+ $firstName = isset($contact->firstName) ? $contact->firstName : null;
101
+ $lastName = isset($contact->lastName) ? $contact->lastName : null;
102
+ }
 
 
 
 
 
 
 
 
 
103
 
104
+ if ( ! empty($firstName) ) {
105
+ $contactModel->setFirstName($firstName);
106
+ }
107
+ if ( ! empty($lastName) ) {
108
+ $contactModel->setLastName($lastName);
109
+ }
110
+ if ( ! empty($contact->phone) ) {
111
+ $contactModel->setPhone($contact->phone);
112
+ }
113
+ if ( ! empty($contact->birthday) ) {
114
+ $contactModel->setBirthday($contact->birthday);
115
+ }
 
 
 
116
 
117
+ return $contactModel;
118
+ }
 
 
119
 
120
+ /**
121
+ * Attempt extraction of additional name.
122
+ *
123
+ * @param ?object $contact The contact.
124
+ * @param mixed $field_key The field key.
125
+ * @param ?array $field_values The field values.
126
+ *
127
+ * @return void|null
128
+ */
129
+ public function attemptAdditionalNameExtraction( $contact, $field_key, $field_values ) {
130
+ // Attempt additional checking for name in an attempt to get custom form fields for names.
131
+ if ( ! isset($field_values[ $field_key ]) ) {
132
+ return null;
133
+ }
134
+ if ( strpos($field_key, 'full_name') !== false || isset($field_values['name']) ) {
135
+ $contact->name = $field_values[ $field_key ];
136
+ return;
137
+ }
138
+ if ( strpos($field_key, 'first_name') !== false || isset($field_values['firstname']) ) {
139
+ $contact->firstName = $field_values[ $field_key ];
140
+ return;
141
+ }
142
+ if ( strpos($field_key, 'last_name') !== false || isset($field_values['lastname']) ) {
143
+ $contact->lastName = $field_values[ $field_key ];
144
+ }
145
+ }
146
 
147
+ /**
148
+ * Handle the NinjaForm submission.
149
+ *
150
+ * @param ?array $form_data The form data.
151
+ *
152
+ * @return void
153
+ */
154
+ public function ceHandleNinjaFormSubmission( $form_data ) {
155
+ try {
156
+ $ninjaContact = new stdClass();
157
+ $this->FindFormValues($ninjaContact, $form_data['fields_by_key']);
158
 
159
+ if ( empty($ninjaContact->email) ) {
160
+ return;
161
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
 
163
+ $ninjaContact->name = $this->getNameFromForm($form_data['fields_by_key']);
164
+ $ninjaContact->opt_in = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
 
166
+ $this->upsertContact($this->convertToContactModel($ninjaContact));
167
+ } catch ( Exception $exception ) {
168
+ RaygunManager::get_instance()->exception_handler($exception);
169
+ }
170
+ }
171
 
172
+ public function registerHooks() {
173
+ add_action('ninja_forms_after_submission', array( $this, 'ceHandleNinjaFormSubmission' ), 10, 1);
174
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
 
176
+ public function unregisterHooks() {
177
+ remove_action('ninja_forms_after_submission', array( $this, 'ceHandleNinjaFormSubmission' ));
178
+ }
 
 
 
 
 
179
 
180
+ public function get_contacts( $limit = null ) {
181
+ $fields = null;
182
+ $submissions = null;
183
+
184
+ if ( ! is_int($limit) || $limit <= 0 ) {
185
+ $limit = null;
186
+ }
187
+ try {
188
+ // Relies on plugin => NinjaForms.
189
+ if ( in_array('ninja-forms/ninja-forms.php', apply_filters('active_plugins', get_option('active_plugins')), true) ) {
190
+ $contactsArray = array();
191
+ // Get an array of Form Models for All Forms.
192
+ $forms = Ninja_Forms()->form()->get_forms();
193
+ if ( is_array($forms) ) {
194
+ foreach ( $forms as $form ) {
195
+ $formId = $form->get_id();
196
+ // Get all form fields and submissions for the form.
197
+ if ( ! empty($formId) ) {
198
+ $fields = Ninja_Forms()->form($formId)->get_fields();
199
+ $submissions = Ninja_Forms()->form($formId)->get_subs();
200
+ }
201
+ if ( ! empty($submissions) ) {
202
+ foreach ( $submissions as $submission ) {
203
+ $contact = new stdClass();
204
+ // Get all values for a submission.
205
+ $field_values = $submission->get_field_values();
206
+
207
+ if ( ! empty($fields) ) {
208
+ foreach ( $fields as $field ) {
209
+ // Get field settings, so we can map the values with its field type.
210
+ $field_settings = $field->get_settings();
211
+ $field_key = $field_settings['key'];
212
+ $field_type = $field_settings['type'];
213
+ $field_value = $field_values[ $field_key ] ?? null; // This prevents undefined index on altered forms.
214
+ switch ( $field_type ) {
215
+ case 'email':
216
+ $email = $field_value;
217
+ if ( filter_var($email, FILTER_VALIDATE_EMAIL) ) {
218
+ $contact->email = $email;
219
+ }
220
+ break;
221
+ case 'phone':
222
+ $contact->phone = $field_value;
223
+ break;
224
+ case 'date':
225
+ if ( in_array(strtolower($field_settings['label']), $this->birthdayFields, true) ) {
226
+ $contact->birthday = $field_value;
227
+ }
228
+ break;
229
+ case 'name':
230
+ case 'full_name':
231
+ $contact->name = $field_value;
232
+ break;
233
+ case 'firstname':
234
+ case 'first_name':
235
+ $contact->firstName = $field_value;
236
+ break;
237
+ case 'lastname':
238
+ case 'last_name':
239
+ $contact->lastName = $field_value;
240
+ break;
241
+ case 'textbox':
242
+ case 'text':
243
+ if ( empty($contact->name) && ( empty($contact->firstName) || empty($contact->lastName) ) ) {
244
+ $this->attemptAdditionalNameExtraction($contact, $field_key, $field_values);
245
+ }
246
+ break;
247
+ default:
248
+ break;
249
+ }
250
+ }
251
+ }
252
+
253
+ if ( ! empty($contact->email) && null != $contact->email ) {
254
+ // Set optin by owner on db sync.
255
+ $contact->optinByOwner = true;
256
+ $contact->opt_in = true;
257
+ // Convert to contactModel and push to the array.
258
+ $contactModel = null;
259
+ try {
260
+ $contactModel = $this->convertToContactModel($contact);
261
+ if ( ! empty($contactModel->getEmail()) ) {
262
+ array_push($contactsArray, $contactModel);
263
+ }
264
+ } catch ( Exception $exception ) {
265
+ RaygunManager::get_instance()->exception_handler($exception);
266
+ continue;
267
+ }
268
+ if ( isset($limit) && count($contactsArray) >= $limit ) {
269
+ break;
270
+ }
271
+ }
272
+ }
273
+ }
274
+ if ( isset($limit) && count($contactsArray) >= $limit ) {
275
+ break;
276
+ }
277
+ }
278
+ }
279
+ // Upsert the contacts.
280
+ if ( ! empty($contactsArray) ) {
281
+ return $contactsArray;
282
+ }
283
+ }
284
+ } catch ( Exception $exception ) {
285
+ RaygunManager::get_instance()->exception_handler($exception);
286
+ }
287
+ return null;
288
+ }
289
  }
src/Modules/Contacts/Handlers/WooCommercePluginHandler.php CHANGED
@@ -1,10 +1,4 @@
1
  <?php
2
- /**
3
- * Created by PhpStorm.
4
- * User: Martijn
5
- * Date: 2020-02-10
6
- * Time: 13:42
7
- */
8
 
9
  namespace CreativeMail\Modules\Contacts\Handlers;
10
 
@@ -14,186 +8,247 @@ use CreativeMail\Managers\RaygunManager;
14
  use CreativeMail\Modules\Contacts\Models\ContactAddressModel;
15
  use CreativeMail\Modules\Contacts\Models\ContactModel;
16
  use Exception;
17
-
18
- class WooCommercePluginHandler extends BaseContactFormPluginHandler
19
- {
20
- const CHECKOUT_CONSENT_CHECKBOX_ID = 'ce4wp_checkout_consent_checkbox';
21
- const CHECKOUT_CONSENT_CHECKBOX_VALUE = 'ce4wp_checkout_consent';
22
- const CHECKOUT_CONSENT_CHECKBOX_VALUE_OLD = 'ce_checkout_consent';
23
- var $isSync = false;
24
-
25
- public function convertToContactModel($orderId)
26
- {
27
- $all_orders = null;
28
- $contactModel = new ContactModel();
29
- $products_detail = get_post_meta($orderId);
30
- $order = wc_get_order($orderId);
31
-
32
- if (is_object($order) && is_a($order, 'WC_Order')) {
33
- $all_orders = wc_get_orders(array('email' => $order->get_billing_email()));
34
- }
35
-
36
- $number_of_orders = count(is_array($all_orders) ? $all_orders : array());
37
-
38
- if (isset($products_detail)) {
39
- if (!empty($products_detail["_billing_email"]) && isset($products_detail["_billing_email"][0]) && !empty($products_detail["_billing_email"][0])) {
40
- $contactModel->setEmail($products_detail["_billing_email"][0]);
41
- } else {
42
- return $contactModel;
43
- }
44
-
45
- if (!empty($products_detail["_billing_first_name"])) {
46
- $contactModel->setFirstName($products_detail["_billing_first_name"][0]);
47
- }
48
- if (!empty($products_detail["_billing_last_name"])) {
49
- $contactModel->setLastName($products_detail["_billing_last_name"][0]);
50
- }
51
-
52
- $contactAddress = $this->getContactAddressFromOrder($products_detail);
53
-
54
- if (!empty($contactAddress)) {
55
- $contactModel->setContactAddress($contactAddress);
56
- }
57
-
58
- if (!empty($contactModel->getEmail())) {
59
- $contactModel->setEventType(CE4WP_WC_EVENTTYPE);
60
- $contactModel->setOptActionBy(2);
61
- $contactModel->setOptIn($this->isSync);
62
- $contactModel->setOptOut(false);
63
- }
64
-
65
- if (!empty($products_detail["_billing_phone"])) {
66
- $contactModel->setPhone($products_detail["_billing_phone"][0]);
67
- }
68
-
69
- if (!empty($number_of_orders)) {
70
- $contactModel->setNumberOfOrders($number_of_orders);
71
- }
72
-
73
- $this->setConsentValues($contactModel, $products_detail);
74
- }
75
- return $contactModel;
76
- }
77
-
78
- function setConsentValues($contactModel, $products_detail){
79
- $checkbox_value = null;
80
-
81
- if (!empty($_POST[self::CHECKOUT_CONSENT_CHECKBOX_ID])) {
82
- $checkbox_value = esc_attr($_POST[self::CHECKOUT_CONSENT_CHECKBOX_ID]);
83
- } else if (!empty($products_detail[self::CHECKOUT_CONSENT_CHECKBOX_ID])) {
84
- $checkbox_value = $products_detail[self::CHECKOUT_CONSENT_CHECKBOX_ID];
85
- } else if (!empty($_POST[self::CHECKOUT_CONSENT_CHECKBOX_VALUE])) {
86
- $checkbox_value = esc_attr($_POST[self::CHECKOUT_CONSENT_CHECKBOX_VALUE]);
87
- } else if (!empty($products_detail[self::CHECKOUT_CONSENT_CHECKBOX_VALUE])) {
88
- $checkbox_value = $products_detail[self::CHECKOUT_CONSENT_CHECKBOX_VALUE][0]; //this value appears to be in array;
89
- } else if (!empty($products_detail[self::CHECKOUT_CONSENT_CHECKBOX_VALUE_OLD])) {
90
- $checkbox_value = $products_detail[self::CHECKOUT_CONSENT_CHECKBOX_VALUE_OLD][0]; //this value appears to be in array;
91
- }
92
-
93
- if (!is_null($checkbox_value)) {
94
- $contactModel->setOptActionBy(1);
95
- if ($checkbox_value == true){
96
- $contactModel->setOptIn(true);
97
- } elseif ($checkbox_value == false){
98
- $contactModel->setOptIn(false);
99
- }
100
- }
101
- }
102
-
103
- function getContactAddressFromOrder($products_detail)
104
- {
105
- $contactAddress = new ContactAddressModel();
106
-
107
- if (isset($products_detail)) {
108
- if (!empty($products_detail["_billing_address_1"])) {
109
- $contactAddress->setAddress($products_detail["_billing_address_1"][0]);
110
- }
111
- if (!empty($products_detail["_billing_address_2"])) {
112
- $contactAddress->setAddress2($products_detail["_billing_address_2"][0]);
113
- }
114
- if (!empty($products_detail["_billing_city"])) {
115
- $contactAddress->setCity($products_detail["_billing_city"][0]);
116
- }
117
- if (!empty($products_detail["_billing_country"])) {
118
- $contactAddress->setCountryCode($products_detail["_billing_country"][0]);
119
- }
120
- if (!empty($products_detail["_billing_postcode"])) {
121
- $contactAddress->setPostalCode($products_detail["_billing_postcode"][0]);
122
- }
123
- if (!empty($products_detail["_billing_state"])) {
124
- $contactAddress->setStateCode($products_detail["_billing_state"][0]);
125
- }
126
- }
127
- return $contactAddress;
128
- }
129
-
130
- public function ceHandlerWooCommerceNewOrder($order_id)
131
- {
132
- try {
133
- $order = wc_get_order($order_id);
134
- if (is_object($order) && is_a($order, 'WC_Order')) {
135
- $this->upsertContact($this->convertToContactModel($order->get_id()));
136
- }
137
- } catch (Exception $exception) {
138
- RaygunManager::get_instance()->exception_handler($exception);
139
- }
140
- }
141
-
142
- public function registerHooks()
143
- {
144
- add_action('woocommerce_checkout_order_created', array($this, 'ceHandlerWooCommerceNewOrder'), 10, 1);
145
- }
146
-
147
- public function unregisterHooks()
148
- {
149
- remove_action('woocommerce_checkout_order_created', array($this, 'ceHandlerWooCommerceOrder'));
150
- }
151
-
152
- public function get_contacts($limit = null)
153
- {
154
- if (!is_int($limit) || $limit <= 0) {
155
- $limit = null;
156
- }
157
-
158
- $backfillArray = array();
159
-
160
- $args = array(
161
- 'posts_per_page' => -1,
162
- 'post_type' => 'shop_order',
163
- 'post_status' => array_keys(wc_get_order_statuses())
164
- );
165
-
166
- if ($limit != null) {
167
- $args['posts_per_page'] = $limit;
168
- }
169
-
170
- $products_orders = get_posts($args);
171
-
172
- foreach ($products_orders as $products_order) {
173
-
174
- $contactModel = null;
175
- try {
176
- $this->isSync = true;
177
- $contactModel = $this->convertToContactModel($products_order->ID);
178
- } catch (Exception $exception) {
179
- // silent exception
180
- continue;
181
- }
182
-
183
- if (!empty($contactModel->getEmail())) {
184
- array_push($backfillArray, $contactModel);
185
- }
186
- }
187
-
188
- if (!empty($backfillArray)) {
189
- return $backfillArray;
190
- }
191
-
192
- return null;
193
- }
194
-
195
- function __construct()
196
- {
197
- parent::__construct();
198
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  }
1
  <?php
 
 
 
 
 
 
2
 
3
  namespace CreativeMail\Modules\Contacts\Handlers;
4
 
8
  use CreativeMail\Modules\Contacts\Models\ContactAddressModel;
9
  use CreativeMail\Modules\Contacts\Models\ContactModel;
10
  use Exception;
11
+ use WC_Order_Refund;
12
+
13
+ final class WooCommercePluginHandler extends BaseContactFormPluginHandler {
14
+
15
+ const CHECKOUT_CONSENT_CHECKBOX_ID = 'ce4wp_checkout_consent_checkbox';
16
+ const CHECKOUT_CONSENT_CHECKBOX_VALUE = 'ce4wp_checkout_consent';
17
+ const CHECKOUT_CONSENT_CHECKBOX_VALUE_OLD = 'ce_checkout_consent';
18
+
19
+ /**
20
+ * Checks if the plugin is sync.
21
+ *
22
+ * @var bool
23
+ */
24
+ public $isSync = false;
25
+
26
+ public function __construct() {
27
+ parent::__construct();
28
+ }
29
+
30
+ /**
31
+ * Converts to contact model.
32
+ *
33
+ * @param int $orderId The order id.
34
+ *
35
+ * @return ContactModel
36
+ *
37
+ * @throws Exception
38
+ */
39
+ public function convertToContactModel( $orderId ) {
40
+ $all_orders = null;
41
+ $contactModel = new ContactModel();
42
+ $products_detail = get_post_meta($orderId);
43
+ $order = wc_get_order($orderId);
44
+
45
+ if ( is_object($order) && is_a($order, 'WC_Order') ) {
46
+ $all_orders = wc_get_orders(array( 'email' => $order->get_billing_email() ));
47
+ }
48
+
49
+ $number_of_orders = count(is_array($all_orders) ? $all_orders : array());
50
+
51
+ if ( isset($products_detail) ) {
52
+ if ( ! empty($products_detail['_billing_email']) && isset($products_detail['_billing_email'][0]) && ! empty($products_detail['_billing_email'][0]) ) {
53
+ $contactModel->setEmail($products_detail['_billing_email'][0]);
54
+ } else {
55
+ return $contactModel;
56
+ }
57
+
58
+ if ( ! empty($products_detail['_billing_first_name']) ) {
59
+ $contactModel->setFirstName($products_detail['_billing_first_name'][0]);
60
+ }
61
+ if ( ! empty($products_detail['_billing_last_name']) ) {
62
+ $contactModel->setLastName($products_detail['_billing_last_name'][0]);
63
+ }
64
+
65
+ $contactAddress = $this->getContactAddressFromOrder($products_detail);
66
+
67
+ if ( ! empty($contactAddress) ) {
68
+ $contactModel->setContactAddress($contactAddress);
69
+ }
70
+
71
+ if ( ! empty($contactModel->getEmail()) ) {
72
+ $contactModel->setEventType(CE4WP_WC_EVENTTYPE);
73
+ $contactModel->setOptActionBy(2);
74
+ $contactModel->setOptIn($this->isSync);
75
+ $contactModel->setOptOut(false);
76
+ }
77
+
78
+ if ( ! empty($products_detail['_billing_phone']) ) {
79
+ $contactModel->setPhone($products_detail['_billing_phone'][0]);
80
+ }
81
+
82
+ if ( ! empty($number_of_orders) ) {
83
+ $contactModel->setNumberOfOrders($number_of_orders);
84
+ }
85
+
86
+ $this->setConsentValues($contactModel, $products_detail);
87
+ }
88
+ return $contactModel;
89
+ }
90
+
91
+ /**
92
+ * Sets the consent values.
93
+ *
94
+ * @param ContactModel $contactModel The contact model.
95
+ * @param array $products_detail The product details.
96
+ *
97
+ * @return void
98
+ */
99
+ public function setConsentValues( $contactModel, $products_detail ) {
100
+ $checkbox_value = null;
101
+
102
+ if ( isset( $_POST['woocommerce-process-checkout-nonce'] ) ) {
103
+ wp_verify_nonce(
104
+ sanitize_text_field( wp_unslash($_POST['woocommerce-process-checkout-nonce']) ),
105
+ 'woocommerce-process_checkout'
106
+ );
107
+ }
108
+
109
+ if ( ! empty($_POST[ self::CHECKOUT_CONSENT_CHECKBOX_ID ]) ) {
110
+ $checkbox_value = esc_attr(
111
+ sanitize_text_field ( wp_unslash($_POST[ self::CHECKOUT_CONSENT_CHECKBOX_ID ]) )
112
+ );
113
+ } elseif ( ! empty($products_detail[ self::CHECKOUT_CONSENT_CHECKBOX_ID ]) ) {
114
+ $checkbox_value = $products_detail[ self::CHECKOUT_CONSENT_CHECKBOX_ID ];
115
+ } elseif ( ! empty($_POST[ self::CHECKOUT_CONSENT_CHECKBOX_VALUE ]) ) {
116
+ $checkbox_value = esc_attr(
117
+ sanitize_text_field ( wp_unslash( $_POST[ self::CHECKOUT_CONSENT_CHECKBOX_VALUE ] ))
118
+ );
119
+ } elseif ( ! empty($products_detail[ self::CHECKOUT_CONSENT_CHECKBOX_VALUE ]) ) {
120
+ $checkbox_value = $products_detail[ self::CHECKOUT_CONSENT_CHECKBOX_VALUE ][0]; // This value appears to be in array.
121
+ } elseif ( ! empty($products_detail[ self::CHECKOUT_CONSENT_CHECKBOX_VALUE_OLD ]) ) {
122
+ $checkbox_value = $products_detail[ self::CHECKOUT_CONSENT_CHECKBOX_VALUE_OLD ][0]; // This value appears to be in array.
123
+ }
124
+
125
+ if ( ! is_null($checkbox_value) ) {
126
+ $contactModel->setOptActionBy(1);
127
+ if ( $checkbox_value ) {
128
+ $contactModel->setOptIn(true);
129
+ } elseif ( ! $checkbox_value ) {
130
+ $contactModel->setOptIn(false);
131
+ }
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Gets the contact address from order.
137
+ *
138
+ * @param array<string,mixed> $products_detail The product details.
139
+ *
140
+ * @return ContactAddressModel
141
+ */
142
+ public function getContactAddressFromOrder( array $products_detail ): ContactAddressModel {
143
+ $contactAddress = new ContactAddressModel();
144
+
145
+ if ( isset($products_detail) ) {
146
+ if ( ! empty($products_detail['_billing_address_1']) ) {
147
+ $contactAddress->setAddress($products_detail['_billing_address_1'][0]);
148
+ }
149
+ if ( ! empty($products_detail['_billing_address_2']) ) {
150
+ $contactAddress->setAddress2($products_detail['_billing_address_2'][0]);
151
+ }
152
+ if ( ! empty($products_detail['_billing_city']) ) {
153
+ $contactAddress->setCity($products_detail['_billing_city'][0]);
154
+ }
155
+ if ( ! empty($products_detail['_billing_country']) ) {
156
+ $contactAddress->setCountryCode($products_detail['_billing_country'][0]);
157
+ }
158
+ if ( ! empty($products_detail['_billing_postcode']) ) {
159
+ $contactAddress->setPostalCode($products_detail['_billing_postcode'][0]);
160
+ }
161
+ if ( ! empty($products_detail['_billing_state']) ) {
162
+ $contactAddress->setStateCode($products_detail['_billing_state'][0]);
163
+ }
164
+ }
165
+
166
+ return $contactAddress;
167
+ }
168
+
169
+ /**
170
+ * WooCommerce Handler for new orders.
171
+ *
172
+ * @param WC_Order|WC_Order_Refund $order_id The order id.
173
+ *
174
+ * @return void
175
+ */
176
+ public function ceHandlerWooCommerceNewOrder( $order_id ) {
177
+ try {
178
+ $order = wc_get_order($order_id);
179
+
180
+ if ( is_object($order) && is_a($order, 'WC_Order') ) {
181
+ $this->upsertContact($this->convertToContactModel($order->get_id()));
182
+ }
183
+ } catch ( Exception $exception ) {
184
+ RaygunManager::get_instance()->exception_handler($exception);
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Register Hooks.
190
+ *
191
+ * @return void
192
+ */
193
+ public function registerHooks() {
194
+ add_action('woocommerce_checkout_order_created', array( $this, 'ceHandlerWooCommerceNewOrder' ), 10, 1);
195
+ }
196
+
197
+ /**
198
+ * Unregister Hooks.
199
+ *
200
+ * @return void
201
+ */
202
+ public function unregisterHooks() {
203
+ remove_action('woocommerce_checkout_order_created', array( $this, 'ceHandlerWooCommerceOrder' ));
204
+ }
205
+
206
+ /**
207
+ * Gets the contact model from order.
208
+ *
209
+ * @param ?int $limit The limit.
210
+ *
211
+ * @return array|null
212
+ */
213
+ public function get_contacts( $limit = null ) {
214
+ if ( ! is_int($limit) || $limit <= 0 ) {
215
+ $limit = null;
216
+ }
217
+
218
+ $backfillArray = array();
219
+
220
+ $args = array(
221
+ 'posts_per_page' => -1,
222
+ 'post_type' => 'shop_order',
223
+ 'post_status' => array_keys(wc_get_order_statuses()),
224
+ );
225
+
226
+ if ( null != $limit ) {
227
+ $args['posts_per_page'] = $limit;
228
+ }
229
+
230
+ $products_orders = get_posts($args);
231
+
232
+ foreach ( $products_orders as $products_order ) {
233
+
234
+ $contactModel = null;
235
+ try {
236
+ $this->isSync = true;
237
+ $contactModel = $this->convertToContactModel($products_order->ID);
238
+ } catch ( Exception $exception ) {
239
+ // Silent exception.
240
+ continue;
241
+ }
242
+
243
+ if ( ! empty($contactModel->getEmail()) ) {
244
+ array_push($backfillArray, $contactModel);
245
+ }
246
+ }
247
+
248
+ if ( ! empty($backfillArray) ) {
249
+ return $backfillArray;
250
+ }
251
+
252
+ return null;
253
+ }
254
  }
src/Modules/Contacts/Handlers/WpFormsPluginHandler.php CHANGED
@@ -1,6 +1,5 @@
1
  <?php
2
 
3
-
4
  namespace CreativeMail\Modules\Contacts\Handlers;
5
 
6
  define('CE4WP_WPF_EVENTTYPE', 'WordPress - WPForms');
@@ -11,164 +10,209 @@ use CreativeMail\Modules\Contacts\Models\OptActionBy;
11
  use Exception;
12
  use function Sodium\add;
13
 
14
- class WpFormsPluginHandler extends BaseContactFormPluginHandler
15
- {
16
- private function get_form_type_field($formData, $type)
17
- {
18
- foreach ($formData as $field) {
19
- if (array_key_exists('type', $field) && $field['type'] === $type) {
20
- return $field;
21
- }
22
- }
23
- return null;
24
- }
25
-
26
- private function convertEntryStringToFormData($entry)
27
- {
28
- $formdata = array();
29
- $entry = json_decode($entry->fields, true);
30
- foreach ($entry as $field) {
31
- if (array_key_exists('type', $field)) {
32
- $formdata[$field["type"]] = $field["value"];
33
- }
34
- }
35
- return $entry;
36
- }
37
-
38
- public function convertToContactModel($formData)
39
- {
40
- $contactModel = new ContactModel();
41
-
42
- $contactModel->setEventType(CE4WP_WPF_EVENTTYPE);
43
- $contactModel->setOptIn(false);
44
- $contactModel->setOptOut(false);
45
- $contactModel->setOptActionBy(OptActionBy::Owner);
46
-
47
- $emailField = $this->get_form_type_field($formData, 'email');
48
- if (array_key_exists('value', $emailField)) {
49
- if (!empty($emailField['value'])) {
50
- $contactModel->setEmail($emailField['value']);
51
- }
52
- }
53
-
54
- $nameField = $this->get_form_type_field($formData, 'name');
55
- if (array_key_exists('first', $nameField)) {
56
- if (!empty($nameField['first'])) {
57
- $contactModel->setFirstName($nameField['first']);
58
- }
59
- }
60
- if (array_key_exists('last', $nameField)) {
61
- if (!empty($nameField['last'])) {
62
- $contactModel->setLastName($nameField['last']);
63
- }
64
- }
65
-
66
- if(empty($contactModel -> firstName) && empty($contactModel -> lastName) && !empty($nameField) && !empty($nameField['value']))
67
- {
68
- $nameValues = preg_split ('/ /', $nameField['value']);
69
- if (!empty($nameValues)) {
70
- $arrLength = count($nameValues);
71
- $contactModel->setFirstName($nameValues[0]);
72
-
73
- if($arrLength > 1) {
74
- $contactModel->setLastName($nameValues[$arrLength - 1]);
75
- }
76
- }
77
- }
78
-
79
- $phoneField = $this->get_form_type_field($formData, 'phone');
80
- if (!empty($phoneField)) {
81
- if (!empty($phoneField['value'])) {
82
- $contactModel->setPhone($phoneField['value']);
83
- }
84
- }
85
-
86
- $dateField = $this->get_form_type_field($formData, 'date-time');
87
- if (!empty($dateField) && array_key_exists('date', $dateField)) {
88
- if (!empty($dateField['date']) && in_array(strtolower($dateField['name']), $this->birthdayFields)) {
89
- $contactModel->setBirthday($dateField['date']);
90
- }
91
- }
92
-
93
- $consentField = $this->get_form_type_field($formData, "gdpr-checkbox");
94
- if (!empty($consentField) && array_key_exists('value', $consentField)) {
95
- //If a gdpr checkbox is present it is required before submitting
96
- //The value is a string like "I consent to having this website store my information . . . " instead of a bool
97
- //Will assume people won't alter or change this to be the other way around so having this value == consent
98
- $contactModel->setOptIn(true);
99
- $contactModel->setOptActionBy(OptActionBy::Visitor);
100
- }
101
-
102
- return $contactModel;
103
- }
104
-
105
- public function ceHandleWpFormsProcessComplete($fields)
106
- {
107
- try {
108
- $this->upsertContact($this->convertToContactModel($fields));
109
- } catch (Exception $exception) {
110
- RaygunManager::get_instance()->exception_handler($exception);
111
- }
112
- }
113
-
114
- public function registerHooks()
115
- {
116
- // https://wpforms.com/developers/wpforms_process_complete/ .
117
- add_action('wpforms_process_complete', array($this, 'ceHandleWpFormsProcessComplete'), 10, 4);
118
- }
119
-
120
- public function unregisterHooks()
121
- {
122
- remove_action('wpforms_process_complete', array($this, 'ceHandleWpFormsProcessComplete'));
123
- }
124
-
125
- public function get_contacts($limit = null)
126
- {
127
- if (!is_int($limit) || $limit <= 0) {
128
- $limit = null;
129
- }
130
-
131
- // Relies on plugin => WpForms paid or pro.
132
- if (in_array('wpforms/wpforms.php', apply_filters('active_plugins', get_option('active_plugins')))
133
- || in_array('wpforms-lite/wpforms.php', apply_filters('active_plugins', get_option('active_plugins')))
134
- ) {
135
- // Get form submissions from the WpForms DB.
136
- global $wpdb;
137
- $contactsArray = array();
138
-
139
- // Get the form entries.
140
- $entriesQuery = 'SELECT fields FROM wp_wpforms_entries';
141
- $entryResult = $wpdb->get_results($wpdb->prepare($entriesQuery));
142
-
143
- // Loop through entries and create the contacts.
144
- foreach ($entryResult as $entry) {
145
- $contactModel = null;
146
- try {
147
- $entryData = $this->convertEntryStringToFormData($entry);
148
- $contact = $this->convertToContactModel($entryData);
149
- if (!empty($contact->getEmail())) {
150
- array_push($contactsArray, $contact);
151
- }
152
- } catch (Exception $exception) {
153
- RaygunManager::get_instance()->exception_handler($exception);
154
- continue;
155
- }
156
-
157
- if (isset($limit) && count($contactsArray) >= $limit) {
158
- break;
159
- }
160
- }
161
-
162
- if (!empty($contactsArray)) {
163
- return $contactsArray;
164
- }
165
- }
166
-
167
- return null;
168
- }
169
-
170
- function __construct()
171
- {
172
- parent::__construct();
173
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  }
1
  <?php
2
 
 
3
  namespace CreativeMail\Modules\Contacts\Handlers;
4
 
5
  define('CE4WP_WPF_EVENTTYPE', 'WordPress - WPForms');
10
  use Exception;
11
  use function Sodium\add;
12
 
13
+ final class WpFormsPluginHandler extends BaseContactFormPluginHandler {
14
+
15
+ public function __construct() {
16
+ parent::__construct();
17
+ }
18
+
19
+ /**
20
+ * Get the form type field.
21
+ *
22
+ * @param mixed $formData The form data.
23
+ * @param string $type The type.
24
+ *
25
+ * @return mixed|null
26
+ */
27
+ private function get_form_type_field( $formData, $type ) {
28
+ foreach ( $formData as $field ) {
29
+ if ( array_key_exists('type', $field) && $field['type'] === $type ) {
30
+ return $field;
31
+ }
32
+ }
33
+
34
+ return null;
35
+ }
36
+
37
+ /**
38
+ * Converts the entry string into form data.
39
+ *
40
+ * @param mixed $entry The entry.
41
+ *
42
+ * @return mixed
43
+ */
44
+ private function convertEntryStringToFormData( $entry ) {
45
+ $formdata = array();
46
+
47
+ $entry = json_decode($entry->fields, true);
48
+
49
+ foreach ( $entry as $field ) {
50
+ if ( array_key_exists('type', $field) ) {
51
+ $formdata[ $field['type'] ] = $field['value'];
52
+ }
53
+ }
54
+
55
+ return $entry;
56
+ }
57
+
58
+ /**
59
+ * Converts to Contact Model.
60
+ *
61
+ * @param mixed $formData The form data.
62
+ *
63
+ * @return ContactModel
64
+ *
65
+ * @throws Exception
66
+ */
67
+ public function convertToContactModel( $formData ) {
68
+ $contactModel = new ContactModel();
69
+
70
+ $contactModel->setEventType(CE4WP_WPF_EVENTTYPE);
71
+ $contactModel->setOptIn(false);
72
+ $contactModel->setOptOut(false);
73
+ $contactModel->setOptActionBy(OptActionBy::OWNER);
74
+
75
+ $emailField = $this->get_form_type_field($formData, 'email');
76
+
77
+ if ( array_key_exists('value', $emailField) ) {
78
+ if ( ! empty($emailField['value']) ) {
79
+ $contactModel->setEmail($emailField['value']);
80
+ }
81
+ }
82
+
83
+ $nameField = $this->get_form_type_field($formData, 'name');
84
+
85
+ if ( array_key_exists('first', $nameField) ) {
86
+ if ( ! empty($nameField['first']) ) {
87
+ $contactModel->setFirstName($nameField['first']);
88
+ }
89
+ }
90
+ if ( array_key_exists('last', $nameField) ) {
91
+ if ( ! empty($nameField['last']) ) {
92
+ $contactModel->setLastName($nameField['last']);
93
+ }
94
+ }
95
+
96
+ if ( empty($contactModel->firstName) && empty($contactModel->lastName) && ! empty($nameField) && ! empty($nameField['value']) ) {
97
+ $nameValues = preg_split ('/ /', $nameField['value']);
98
+ if ( ! empty($nameValues) ) {
99
+ $arrLength = count($nameValues);
100
+ $contactModel->setFirstName($nameValues[0]);
101
+
102
+ if ( $arrLength > 1 ) {
103
+ $contactModel->setLastName($nameValues[ $arrLength - 1 ]);
104
+ }
105
+ }
106
+ }
107
+
108
+ $phoneField = $this->get_form_type_field($formData, 'phone');
109
+
110
+ if ( ! empty($phoneField) ) {
111
+ if ( ! empty($phoneField['value']) ) {
112
+ $contactModel->setPhone($phoneField['value']);
113
+ }
114
+ }
115
+
116
+ $dateField = $this->get_form_type_field($formData, 'date-time');
117
+
118
+ if ( ! empty($dateField) && array_key_exists('date', $dateField) ) {
119
+ if ( ! empty($dateField['date']) && in_array(strtolower($dateField['name']), $this->birthdayFields, true) ) {
120
+ $contactModel->setBirthday($dateField['date']);
121
+ }
122
+ }
123
+
124
+ $consentField = $this->get_form_type_field($formData, 'gdpr-checkbox');
125
+
126
+ if ( ! empty($consentField) && array_key_exists('value', $consentField) ) {
127
+ // If a gdpr checkbox is present it is required before submitting.
128
+ // The value is a string like "I consent to having this website store my information . . . " instead of a bool.
129
+ // Will assume people won't alter or change this to be the other way around so having this value == consent.
130
+ $contactModel->setOptIn(true);
131
+ $contactModel->setOptActionBy(OptActionBy::VISITOR);
132
+ }
133
+
134
+ return $contactModel;
135
+ }
136
+
137
+ /**
138
+ * Handles the form submission.
139
+ *
140
+ * @param mixed $fields The fields.
141
+ *
142
+ * @return void
143
+ */
144
+ public function ceHandleWpFormsProcessComplete( $fields ): void {
145
+ try {
146
+ $this->upsertContact($this->convertToContactModel($fields));
147
+ } catch ( Exception $exception ) {
148
+ RaygunManager::get_instance()->exception_handler($exception);
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Register the Hooks.
154
+ *
155
+ * @return void
156
+ */
157
+ public function registerHooks() {
158
+ add_action('wpforms_process_complete', array( $this, 'ceHandleWpFormsProcessComplete' ), 10, 4);
159
+ }
160
+
161
+ /**
162
+ * Unregister the Hooks.
163
+ *
164
+ * @return void
165
+ */
166
+ public function unregisterHooks() {
167
+ remove_action('wpforms_process_complete', array( $this, 'ceHandleWpFormsProcessComplete' ));
168
+ }
169
+
170
+ /**
171
+ * Get the contacts.
172
+ *
173
+ * @param int|null $limit The limit.
174
+ *
175
+ * @return array|null
176
+ */
177
+ public function get_contacts( $limit = null ) {
178
+ if ( ! is_int($limit) || $limit <= 0 ) {
179
+ $limit = null;
180
+ }
181
+
182
+ // Relies on plugin => WpForms paid or pro.
183
+ if ( in_array('wpforms/wpforms.php', apply_filters('active_plugins', get_option('active_plugins')), true)
184
+ || in_array('wpforms-lite/wpforms.php', apply_filters('active_plugins', get_option('active_plugins')), true)
185
+ ) {
186
+ // Get form submissions from the WpForms DB.
187
+ global $wpdb;
188
+ $contactsArray = array();
189
+ // Get the form entries.
190
+ $entryResult = $wpdb->get_results('SELECT fields FROM wp_wpforms_entries');
191
+
192
+ // Loop through entries and create the contacts.
193
+ foreach ( $entryResult as $entry ) {
194
+ $contactModel = null;
195
+ try {
196
+ $entryData = $this->convertEntryStringToFormData($entry);
197
+ $contact = $this->convertToContactModel($entryData);
198
+ if ( ! empty($contact->getEmail()) ) {
199
+ array_push($contactsArray, $contact);
200
+ }
201
+ } catch ( Exception $exception ) {
202
+ RaygunManager::get_instance()->exception_handler($exception);
203
+ continue;
204
+ }
205
+
206
+ if ( isset($limit) && count($contactsArray) >= $limit ) {
207
+ break;
208
+ }
209
+ }
210
+
211
+ if ( ! empty($contactsArray) ) {
212
+ return $contactsArray;
213
+ }
214
+ }
215
+
216
+ return null;
217
+ }
218
  }
src/Modules/Contacts/Managers/ContactsSyncManager.php CHANGED
@@ -4,25 +4,32 @@ namespace CreativeMail\Modules\Contacts\Managers;
4
 
5
  use CreativeMail\Modules\Contacts\Processors\ContactsSyncBackgroundProcessor;
6
 
7
- class ContactsSyncManager
8
- {
9
- private $contacts_sync_background_processor;
10
 
11
- public function __construct()
12
- {
13
- $this->contacts_sync_background_processor = new ContactsSyncBackgroundProcessor();
14
- add_action(CE4WP_SYNCHRONIZE_ACTION, array($this, 'publish_contact_sync_request'));
15
- }
 
16
 
17
- public function __destruct()
18
- {
19
- remove_action(CE4WP_SYNCHRONIZE_ACTION, array($this, 'publish_contact_sync_request'));
20
- }
21
 
22
- public function publish_contact_sync_request()
23
- {
24
- $this->contacts_sync_background_processor->push_to_queue(null);
25
- // Start the queue.
26
- $this->contacts_sync_background_processor->save()->dispatch();
27
- }
 
 
 
 
 
 
 
 
28
  }
4
 
5
  use CreativeMail\Modules\Contacts\Processors\ContactsSyncBackgroundProcessor;
6
 
7
+ final class ContactsSyncManager {
 
 
8
 
9
+ /**
10
+ * Stores the background processor instance.
11
+ *
12
+ * @var ContactsSyncBackgroundProcessor
13
+ */
14
+ private $contacts_sync_background_processor;
15
 
16
+ public function __construct() {
17
+ $this->contacts_sync_background_processor = new ContactsSyncBackgroundProcessor();
18
+ add_action(CE4WP_SYNCHRONIZE_ACTION, array( $this, 'publish_contact_sync_request' ));
19
+ }
20
 
21
+ public function __destruct() {
22
+ remove_action(CE4WP_SYNCHRONIZE_ACTION, array( $this, 'publish_contact_sync_request' ));
23
+ }
24
+
25
+ /**
26
+ * Publishes a contact sync request to the background processor.
27
+ *
28
+ * @return void
29
+ */
30
+ public function publish_contact_sync_request(): void {
31
+ $this->contacts_sync_background_processor->push_to_queue(null);
32
+ // Start the queue.
33
+ $this->contacts_sync_background_processor->save()->dispatch();
34
+ }
35
  }
src/Modules/Contacts/Models/ContactAddressModel.php CHANGED
@@ -1,97 +1,212 @@
1
- <?php
2
 
3
  namespace CreativeMail\Modules\Contacts\Models;
4
 
5
- class ContactAddressModel
6
- {
7
- public $countryCode;
8
- public $postalCode;
9
- public $state;
10
- public $stateCode;
11
- public $address;
12
- public $address2;
13
- public $city;
14
-
15
- public function setCountryCode($countryCode)
16
- {
17
- $this->countryCode = $countryCode;
18
- }
19
-
20
- public function getCountryCode()
21
- {
22
- return $this->countryCode;
23
- }
24
-
25
- public function setPostalCode($postalCode)
26
- {
27
- $this->postalCode = $postalCode;
28
- }
29
-
30
- public function getPostalCode()
31
- {
32
- return $this->postalCode;
33
- }
34
-
35
- public function setState($state)
36
- {
37
- $this->state = $state;
38
- }
39
-
40
- public function getState()
41
- {
42
- return $this->state;
43
- }
44
-
45
- public function setStateCode($stateCode)
46
- {
47
- $this->stateCode = $stateCode;
48
- }
49
-
50
- public function getStateCode()
51
- {
52
- return $this->stateCode;
53
- }
54
-
55
- public function setAddress($address)
56
- {
57
- $this->address = $address;
58
- }
59
-
60
- public function getAddress()
61
- {
62
- return $this->address;
63
- }
64
-
65
- public function setAddress2($address2)
66
- {
67
- $this->address2 = $address2;
68
- }
69
-
70
- public function getAddress2()
71
- {
72
- return $this->address2;
73
- }
74
-
75
- public function setCity($city)
76
- {
77
- $this->city = $city;
78
- }
79
-
80
- public function getCity()
81
- {
82
- return $this->city;
83
- }
84
-
85
- public function toArray()
86
- {
87
- return array(
88
- "country_code" => $this->getCountryCode(),
89
- "state_code" => $this->getStateCode(),
90
- "state" => $this->getState(),
91
- "postal_code" => $this->getPostalCode(),
92
- "address" => $this->getAddress(),
93
- "address2" => $this->getAddress2(),
94
- "city" => $this->getCity()
95
- );
96
- }
97
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare(strict_types = 1);
2
 
3
  namespace CreativeMail\Modules\Contacts\Models;
4
 
5
+ final class ContactAddressModel {
6
+
7
+ /**
8
+ * Stores the country code of the contact address.
9
+ *
10
+ * @var ?string
11
+ */
12
+ public $countryCode;
13
+
14
+ /**
15
+ * Stores the postal code of the contact address.
16
+ *
17
+ * @var ?string
18
+ */
19
+ public $postalCode;
20
+
21
+ /**
22
+ * Stores the state of the contact address.
23
+ *
24
+ * @var ?string
25
+ */
26
+ public $state;
27
+
28
+ /**
29
+ * Stores the state code of the contact address.
30
+ *
31
+ * @var ?string
32
+ */
33
+ public $stateCode;
34
+
35
+ /**
36
+ * Stores the address of the contact.
37
+ *
38
+ * @var ?string
39
+ */
40
+ public $address;
41
+
42
+ /**
43
+ * Stores the secondary address of the contact.
44
+ *
45
+ * @var ?string
46
+ */
47
+ public $address2;
48
+
49
+ /**
50
+ * Stores the city of the contact address.
51
+ *
52
+ * @var ?string
53
+ */
54
+ public $city;
55
+
56
+ /**
57
+ * Sets the country code of the contact address.
58
+ *
59
+ * @param ?string $countryCode The country code of the contact address.
60
+ *
61
+ * @return void
62
+ */
63
+ public function setCountryCode( ?string $countryCode ): void {
64
+ $this->countryCode = $countryCode;
65
+ }
66
+
67
+ /**
68
+ * Returns the country code of the contact address.
69
+ *
70
+ * @return ?string
71
+ */
72
+ public function getCountryCode(): ?string {
73
+ return $this->countryCode;
74
+ }
75
+
76
+ /**
77
+ * Set the postal code.
78
+ *
79
+ * @param ?string $postalCode The postal code.
80
+ *
81
+ * @return void
82
+ */
83
+ public function setPostalCode( ?string $postalCode ): void {
84
+ $this->postalCode = $postalCode;
85
+ }
86
+
87
+ /**
88
+ * Returns the postal code of the contact address.
89
+ *
90
+ * @return ?string
91
+ */
92
+ public function getPostalCode(): ?string {
93
+ return $this->postalCode;
94
+ }
95
+
96
+ /**
97
+ * Set the state.
98
+ *
99
+ * @param ?string $state The state.
100
+ *
101
+ * @return void
102
+ */
103
+ public function setState( ?string $state ): void {
104
+ $this->state = $state;
105
+ }
106
+
107
+ /**
108
+ * Returns the state of the contact address.
109
+ *
110
+ * @return ?string
111
+ */
112
+ public function getState(): ?string {
113
+ return $this->state;
114
+ }
115
+
116
+ /**
117
+ * Set the state code.
118
+ *
119
+ * @param ?string $stateCode The state code.
120
+ *
121
+ * @return void
122
+ */
123
+ public function setStateCode( ?string $stateCode ): void {
124
+ $this->stateCode = $stateCode;
125
+ }
126
+
127
+ /**
128
+ * Returns the state code of the contact address.
129
+ *
130
+ * @return ?string
131
+ */
132
+ public function getStateCode(): ?string {
133
+ return $this->stateCode;
134
+ }
135
+
136
+ /**
137
+ * Set the address.
138
+ *
139
+ * @param ?string $address The address.
140
+ *
141
+ * @return void
142
+ */
143
+ public function setAddress( ?string $address ): void {
144
+ $this->address = $address;
145
+ }
146
+
147
+ /**
148
+ * Returns the address of the contact.
149
+ *
150
+ * @return ?string
151
+ */
152
+ public function getAddress(): ?string {
153
+ return $this->address;
154
+ }
155
+
156
+ /**
157
+ * Set the secondary address.
158
+ *
159
+ * @param ?string $address2 The secondary address.
160
+ *
161
+ * @return void
162
+ */
163
+ public function setAddress2( ?string $address2 ): void {
164
+ $this->address2 = $address2;
165
+ }
166
+
167
+ /**
168
+ * Returns the secondary address of the contact.
169
+ *
170
+ * @return ?string
171
+ */
172
+ public function getAddress2(): ?string {
173
+ return $this->address2;
174
+ }
175
+
176
+ /**
177
+ * Set the city.
178
+ *
179
+ * @param ?string $city The city.
180
+ *
181
+ * @return void
182
+ */
183
+ public function setCity( ?string $city ): void {
184
+ $this->city = $city;
185
+ }
186
+
187
+ /**
188
+ * Returns the city of the contact address.
189
+ *
190
+ * @return ?string
191
+ */
192
+ public function getCity(): ?string {
193
+ return $this->city;
194
+ }
195
+
196
+ /**
197
+ * Returns the contact address as an array.
198
+ *
199
+ * @return array<string,string>
200
+ */
201
+ public function toArray(): array {
202
+ return array(
203
+ 'country_code' => $this->getCountryCode(),
204
+ 'state_code' => $this->getStateCode(),
205
+ 'state' => $this->getState(),
206
+ 'postal_code' => $this->getPostalCode(),
207
+ 'address' => $this->getAddress(),
208
+ 'address2' => $this->getAddress2(),
209
+ 'city' => $this->getCity(),
210
+ );
211
+ }
212
+ }
src/Modules/Contacts/Models/ContactFormSevenSubmission.php CHANGED
@@ -5,7 +5,7 @@ namespace CreativeMail\Modules\Contacts\Models;
5
 
6
  use WPCF7_Submission;
7
 
8
- class ContactFormSevenSubmission extends WPCF7_Submission
9
- {
10
-
11
- }
5
 
6
  use WPCF7_Submission;
7
 
8
+ class ContactFormSevenSubmission extends WPCF7_Submission {
9
+
10
+
11
+ }
src/Modules/Contacts/Models/ContactModel.php CHANGED
@@ -4,205 +4,173 @@ namespace CreativeMail\Modules\Contacts\Models;
4
 
5
  use Exception;
6
 
7
- class ContactModel
8
- {
9
- public $email;
10
- public $phone;
11
- public $companyName;
12
- public $name;
13
- public $firstName;
14
- public $lastName;
15
- public $optIn;
16
- public $optOut;
17
- public $optActionBy;
18
- public $contactAddresses;
19
- public $eventType;
20
- public $numberOfOrders;
21
- private $birthday;
22
- private $listId;
23
-
24
- function __construct()
25
- {
26
- }
27
-
28
- public function setEmail($email)
29
- {
30
- if (isset($email) && !empty($email)) {
31
- $this->email = $email;
32
- }
33
- else {
34
- throw new Exception('invalid value for email');
35
- }
36
- }
37
-
38
- public function getEmail()
39
- {
40
- return $this->email;
41
- }
42
-
43
- public function setPhone($phone)
44
- {
45
- $this->phone = $phone;
46
- }
47
-
48
- public function getPhone()
49
- {
50
- return $this->phone;
51
- }
52
-
53
- public function setCompanyName($companyName)
54
- {
55
- $this->companyName = $companyName;
56
- }
57
-
58
- public function getCompanyName()
59
- {
60
- return $this->companyName;
61
- }
62
-
63
- public function setName($name)
64
- {
65
- $this->name = $name;
66
- }
67
-
68
- public function getName()
69
- {
70
- return $this->name;
71
- }
72
-
73
- public function setFirstName($firstName)
74
- {
75
- $this->firstName = $firstName;
76
- }
77
-
78
- public function getFirstName()
79
- {
80
- return $this->firstName;
81
- }
82
-
83
- public function setLastName($lastName)
84
- {
85
- $this->lastName = $lastName;
86
- }
87
-
88
- public function getLastName()
89
- {
90
- return $this->lastName;
91
- }
92
-
93
- public function setOptIn($optIn)
94
- {
95
- $this->optIn = $optIn;
96
- }
97
-
98
- public function setOptOut($optOut)
99
- {
100
- $this->optOut = $optOut;
101
- }
102
-
103
- public function getOptIn()
104
- {
105
- return $this->optIn;
106
- }
107
-
108
- public function getOptOut()
109
- {
110
- return $this->optOut;
111
- }
112
-
113
- public function setOptActionBy($optActionBy)
114
- {
115
- $this->optActionBy = $optActionBy;
116
- }
117
-
118
- public function getOptActionBy()
119
- {
120
- return $this->optActionBy;
121
- }
122
-
123
- public function setNumberOfOrders($numberOfOrders)
124
- {
125
- $this->numberOfOrders = $numberOfOrders;
126
- }
127
-
128
- public function getNumberOfOrders()
129
- {
130
- return $this->numberOfOrders;
131
- }
132
-
133
- public function setContactAddress(ContactAddressModel $contactAddresses)
134
- {
135
- $this->contactAddresses = $contactAddresses;
136
- }
137
-
138
- /**
139
- * The address model for the contact.
140
- *
141
- * @return ContactAddressModel
142
- */
143
- public function getContactAddress()
144
- {
145
- return $this->contactAddresses;
146
- }
147
-
148
- public function setEventType($eventType)
149
- {
150
- $this->eventType = $eventType;
151
- }
152
-
153
- public function getEventType()
154
- {
155
- return $this->eventType;
156
- }
157
-
158
- public function getBirthday()
159
- {
160
- return $this->birthday;
161
- }
162
-
163
- public function setBirthday($birthday)
164
- {
165
- $this->birthday = $birthday;
166
- }
167
-
168
- public function getListId()
169
- {
170
- return $this->listId;
171
- }
172
-
173
- public function setListId($listId)
174
- {
175
- $this->listId = $listId;
176
- }
177
-
178
- function toArray()
179
- {
180
- $result = array(
181
- "email" => $this->getEmail(),
182
- "phone" => $this->getPhone(),
183
- "birthday" => $this->getBirthday(),
184
- "company_name" => $this->getCompanyName(),
185
- "name" => $this->getName(),
186
- "first_name" => $this->getFirstName(),
187
- "last_name" => $this->getLastName(),
188
- "opt_in" => $this->getOptIn(),
189
- "opt_out" => $this->getOptOut(),
190
- "opt_action_by" => $this->getOptActionBy(),
191
- "event_type" => $this->getEventType(),
192
- "list_id" => $this->getListId(),
193
- "number_of_orders" => $this->getNumberOfOrders(),
194
- );
195
-
196
- $address = $this->getContactAddress();
197
- if( $address != null ) {
198
- $result["addresses"] = array($address->toArray());
199
- }
200
-
201
- return $result;
202
- }
203
-
204
- function toJson()
205
- {
206
- return wp_json_encode($this->toArray());
207
- }
208
  }
4
 
5
  use Exception;
6
 
7
+ class ContactModel {
8
+
9
+ public $email;
10
+ public $phone;
11
+ public $companyName;
12
+ public $name;
13
+ public $firstName;
14
+ public $lastName;
15
+ public $optIn;
16
+ public $optOut;
17
+ public $optActionBy;
18
+ public $contactAddresses;
19
+ public $eventType;
20
+ public $numberOfOrders;
21
+ private $birthday;
22
+ private $listId;
23
+
24
+ public function __construct() {
25
+ }
26
+
27
+ public function setEmail( $email ) {
28
+ if ( isset($email) && ! empty($email) ) {
29
+ $this->email = $email;
30
+ } else {
31
+ throw new Exception('invalid value for email');
32
+ }
33
+ }
34
+
35
+ public function getEmail() {
36
+ return $this->email;
37
+ }
38
+
39
+ public function setPhone( $phone ) {
40
+ $this->phone = $phone;
41
+ }
42
+
43
+ public function getPhone() {
44
+ return $this->phone;
45
+ }
46
+
47
+ public function setCompanyName( $companyName ) {
48
+ $this->companyName = $companyName;
49
+ }
50
+
51
+ public function getCompanyName() {
52
+ return $this->companyName;
53
+ }
54
+
55
+ public function setName( $name ) {
56
+ $this->name = $name;
57
+ }
58
+
59
+ public function getName() {
60
+ return $this->name;
61
+ }
62
+
63
+ public function setFirstName( $firstName ) {
64
+ $this->firstName = $firstName;
65
+ }
66
+
67
+ public function getFirstName() {
68
+ return $this->firstName;
69
+ }
70
+
71
+ public function setLastName( $lastName ) {
72
+ $this->lastName = $lastName;
73
+ }
74
+
75
+ public function getLastName() {
76
+ return $this->lastName;
77
+ }
78
+
79
+ public function setOptIn( $optIn ) {
80
+ $this->optIn = $optIn;
81
+ }
82
+
83
+ public function setOptOut( $optOut ) {
84
+ $this->optOut = $optOut;
85
+ }
86
+
87
+ public function getOptIn() {
88
+ return $this->optIn;
89
+ }
90
+
91
+ public function getOptOut() {
92
+ return $this->optOut;
93
+ }
94
+
95
+ public function setOptActionBy( $optActionBy ) {
96
+ $this->optActionBy = $optActionBy;
97
+ }
98
+
99
+ public function getOptActionBy() {
100
+ return $this->optActionBy;
101
+ }
102
+
103
+ public function setNumberOfOrders( $numberOfOrders ) {
104
+ $this->numberOfOrders = $numberOfOrders;
105
+ }
106
+
107
+ public function getNumberOfOrders() {
108
+ return $this->numberOfOrders;
109
+ }
110
+
111
+ public function setContactAddress( ?ContactAddressModel $contactAddresses ) {
112
+ $this->contactAddresses = $contactAddresses;
113
+ }
114
+
115
+ /**
116
+ * The address model for the contact.
117
+ *
118
+ * @return ContactAddressModel
119
+ */
120
+ public function getContactAddress() {
121
+ return $this->contactAddresses;
122
+ }
123
+
124
+ public function setEventType( $eventType ) {
125
+ $this->eventType = $eventType;
126
+ }
127
+
128
+ public function getEventType() {
129
+ return $this->eventType;
130
+ }
131
+
132
+ public function getBirthday() {
133
+ return $this->birthday;
134
+ }
135
+
136
+ public function setBirthday( $birthday ) {
137
+ $this->birthday = $birthday;
138
+ }
139
+
140
+ public function getListId() {
141
+ return $this->listId;
142
+ }
143
+
144
+ public function setListId( $listId ) {
145
+ $this->listId = $listId;
146
+ }
147
+
148
+ public function toArray() {
149
+ $result = array(
150
+ 'email' => $this->getEmail(),
151
+ 'phone' => $this->getPhone(),
152
+ 'birthday' => $this->getBirthday(),
153
+ 'company_name' => $this->getCompanyName(),
154
+ 'name' => $this->getName(),
155
+ 'first_name' => $this->getFirstName(),
156
+ 'last_name' => $this->getLastName(),
157
+ 'opt_in' => $this->getOptIn(),
158
+ 'opt_out' => $this->getOptOut(),
159
+ 'opt_action_by' => $this->getOptActionBy(),
160
+ 'event_type' => $this->getEventType(),
161
+ 'list_id' => $this->getListId(),
162
+ 'number_of_orders' => $this->getNumberOfOrders(),
163
+ );
164
+
165
+ $address = $this->getContactAddress();
166
+ if ( null != $address ) {
167
+ $result['addresses'] = array( $address->toArray() );
168
+ }
169
+
170
+ return $result;
171
+ }
172
+
173
+ public function toJson() {
174
+ return wp_json_encode($this->toArray());
175
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  }
src/Modules/Contacts/Models/FormidableContactForm.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace CreativeMail\Modules\Contacts\Models;
4
+
5
+ class FormidableContactForm {
6
+ public string $firstName;
7
+ public string $lastName;
8
+ public string $birthday;
9
+ public string $phone;
10
+ public string $email;
11
+ }
src/Modules/Contacts/Models/OptActionBy.php CHANGED
@@ -3,9 +3,7 @@
3
 
4
  namespace CreativeMail\Modules\Contacts\Models;
5
 
6
-
7
- class OptActionBy
8
- {
9
- const Visitor = 1;
10
- const Owner = 2;
11
- }
3
 
4
  namespace CreativeMail\Modules\Contacts\Models;
5
 
6
+ class OptActionBy {
7
+ const VISITOR = 1;
8
+ const OWNER = 2;
9
+ }
 
 
src/Modules/Contacts/Processors/ContactsSyncBackgroundProcessor.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  namespace CreativeMail\Modules\Contacts\Processors;
4
 
5
- use CreativeMail\Helpers\ValidationHelper;
6
  use CreativeMail\Managers\IntegrationManager;
7
  use CreativeMail\Managers\RaygunManager;
8
  use CreativeMail\Modules\Contacts\Services\ContactsSyncService;
@@ -12,72 +12,71 @@ use ReflectionClass;
12
  use ReflectionException;
13
  use WP_Background_Process;
14
 
15
- class ContactsSyncBackgroundProcessor extends WP_Background_Process
16
- {
17
- protected $action = 'ce_contact_sync_background_process';
18
 
19
- /**
20
- * Task
21
- *
22
- * Override this method to perform any actions required on each
23
- * queue item. Return the modified item for further processing
24
- * in the next pass through. Or, return false to remove the
25
- * item from the queue.
26
- *
27
- * @param mixed $item
28
- *
29
- * @return false
30
- */
31
- protected function task($item)
32
- {
33
- try {
34
- // Synchronize contacts based on the active plugins
35
- $integrationManager = new IntegrationManager();
36
- $activated_integrations = $integrationManager->get_activated_integrations();
37
 
38
- if (!empty($activated_integrations)) {
39
- $this->start_contacts_sync_for_all_integrations($activated_integrations);
40
- }
41
- } catch (Exception $exception) {
42
- RaygunManager::get_instance()->exception_handler($exception);
43
- }
 
 
 
 
 
 
 
 
 
 
 
44
 
45
- return false;
46
- }
 
 
 
 
47
 
48
- /**
49
- * Starts the contacts sync for all the activated plugins
50
- *
51
- * @param Integration[] $activated_integrations
52
- *
53
- * @throws ReflectionException
54
- */
55
- private function start_contacts_sync_for_all_integrations($activated_integrations)
56
- {
57
- $total_contacts = array();
58
 
59
- if (!ValidationHelper::is_null_or_empty($activated_integrations)) {
60
- // todo throw exception
61
- }
 
 
 
 
 
 
62
 
63
- // Get all contacts.
64
- foreach ($activated_integrations as $activated_integration) {
65
- $class = new ReflectionClass($activated_integration->get_integration_handler());
66
- $plugin_handler = $class->newInstance();
67
- if (method_exists($plugin_handler, 'get_contacts')) {
68
- $plugin_contacts = $plugin_handler->get_contacts(null);
69
- }
70
- if (isset($plugin_contacts) && !empty($plugin_contacts)) {
71
- foreach ($plugin_contacts as $plugin_contact) {
72
- $total_contacts[] = $plugin_contact;
73
- }
74
- }
75
- }
76
 
77
- if (!empty($total_contacts)) {
78
- // Start contact sync.
79
- $contactSyncService = new ContactsSyncService();
80
- $contactSyncService->upsertContacts($total_contacts);
81
- }
82
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  }
2
 
3
  namespace CreativeMail\Modules\Contacts\Processors;
4
 
5
+ use CreativeMail\Exceptions\CreativeMailException;
6
  use CreativeMail\Managers\IntegrationManager;
7
  use CreativeMail\Managers\RaygunManager;
8
  use CreativeMail\Modules\Contacts\Services\ContactsSyncService;
12
  use ReflectionException;
13
  use WP_Background_Process;
14
 
15
+ class ContactsSyncBackgroundProcessor extends WP_Background_Process {
 
 
16
 
17
+ protected $action = 'ce_contact_sync_background_process';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
+ /**
20
+ * Task
21
+ *
22
+ * Override this method to perform any actions required on each
23
+ * queue item. Return the modified item for further processing
24
+ * in the next pass through. Or, return false to remove the
25
+ * item from the queue.
26
+ *
27
+ * @param mixed $item Queue item to iterate over.
28
+ *
29
+ * @return false
30
+ */
31
+ protected function task( $item ) {
32
+ try {
33
+ // Synchronize contacts based on the active plugins.
34
+ $integrationManager = new IntegrationManager();
35
+ $activated_integrations = $integrationManager->get_activated_integrations();
36
 
37
+ if ( ! empty($activated_integrations) ) {
38
+ $this->start_contacts_sync_for_all_integrations($activated_integrations);
39
+ }
40
+ } catch ( Exception $exception ) {
41
+ RaygunManager::get_instance()->exception_handler($exception);
42
+ }
43
 
44
+ return false;
45
+ }
 
 
 
 
 
 
 
 
46
 
47
+ /**
48
+ * Starts the contacts sync for all the activated plugins
49
+ *
50
+ * @param Integration[] $activated_integrations The activated integrations.
51
+ *
52
+ * @throws ReflectionException
53
+ */
54
+ private function start_contacts_sync_for_all_integrations( $activated_integrations ) {
55
+ $total_contacts = array();
56
 
57
+ if ( ! empty($activated_integrations) ) {
58
+ $exception = new CreativeMailException('No activated integrations available');
59
+ RaygunManager::get_instance()->exception_handler($exception);
60
+ }
 
 
 
 
 
 
 
 
 
61
 
62
+ // Get all contacts.
63
+ foreach ( $activated_integrations as $activated_integration ) {
64
+ $class = new ReflectionClass($activated_integration->get_integration_handler());
65
+ $plugin_handler = $class->newInstance();
66
+ if ( method_exists($plugin_handler, 'get_contacts') ) {
67
+ $plugin_contacts = $plugin_handler->get_contacts(null);
68
+ }
69
+ if ( isset($plugin_contacts) && ! empty($plugin_contacts) ) {
70
+ foreach ( $plugin_contacts as $plugin_contact ) {
71
+ $total_contacts[] = $plugin_contact;
72
+ }
73
+ }
74
+ }
75
+
76
+ if ( ! empty($total_contacts) ) {
77
+ // Start contact sync.
78
+ $contactSyncService = new ContactsSyncService();
79
+ $contactSyncService->upsertContacts($total_contacts);
80
+ }
81
+ }
82
  }
src/Modules/Contacts/Services/ContactsSyncService.php CHANGED
@@ -3,278 +3,276 @@
3
  namespace CreativeMail\Modules\Contacts\Services;
4
 
5
  use CreativeMail\CreativeMail;
 
6
  use CreativeMail\Helpers\EnvironmentHelper;
7
  use CreativeMail\Helpers\OptionsHelper;
8
- use CreativeMail\Helpers\ValidationHelper;
9
  use CreativeMail\Managers\RaygunManager;
10
  use CreativeMail\Modules\Api\Models\ApiRequestItem;
11
  use CreativeMail\Modules\Contacts\Models\ContactModel;
12
  use Exception;
13
  use stdClass;
14
 
15
- class ContactsSyncService
16
- {
17
- const FAST_LANE_LIMIT = 250;
18
- const CSV_FILE_MAX_MEMORY_SIZE = 1024 * 1024 * 5; // 5MB
19
-
20
- private function validate_email_address($emailAddress)
21
- {
22
- if (!isset($emailAddress) && empty($emailAddress)) {
23
- throw new Exception('No valid email address provided');
24
- }
25
- }
26
-
27
- private function ensure_event_type($eventType)
28
- {
29
- // DEV: For now, we only support WordPress.
30
- if (isset($eventType) && !empty($eventType)) {
31
- return $eventType;
32
- }
33
-
34
- return 'WordPress';
35
- }
36
-
37
- private function build_payload($contactModels)
38
- {
39
- $contacts = array();
40
- foreach ($contactModels as $model) {
41
- array_push($contacts, $model->toArray());
42
- }
43
-
44
- $data = array(
45
- "contacts" => $contacts
46
- );
47
-
48
- return wp_json_encode($data);
49
- }
50
-
51
- public function upsertContact(ContactModel $contactModel)
52
- {
53
- if( $contactModel == null ) {
54
- return false;
55
- }
56
-
57
- $this->validate_email_address($contactModel->getEmail());
58
- $contactModel->setEventType($this->ensure_event_type($contactModel->getEventType()));
59
-
60
- $jsonData = $this->build_payload(array($contactModel));
61
-
62
- $creativ_email = CreativeMail::get_instance();
63
-
64
-
65
- $creativ_email->get_api_manager()->get_api_background_process()->push_to_queue(
66
- new ApiRequestItem(
67
- 'POST',
68
- 'application/json',
69
- '/v1.0/contacts',
70
- $jsonData
71
- )
72
- );
73
-
74
- // Start the queue.
75
- $creativ_email->get_api_manager()->get_api_background_process()->save()->dispatch();
76
-
77
- return true;
78
- }
79
-
80
- public function upsertContacts($contactModels)
81
- {
82
- try {
83
- if (ValidationHelper::is_null_or_empty($contactModels)) {
84
- // todo throw exception
85
- }
86
-
87
- if (count($contactModels) > self::FAST_LANE_LIMIT) {
88
- $this->fast_lane_contacts_sync(array_slice($contactModels, 0, self::FAST_LANE_LIMIT));
89
- $this->slow_lane_contacts_sync(array_slice($contactModels, self::FAST_LANE_LIMIT, count($contactModels) - self::FAST_LANE_LIMIT));
90
-
91
- } else {
92
- $this->fast_lane_contacts_sync($contactModels);
93
- }
94
- } catch (Exception $exception) {
95
- RaygunManager::get_instance()->exception_handler($exception);
96
- }
97
-
98
- return true;
99
- }
100
-
101
- private function fast_lane_contacts_sync($contactModels)
102
- {
103
- if (ValidationHelper::is_null_or_empty($contactModels)) {
104
- // todo throw exception
105
- }
106
-
107
- $url = EnvironmentHelper::get_app_gateway_url('wordpress') . '/v1.0/contacts';
108
-
109
- $jsonData = $this->build_payload($contactModels);
110
-
111
- $args = [
112
- 'headers' => [
113
- 'x-api-key' => OptionsHelper::get_instance_api_key(),
114
- 'x-account-id' => OptionsHelper::get_connected_account_id(),
115
- 'content-type' => 'application/json'
116
- ],
117
- 'body' => $jsonData
118
- ];
119
-
120
- wp_remote_post($url, $args);
121
- }
122
-
123
- private function slow_lane_contacts_sync($contactModels)
124
- {
125
- if (ValidationHelper::is_null_or_empty($contactModels)) {
126
- // todo throw exception
127
- }
128
-
129
- // 1. Convert to csv file.
130
- $csv_file = $this->create_csv_file($contactModels);
131
- // 2. Request sas model (with url and uuid).
132
- $sas_request_model = $this->request_sas_model();
133
- // 3. Upload csv file using sas url.
134
- $this->upload_csv_file($csv_file, $sas_request_model->url);
135
- // 4. Call endpoint to start import (using uuid).
136
- $this->start_import_for_uuid($sas_request_model->uuid);
137
-
138
- }
139
-
140
- private function create_csv_file($contactModels)
141
- {
142
- $csv_content = '';
143
- if (ValidationHelper::is_null_or_empty($contactModels)) {
144
- // todo throw exception
145
- }
146
-
147
- $fd = fopen('php://temp/maxmemory:' . self::CSV_FILE_MAX_MEMORY_SIZE, 'w');
148
- if ($fd === false) {
149
- // todo throw exception
150
- }
151
-
152
- foreach($contactModels as $contactModel) {
153
- $contact_fields_array = $this->convert_contact_to_csv_array($contactModel);
154
- if (!ValidationHelper::is_null_or_empty($contact_fields_array)) {
155
- if ($fd !== false) {
156
- fputcsv($fd, $contact_fields_array);
157
- }
158
- }
159
- }
160
-
161
- if ($fd !== false) {
162
- rewind($fd);
163
- $csv_content = stream_get_contents($fd);
164
- fclose($fd);
165
- }
166
-
167
- return $csv_content;
168
- }
169
-
170
- private function request_sas_model()
171
- {
172
- $url = EnvironmentHelper::get_app_gateway_url('wordpress') . '/v1.0/contacts/request-import-sas-url';
173
- $args = [
174
- 'headers' => [
175
- 'x-api-key' => OptionsHelper::get_instance_api_key(),
176
- 'x-account-id' => OptionsHelper::get_connected_account_id()
177
- ]
178
- ];
179
- $response = wp_remote_get($url, $args);
180
-
181
- if (is_wp_error($response)) {
182
- // todo throw error
183
- }
184
- if (!$this->is_success_response($response)) {
185
- // todo throw error
186
- }
187
-
188
- $json = json_decode(is_array($response) ? $response['body'] : '');
189
-
190
- $request_sas_model = new stdClass();
191
- $request_sas_model->url = $json->url;
192
- $request_sas_model->uuid = $json->uuid;
193
-
194
- return $request_sas_model;
195
- }
196
-
197
- private function upload_csv_file($csv_file, $upload_url)
198
- {
199
- $args = array(
200
- 'headers' => array(
201
- 'x-ms-blob-type' => 'BlockBlob',
202
- 'content-type' => 'text/plain'
203
- ),
204
- 'body' => $csv_file,
205
- 'method' => 'PUT'
206
- );
207
-
208
- $response = wp_remote_request($upload_url, $args);
209
-
210
- if (is_wp_error($response)) {
211
- // todo throw exception
212
- }
213
-
214
- if (!$this->is_success_response($response)) {
215
- // todo throw exception
216
- }
217
- }
218
-
219
- private function start_import_for_uuid($uuid)
220
- {
221
- $url = EnvironmentHelper::get_app_gateway_url('wordpress') . '/v1.0/contacts/import';
222
-
223
- $data = array (
224
- 'uuid' => $uuid
225
- );
226
-
227
- $args = [
228
- 'headers' => [
229
- 'x-api-key' => OptionsHelper::get_instance_api_key(),
230
- 'x-account-id' => OptionsHelper::get_connected_account_id(),
231
- 'content-type' => 'application/json'
232
- ],
233
- 'body' => wp_json_encode($data),
234
- 'method' => 'POST'
235
- ];
236
-
237
- $response = wp_remote_post($url,
238
- $args);
239
-
240
- if (is_wp_error($response)) {
241
- // todo throw exception
242
- }
243
-
244
- if(!$this->is_success_response($response)) {
245
- // todo throw exception
246
- }
247
- }
248
-
249
- private function convert_contact_to_csv_array(ContactModel $contactModel)
250
- {
251
- if (ValidationHelper::is_null_or_empty($contactModel)) {
252
- return null;
253
- }
254
-
255
- $contact_fields = array(
256
- strval($contactModel->getEmail()),
257
- strval($contactModel->getFirstName()),
258
- strval($contactModel->getLastName()));
259
-
260
-
261
- $contactAddressModel = $contactModel->getContactAddress();
262
-
263
- if (ValidationHelper::is_null_or_empty($contactAddressModel)) {
264
- array_push($contact_fields, '','', '', '', '');
265
- } else {
266
- array_push($contact_fields, strval($contactAddressModel->getAddress()), strval($contactAddressModel->getCity()), strval($contactAddressModel->getPostalCode()),
267
- strval($contactAddressModel->getCountryCode()), strval($contactAddressModel->getState()));
268
- }
269
-
270
- array_push($contact_fields, strval($contactModel->getPhone()), strval($contactModel->getBirthday()), strval($contactModel->getCompanyName()), '', // JobTitle
271
- strval($contactModel->getOptIn()), strval($contactModel->getOptOut()), strval($contactModel->getEventType()));
272
- return $contact_fields;
273
- }
274
-
275
- private function is_success_response($response)
276
- {
277
- $response_code = wp_remote_retrieve_response_code($response);
278
- return $response_code >= 200 && $response_code <= 299;
279
- }
280
  }
3
  namespace CreativeMail\Modules\Contacts\Services;
4
 
5
  use CreativeMail\CreativeMail;
6
+ use CreativeMail\Exceptions\CreativeMailException;
7
  use CreativeMail\Helpers\EnvironmentHelper;
8
  use CreativeMail\Helpers\OptionsHelper;
 
9
  use CreativeMail\Managers\RaygunManager;
10
  use CreativeMail\Modules\Api\Models\ApiRequestItem;
11
  use CreativeMail\Modules\Contacts\Models\ContactModel;
12
  use Exception;
13
  use stdClass;
14
 
15
+ class ContactsSyncService {
16
+
17
+ const FAST_LANE_LIMIT = 250;
18
+ const CSV_FILE_MAX_MEMORY_SIZE = 1024 * 1024 * 5; // 5MB
19
+
20
+ private function validate_email_address( $emailAddress ) {
21
+ if ( ! isset($emailAddress) && empty($emailAddress) ) {
22
+ throw new Exception('No valid email address provided');
23
+ }
24
+ }
25
+
26
+ private function ensure_event_type( $eventType ) {
27
+ // DEV: For now, we only support WordPress.
28
+ if ( isset($eventType) && ! empty($eventType) ) {
29
+ return $eventType;
30
+ }
31
+
32
+ return 'WordPress';
33
+ }
34
+
35
+ private function build_payload( $contactModels ) {
36
+ $contacts = array();
37
+ foreach ( $contactModels as $model ) {
38
+ array_push($contacts, $model->toArray());
39
+ }
40
+
41
+ $data = array(
42
+ 'contacts' => $contacts,
43
+ );
44
+
45
+ return wp_json_encode($data);
46
+ }
47
+
48
+ public function upsertContact( ContactModel $contactModel ) {
49
+ if ( null == $contactModel ) {
50
+ return false;
51
+ }
52
+
53
+ $this->validate_email_address($contactModel->getEmail());
54
+ $contactModel->setEventType($this->ensure_event_type($contactModel->getEventType()));
55
+
56
+ $jsonData = $this->build_payload(array( $contactModel ));
57
+
58
+ $creativ_email = CreativeMail::get_instance();
59
+
60
+ $test = $creativ_email->get_api_manager()->get_api_background_process()->push_to_queue(
61
+ new ApiRequestItem(
62
+ 'POST',
63
+ 'application/json',
64
+ '/v1.0/contacts',
65
+ $jsonData
66
+ )
67
+ );
68
+
69
+ // Start the queue.
70
+ $creativ_email->get_api_manager()->get_api_background_process()->save()->dispatch();
71
+
72
+ return true;
73
+ }
74
+
75
+ public function upsertContacts( $contactModels ) {
76
+ try {
77
+ if ( empty($contactModels) ) {
78
+ $exception = new CreativeMailException('No contacts provided or empty Contact Model');
79
+ RaygunManager::get_instance()->exception_handler($exception);
80
+ }
81
+
82
+ if ( count($contactModels) > self::FAST_LANE_LIMIT ) {
83
+ $this->fast_lane_contacts_sync(array_slice($contactModels, 0, self::FAST_LANE_LIMIT));
84
+ $this->slow_lane_contacts_sync(array_slice($contactModels, self::FAST_LANE_LIMIT, count($contactModels) - self::FAST_LANE_LIMIT));
85
+
86
+ } else {
87
+ $this->fast_lane_contacts_sync($contactModels);
88
+ }
89
+ } catch ( Exception $exception ) {
90
+ RaygunManager::get_instance()->exception_handler($exception);
91
+ }
92
+
93
+ return true;
94
+ }
95
+
96
+ private function fast_lane_contacts_sync( $contactModels ) {
97
+ if ( empty( $contactModels ) ) {
98
+ $exception = new CreativeMailException('No contacts provided or empty Contact Model');
99
+ RaygunManager::get_instance()->exception_handler($exception);
100
+ }
101
+
102
+ $url = EnvironmentHelper::get_app_gateway_url('wordpress/v1.0/contacts');
103
+
104
+ $jsonData = $this->build_payload($contactModels);
105
+
106
+ $args = array(
107
+ 'headers' => array(
108
+ 'x-api-key' => OptionsHelper::get_instance_api_key(),
109
+ 'x-account-id' => OptionsHelper::get_connected_account_id(),
110
+ 'content-type' => 'application/json',
111
+ ),
112
+ 'body' => $jsonData,
113
+ );
114
+
115
+ wp_remote_post($url, $args);
116
+ }
117
+
118
+ private function slow_lane_contacts_sync( $contactModels ) {
119
+ if ( empty($contactModels) ) {
120
+ $exception = new CreativeMailException('No contacts provided or empty Contact Model');
121
+ RaygunManager::get_instance()->exception_handler($exception);
122
+ }
123
+
124
+ // 1. Convert to csv file.
125
+ $csv_file = $this->create_csv_file($contactModels);
126
+ // 2. Request sas model (with url and uuid).
127
+ $sas_request_model = $this->request_sas_model();
128
+ // 3. Upload csv file using sas url.
129
+ $this->upload_csv_file($csv_file, $sas_request_model->url);
130
+ // 4. Call endpoint to start import (using uuid).
131
+ $this->start_import_for_uuid($sas_request_model->uuid);
132
+
133
+ }
134
+
135
+ private function create_csv_file( $contactModels ) {
136
+ $csv_content = '';
137
+ if ( empty($contactModels) ) {
138
+ $exception = new CreativeMailException('Error trying to create the CSV to get the contacts data');
139
+ RaygunManager::get_instance()->exception_handler($exception);
140
+ }
141
+
142
+ $fd = fopen('php://temp/maxmemory:' . self::CSV_FILE_MAX_MEMORY_SIZE, 'w');
143
+ if ( false === $fd ) {
144
+ $exception = new CreativeMailException('No contacts provided or empty Contact Model');
145
+ RaygunManager::get_instance()->exception_handler($exception);
146
+ }
147
+
148
+ foreach ( $contactModels as $contactModel ) {
149
+ $contact_fields_array = $this->convert_contact_to_csv_array($contactModel);
150
+ if ( ! empty($contact_fields_array) ) {
151
+ if ( false !== $fd ) {
152
+ fputcsv($fd, $contact_fields_array);
153
+ }
154
+ }
155
+ }
156
+
157
+ if ( false !== $fd ) {
158
+ rewind($fd);
159
+ $csv_content = stream_get_contents($fd);
160
+ fclose($fd);
161
+ }
162
+
163
+ return $csv_content;
164
+ }
165
+
166
+ private function request_sas_model() {
167
+ $url = EnvironmentHelper::get_app_gateway_url('wordpress/v1.0/contacts/request-import-sas-url');
168
+ $args = array(
169
+ 'headers' => array(
170
+ 'x-api-key' => OptionsHelper::get_instance_api_key(),
171
+ 'x-account-id' => OptionsHelper::get_connected_account_id(),
172
+ ),
173
+ );
174
+ $response = wp_remote_get($url, $args);
175
+
176
+ if ( is_wp_error($response) ) {
177
+ $exception = new CreativeMailException('No contacts provided or empty Contact Model');
178
+ RaygunManager::get_instance()->exception_handler($exception);
179
+ }
180
+ if ( ! $this->is_success_response($response) ) {
181
+ $exception = new CreativeMailException('No contacts provided or empty Contact Model');
182
+ RaygunManager::get_instance()->exception_handler($exception);
183
+ }
184
+
185
+ $json = json_decode(is_array($response) ? $response['body'] : '');
186
+
187
+ $request_sas_model = new stdClass();
188
+ $request_sas_model->url = $json->url;
189
+ $request_sas_model->uuid = $json->uuid;
190
+
191
+ return $request_sas_model;
192
+ }
193
+
194
+ private function upload_csv_file( $csv_file, $upload_url ) {
195
+ $args = array(
196
+ 'headers' => array(
197
+ 'x-ms-blob-type' => 'BlockBlob',
198
+ 'content-type' => 'text/plain',
199
+ ),
200
+ 'body' => $csv_file,
201
+ 'method' => 'PUT',
202
+ );
203
+
204
+ $response = wp_remote_request($upload_url, $args);
205
+
206
+ if ( is_wp_error($response) ) {
207
+ $exception = new CreativeMailException('No contacts provided or empty Contact Model');
208
+ RaygunManager::get_instance()->exception_handler($exception);
209
+ }
210
+
211
+ if ( ! $this->is_success_response($response) ) {
212
+ $exception = new CreativeMailException('No contacts provided or empty Contact Model');
213
+ RaygunManager::get_instance()->exception_handler($exception);
214
+ }
215
+ }
216
+
217
+ private function start_import_for_uuid( $uuid ) {
218
+ $url = EnvironmentHelper::get_app_gateway_url('wordpress/v1.0/contacts/import');
219
+
220
+ $data = array(
221
+ 'uuid' => $uuid,
222
+ );
223
+
224
+ $args = array(
225
+ 'headers' => array(
226
+ 'x-api-key' => OptionsHelper::get_instance_api_key(),
227
+ 'x-account-id' => OptionsHelper::get_connected_account_id(),
228
+ 'content-type' => 'application/json',
229
+ ),
230
+ 'body' => wp_json_encode($data),
231
+ 'method' => 'POST',
232
+ );
233
+
234
+ $response = wp_remote_post($url,
235
+ $args);
236
+
237
+ if ( is_wp_error($response) ) {
238
+ $exception = new CreativeMailException('There was a WP_ERROR while trying to start import');
239
+ RaygunManager::get_instance()->exception_handler($exception);
240
+ }
241
+
242
+ if ( ! $this->is_success_response($response) ) {
243
+ $exception = new CreativeMailException('There was an error at the response.');
244
+ RaygunManager::get_instance()->exception_handler($exception);
245
+ }
246
+ }
247
+
248
+ private function convert_contact_to_csv_array( ContactModel $contactModel ) {
249
+ if ( empty($contactModel) ) {
250
+ return null;
251
+ }
252
+
253
+ $contact_fields = array(
254
+ strval($contactModel->getEmail()),
255
+ strval($contactModel->getFirstName()),
256
+ strval($contactModel->getLastName()),
257
+ );
258
+
259
+ $contactAddressModel = $contactModel->getContactAddress();
260
+
261
+ if ( empty($contactAddressModel) ) {
262
+ array_push($contact_fields, '', '', '', '', '');
263
+ } else {
264
+ array_push($contact_fields, strval($contactAddressModel->getAddress()), strval($contactAddressModel->getCity()), strval($contactAddressModel->getPostalCode()),
265
+ strval($contactAddressModel->getCountryCode()), strval($contactAddressModel->getState()));
266
+ }
267
+
268
+ // Job Title.
269
+ array_push($contact_fields, strval($contactModel->getPhone()), strval($contactModel->getBirthday()), strval($contactModel->getCompanyName()), '',
270
+ strval($contactModel->getOptIn()), strval($contactModel->getOptOut()), strval($contactModel->getEventType()));
271
+ return $contact_fields;
272
+ }
273
+
274
+ private function is_success_response( $response ) {
275
+ $response_code = wp_remote_retrieve_response_code($response);
276
+ return $response_code >= 200 && $response_code <= 299;
277
+ }
 
 
278
  }
src/Modules/DashboardWidgetModule.php CHANGED
@@ -6,111 +6,104 @@ use CreativeMail\Clients\CreativeMailClient;
6
  use CreativeMail\CreativeMail;
7
  use CreativeMail\Exceptions\CreativeMailException;
8
  use CreativeMail\Helpers\OptionsHelper;
9
- use CreativeMail\Helpers\ValidationHelper;
10
  use CreativeMail\Managers\RaygunManager;
11
  use Exception;
12
 
13
- class DashboardWidgetModule
14
- {
15
-
16
- private $creative_mail_client;
17
-
18
- /**
19
- * DashboardWidgetModule constructor.
20
- */
21
- public function __construct()
22
- {
23
- $this->creative_mail_client = new CreativeMailClient();
24
- }
25
-
26
- /**
27
- * Shows the Dashboard Widget.
28
- */
29
- public function show()
30
- {
31
- wp_enqueue_script( 'ce4wp_dashboard_widget', CE4WP_PLUGIN_URL . 'assets/js/dashboard.js', [], CE4WP_PLUGIN_VERSION );
32
- wp_localize_script( 'ce4wp_dashboard_widget', 'ce4wp_data', array(
33
- 'url' => admin_url( 'admin-ajax.php' ),
34
- 'nonce' => wp_create_nonce( 'ajax-nonce' )
35
- ) );
36
-
37
- $ce_has_account = OptionsHelper::get_instance_id() != null;
38
- if ( !$ce_has_account ) {
39
- $this->show_no_account();
40
- return;
41
- }
42
-
43
- try {
44
- $ce_account_status = $this->creative_mail_client->get_account_status();
45
-
46
- if (!ValidationHelper::is_null_or_empty($ce_account_status)) {
47
- $ce_has_finished_onboarding = $ce_account_status['has_finished_onboarding'];
48
- if (!$ce_has_finished_onboarding) {
49
- $this->show_no_account();
50
- return;
51
- }
52
- $ce_has_campaign = $ce_account_status['has_campaigns'];
53
- if (!$ce_has_campaign) {
54
- $this->show_no_campaigns();
55
- } else {
56
- $this->show_campaigns();
57
- }
58
- } else {
59
- $this->show_no_campaigns();
60
- }
61
-
62
- if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
63
- include CE4WP_PLUGIN_DIR . 'src/views/admin-dashboard-widget/divider.php';
64
- $this->show_woo_commerce();
65
- }
66
- } catch ( CreativeMailException $exception ) {
67
- RaygunManager::get_instance()->exception_handler($exception);
68
- $this->show_exception();
69
- }
70
- }
71
-
72
- private function show_no_account()
73
- {
74
- include CE4WP_PLUGIN_DIR . 'src/views/admin-dashboard-widget/no-ce-account.php';
75
- }
76
-
77
- private function show_no_campaigns()
78
- {
79
- include CE4WP_PLUGIN_DIR . 'src/views/admin-dashboard-widget/no-campaign.php';
80
- }
81
-
82
- private function show_campaigns()
83
- {
84
- $ce_most_recent_campaigns = $this->creative_mail_client->get_most_recent_campaigns();
85
- include CE4WP_PLUGIN_DIR . 'src/views/admin-dashboard-widget/most-recent-campaigns.php';
86
- }
87
-
88
- private function show_woo_commerce()
89
- {
90
- $number_of_possible_notifications = 0;
91
- $number_of_active_notifications = 0;
92
-
93
- try {
94
- $email_manager = CreativeMail::get_instance()->get_email_manager();
95
- $supported_email_notifications = $email_manager->get_managed_email_notifications();
96
- $active_email_notifications = array_filter($supported_email_notifications, function ($email_notification) {
97
- return $email_notification->active === true;
98
- });
99
-
100
- $number_of_active_notifications = count($active_email_notifications);
101
-
102
- if ($number_of_active_notifications > 0) {
103
- $number_of_possible_notifications = count($email_manager->get_valid_email_notification_names());
104
- include CE4WP_PLUGIN_DIR . 'src/views/admin-dashboard-widget/woocommerce.php';
105
- } else {
106
- include CE4WP_PLUGIN_DIR . 'src/views/admin-dashboard-widget/no-woocommerce.php';
107
- }
108
- }
109
- catch(Exception $ex) { }
110
- }
111
-
112
- private function show_exception()
113
- {
114
- include CE4WP_PLUGIN_DIR . 'src/views/admin-dashboard-widget/exception.php';
115
- }
116
  }
6
  use CreativeMail\CreativeMail;
7
  use CreativeMail\Exceptions\CreativeMailException;
8
  use CreativeMail\Helpers\OptionsHelper;
 
9
  use CreativeMail\Managers\RaygunManager;
10
  use Exception;
11
 
12
+ class DashboardWidgetModule {
13
+
14
+
15
+ private $creative_mail_client;
16
+
17
+ /**
18
+ * DashboardWidgetModule constructor.
19
+ */
20
+ public function __construct() {
21
+ $this->creative_mail_client = new CreativeMailClient();
22
+ }
23
+
24
+ /**
25
+ * Shows the Dashboard Widget.
26
+ */
27
+ public function show() {
28
+ wp_enqueue_script( 'ce4wp_dashboard_widget', CE4WP_PLUGIN_URL . 'assets/js/dashboard.js', array(), CE4WP_PLUGIN_VERSION, true );
29
+ wp_localize_script( 'ce4wp_dashboard_widget', 'ce4wp_data', array(
30
+ 'url' => admin_url( 'admin-ajax.php' ),
31
+ 'nonce' => wp_create_nonce( 'ajax-nonce' ),
32
+ ) );
33
+
34
+ $ce_has_account = OptionsHelper::get_instance_id() != null;
35
+ if ( ! $ce_has_account ) {
36
+ $this->show_no_account();
37
+ return;
38
+ }
39
+
40
+ try {
41
+ $ce_account_status = $this->creative_mail_client->get_account_status();
42
+
43
+ if ( ! empty($ce_account_status) ) {
44
+ $ce_has_finished_onboarding = $ce_account_status['has_finished_onboarding'];
45
+ if ( ! $ce_has_finished_onboarding ) {
46
+ $this->show_no_account();
47
+ return;
48
+ }
49
+ $ce_has_campaign = $ce_account_status['has_campaigns'];
50
+ if ( ! $ce_has_campaign ) {
51
+ $this->show_no_campaigns();
52
+ } else {
53
+ $this->show_campaigns();
54
+ }
55
+ } else {
56
+ $this->show_no_campaigns();
57
+ }
58
+
59
+ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ), true ) ) {
60
+ include CE4WP_PLUGIN_DIR . 'src/views/admin-dashboard-widget/divider.php';
61
+ $this->show_woo_commerce();
62
+ }
63
+ } catch ( CreativeMailException $exception ) {
64
+ RaygunManager::get_instance()->exception_handler($exception);
65
+ $this->show_exception();
66
+ }
67
+ }
68
+
69
+ private function show_no_account() {
70
+ include CE4WP_PLUGIN_DIR . 'src/views/admin-dashboard-widget/no-ce-account.php';
71
+ }
72
+
73
+ private function show_no_campaigns() {
74
+ include CE4WP_PLUGIN_DIR . 'src/views/admin-dashboard-widget/no-campaign.php';
75
+ }
76
+
77
+ private function show_campaigns() {
78
+ $ce_most_recent_campaigns = $this->creative_mail_client->get_most_recent_campaigns();
79
+ include CE4WP_PLUGIN_DIR . 'src/views/admin-dashboard-widget/most-recent-campaigns.php';
80
+ }
81
+
82
+ private function show_woo_commerce() {
83
+ $number_of_possible_notifications = 0;
84
+ $number_of_active_notifications = 0;
85
+
86
+ try {
87
+ $email_manager = CreativeMail::get_instance()->get_email_manager();
88
+ $supported_email_notifications = $email_manager->get_managed_email_notifications();
89
+ $active_email_notifications = array_filter($supported_email_notifications, function ( $email_notification ) {
90
+ return true === $email_notification->active;
91
+ });
92
+
93
+ $number_of_active_notifications = count($active_email_notifications);
94
+
95
+ if ( $number_of_active_notifications > 0 ) {
96
+ $number_of_possible_notifications = count($email_manager->get_valid_email_notification_names());
97
+ include CE4WP_PLUGIN_DIR . 'src/views/admin-dashboard-widget/woocommerce.php';
98
+ } else {
99
+ include CE4WP_PLUGIN_DIR . 'src/views/admin-dashboard-widget/no-woocommerce.php';
100
+ }
101
+ } catch ( Exception $ex ) {
102
+ RaygunManager::get_instance()->exception_handler($ex);
103
+ }
104
+ }
105
+
106
+ private function show_exception() {
107
+ include CE4WP_PLUGIN_DIR . 'src/views/admin-dashboard-widget/exception.php';
108
+ }
 
 
 
 
 
 
109
  }
src/Modules/FeedbackNoticeModule.php CHANGED
@@ -8,83 +8,82 @@ use CreativeMail\Helpers\OptionsHelper;
8
  use CreativeMail\Managers\RaygunManager;
9
  use Exception;
10
 
11
- class FeedbackNoticeModule
12
- {
13
-
14
- private $integration_manager;
15
-
16
- public function __construct()
17
- {
18
- $this->integration_manager = CreativeMail::get_instance()->get_integration_manager();
19
- }
20
-
21
- public function display()
22
- {
23
- wp_register_style('ce4wp_feedback_notice_css', CE4WP_PLUGIN_URL . 'assets/css/feedback_notice.css', [], CE4WP_PLUGIN_VERSION);
24
- wp_enqueue_style('ce4wp_feedback_notice_css');
25
- wp_enqueue_script('ce4wp_feedback_notice', CE4WP_PLUGIN_URL.'assets/js/feedback_notice.js', [],CE4WP_PLUGIN_VERSION,true);
26
-
27
- $admin_url = admin_url('admin-ajax.php');
28
- $nonce = wp_create_nonce('ajax-nonce');
29
-
30
- wp_localize_script('ce4wp_feedback_notice', 'ce4wp_data', array(
31
- 'url' => $admin_url,
32
- 'nonce' => $nonce,
33
- 'hide_banner_url' => get_rest_url( null, 'creativemail/v1/hide_banner?banner=' ),
34
- ));
35
- wp_enqueue_script('ce4wp_dashboard', CE4WP_PLUGIN_URL.'assets/js/dashboard.js', [],CE4WP_PLUGIN_VERSION);
36
- wp_localize_script('ce4wp_dashboard', 'ce4wp_data', array(
37
- 'url' => $admin_url,
38
- 'nonce' => $nonce,
39
- 'hide_banner_url' => get_rest_url( null, 'creativemail/v1/hide_banner?banner=' ),
40
- ));
41
-
42
- $ce_sync_enabled = $this->integration_manager->is_plugin_active('jetpack') || $this->integration_manager->is_plugin_active('jetpack-beta');
43
- if ( !$ce_sync_enabled ) {
44
- if (OptionsHelper::get_hide_banner('feedback_notice_sync_disabled')) {
45
- return;
46
- }
47
-
48
- include CE4WP_PLUGIN_DIR . 'src/views/admin-feedback-notice/sync-disabled.php';
49
- return;
50
- }
51
-
52
- try {
53
- $contact_metrics = $this->get_contact_metrics();
54
- $ce_number_of_contacts = $contact_metrics['number_of_subscribed_contacts'];
55
-
56
- if ( $ce_number_of_contacts < 10 ) {
57
- if (OptionsHelper::get_hide_banner('feedback_notice_few_contacts')) {
58
- return;
59
- }
60
-
61
- include CE4WP_PLUGIN_DIR . 'src/views/admin-feedback-notice/few-contacts.php';
62
- } else {
63
- if (OptionsHelper::get_hide_banner('feedback_notice_many_contacts')) {
64
- return;
65
- }
66
-
67
- include CE4WP_PLUGIN_DIR . 'src/views/admin-feedback-notice/many-contacts.php';
68
- }
69
- } catch (Exception $exception) {
70
- RaygunManager::get_instance()->exception_handler($exception);
71
- }
72
- }
73
-
74
- private function get_contact_metrics()
75
- {
76
- $response = wp_remote_get( EnvironmentHelper::get_app_gateway_url() . 'wordpress/v1.0/contacts/contact-metrics', [
77
- 'headers' => [
78
- 'x-api-key' => OptionsHelper::get_instance_api_key(),
79
- 'x-account-id' => OptionsHelper::get_connected_account_id()
80
- ],
81
- ] );
82
-
83
- if ( is_wp_error( $response ) ) {
84
- throw new Exception( 'Could not get contact metrics' );
85
- }
86
-
87
- return json_decode( $response['body'], true );
88
- }
89
 
90
  }
8
  use CreativeMail\Managers\RaygunManager;
9
  use Exception;
10
 
11
+ class FeedbackNoticeModule {
12
+
13
+
14
+ private $integration_manager;
15
+
16
+ public function __construct() {
17
+ $this->integration_manager = CreativeMail::get_instance()->get_integration_manager();
18
+ }
19
+
20
+ public function display() {
21
+ wp_register_style('ce4wp_feedback_notice_css', CE4WP_PLUGIN_URL . 'assets/css/feedback_notice.css', array(), CE4WP_PLUGIN_VERSION);
22
+ wp_enqueue_style('ce4wp_feedback_notice_css');
23
+ wp_enqueue_script('ce4wp_feedback_notice', CE4WP_PLUGIN_URL . 'assets/js/feedback_notice.js', array(), CE4WP_PLUGIN_VERSION, true);
24
+
25
+ $admin_url = admin_url('admin-ajax.php');
26
+ $nonce = wp_create_nonce('ajax-nonce');
27
+
28
+ wp_localize_script('ce4wp_feedback_notice', 'ce4wp_data', array(
29
+ 'url' => $admin_url,
30
+ 'nonce' => $nonce,
31
+ 'hide_banner_url' => get_rest_url( null, 'creativemail/v1/hide_banner?banner=' ),
32
+ ));
33
+ wp_enqueue_script('ce4wp_dashboard', CE4WP_PLUGIN_URL . 'assets/js/dashboard.js', array(), CE4WP_PLUGIN_VERSION, true);
34
+ wp_localize_script('ce4wp_dashboard', 'ce4wp_data', array(
35
+ 'url' => $admin_url,
36
+ 'nonce' => $nonce,
37
+ 'hide_banner_url' => get_rest_url( null, 'creativemail/v1/hide_banner?banner=' ),
38
+ ));
39
+
40
+ $ce_sync_enabled = $this->integration_manager->is_plugin_active('jetpack') || $this->integration_manager->is_plugin_active('jetpack-beta');
41
+ if ( ! $ce_sync_enabled ) {
42
+ if ( OptionsHelper::get_hide_banner('feedback_notice_sync_disabled') ) {
43
+ return;
44
+ }
45
+
46
+ include CE4WP_PLUGIN_DIR . 'src/views/admin-feedback-notice/sync-disabled.php';
47
+ return;
48
+ }
49
+
50
+ try {
51
+ $contact_metrics = $this->get_contact_metrics();
52
+ $ce_number_of_contacts = $contact_metrics['number_of_subscribed_contacts'];
53
+
54
+ if ( $ce_number_of_contacts < 10 ) {
55
+ if ( OptionsHelper::get_hide_banner('feedback_notice_few_contacts') ) {
56
+ return;
57
+ }
58
+
59
+ include CE4WP_PLUGIN_DIR . 'src/views/admin-feedback-notice/few-contacts.php';
60
+ } else {
61
+ if ( OptionsHelper::get_hide_banner('feedback_notice_many_contacts') ) {
62
+ return;
63
+ }
64
+
65
+ include CE4WP_PLUGIN_DIR . 'src/views/admin-feedback-notice/many-contacts.php';
66
+ }
67
+ } catch ( Exception $exception ) {
68
+ RaygunManager::get_instance()->exception_handler($exception);
69
+ }
70
+ }
71
+
72
+ private function get_contact_metrics() {
73
+ $response = wp_remote_get(
74
+ EnvironmentHelper::get_app_gateway_url('wordpress/v1.0/contacts/contact-metrics'),
75
+ array(
76
+ 'headers' => array(
77
+ 'x-api-key' => OptionsHelper::get_instance_api_key(),
78
+ 'x-account-id' => OptionsHelper::get_connected_account_id(),
79
+ ),
80
+ ) );
81
+
82
+ if ( is_wp_error( $response ) ) {
83
+ throw new Exception( 'Could not get contact metrics' );
84
+ }
85
+
86
+ return json_decode( $response['body'], true );
87
+ }
 
88
 
89
  }
src/Modules/WooCommerce/Emails/AbandonedCartEmail.php CHANGED
@@ -5,26 +5,24 @@ use WC_Email;
5
  use WC_Order;
6
 
7
  class AbandonedCartEmail extends WC_Email {
8
- /**
9
- * Constructor.
10
- */
11
- public function __construct( ) {
12
- $this->id = 'cart_abandoned_ce4wp';
13
- $this->title = __( 'Abandoned cart', 'ce4wp' );
14
- $this->description = __( 'Send customers a reminder after they abandoned their shopping cart', 'ce4wp' );
15
- $this->customer_email = true;
16
- $this->enabled = 'no';
17
 
18
- // We want all the parent's methods, with none of its properties, so call its parent's constructor, rather than my parent constructor.
19
- parent::__construct();
20
- }
21
 
22
- /**
23
- * Triggers the email.
24
- *
25
- * @param WC_Order $order The order.
26
- */
27
- public function trigger( $order ) {
28
- return;
29
- }
30
  }
5
  use WC_Order;
6
 
7
  class AbandonedCartEmail extends WC_Email {
8
+ /**
9
+ * Constructor.
10
+ */
11
+ public function __construct() {
12
+ $this->id = 'cart_abandoned_ce4wp';
13
+ $this->title = __( 'Abandoned cart', 'creative-mail-by-constant-contact' );
14
+ $this->description = __( 'Send customers a reminder after they abandoned their shopping cart', 'creative-mail-by-constant-contact' );
15
+ $this->customer_email = true;
16
+ $this->enabled = 'no';
17
 
18
+ // We want all the parent's methods, with none of its properties, so call its parent's constructor, rather than my parent constructor.
19
+ parent::__construct();
20
+ }
21
 
22
+ /**
23
+ * Triggers the email.
24
+ *
25
+ * @param WC_Order $order The order.
26
+ */
27
+ public function trigger( $order ) {}
 
 
28
  }
src/Modules/WooCommerce/Models/WCInformationModel.php CHANGED
@@ -1,24 +1,24 @@
1
  <?php
2
 
3
  namespace CreativeMail\Modules\WooCommerce\Models;
 
4
  use CreativeMail\CreativeMail;
5
 
6
- class WCInformationModel
7
- {
8
- public $wc_installed;
9
- public $wc_version;
10
- public $plugin_version;
11
- public $perma_links;
12
 
13
- function __construct()
14
- {
15
- $this->wc_installed = in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')));
16
- if ($this->wc_installed) {
17
- global $woocommerce;
18
- $this->wc_version = $woocommerce->version;
19
- }
20
 
21
- $this->plugin_version = CE4WP_PLUGIN_VERSION;
22
- $this->perma_links = CreativeMail::get_instance()->get_integration_manager()->get_permalinks_enabled();
23
- }
24
  }
1
  <?php
2
 
3
  namespace CreativeMail\Modules\WooCommerce\Models;
4
+
5
  use CreativeMail\CreativeMail;
6
 
7
+ class WCInformationModel {
8
+
9
+ public $wc_installed;
10
+ public $wc_version;
11
+ public $plugin_version;
12
+ public $perma_links;
13
 
14
+ public function __construct() {
15
+ $this->wc_installed = in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')), true);
16
+ if ( $this->wc_installed ) {
17
+ global $woocommerce;
18
+ $this->wc_version = $woocommerce->version;
19
+ }
 
20
 
21
+ $this->plugin_version = CE4WP_PLUGIN_VERSION;
22
+ $this->perma_links = CreativeMail::get_instance()->get_integration_manager()->get_permalinks_enabled();
23
+ }
24
  }
src/Modules/WooCommerce/Models/WCProductModel.php CHANGED
@@ -1,44 +1,43 @@
1
- <?php
2
 
3
  namespace CreativeMail\Modules\WooCommerce\Models;
4
 
5
- class WCProductModel
6
- {
7
- public $id;
8
- public $name;
9
- public $sku;
10
- public $slug;
11
- public $description;
12
- public $short_description;
13
- public $price;
14
- public $regular_price;
15
- public $sale_price;
16
- public $date_created;
17
- public $date_modified;
18
- public $status;
19
- public $stock_status;
20
- public $url;
21
- public $image_url;
22
 
23
- function __construct($data)
24
- {
25
- $this->id = $data['id'];
26
- $this->name = $data['name'];
27
- $this->sku = $data['sku'];
28
- $this->slug = $data['slug'];
29
- $this->description = $data['description'];
30
- $this->short_description = $data['short_description'];
31
- $this->price = $data['price'];
32
- $this->regular_price = $data['regular_price'];
33
- $this->sale_price = $data['sale_price'];
34
- $this->date_created = $data['date_created'];
35
- $this->date_modified = $data['date_modified'];
36
- $this->status = $data['status'];
37
- $this->stock_status = $data['stock_status'];
38
- $this->url = get_permalink($data['id']);
39
- $this->image_url = null;
40
- if ($data['image_id'] !== "") {
41
- $this->image_url = wp_get_attachment_url($data['image_id']);
42
- }
43
- }
44
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
 
3
  namespace CreativeMail\Modules\WooCommerce\Models;
4
 
5
+ class WCProductModel {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ public $id;
8
+ public $name;
9
+ public $sku;
10
+ public $slug;
11
+ public $description;
12
+ public $short_description;
13
+ public $price;
14
+ public $regular_price;
15
+ public $sale_price;
16
+ public $date_created;
17
+ public $date_modified;
18
+ public $status;
19
+ public $stock_status;
20
+ public $url;
21
+ public $image_url;
22
+
23
+ public function __construct( $data ) {
24
+ $this->id = $data['id'];
25
+ $this->name = $data['name'];
26
+ $this->sku = $data['sku'];
27
+ $this->slug = $data['slug'];
28
+ $this->description = $data['description'];
29
+ $this->short_description = $data['short_description'];
30
+ $this->price = $data['price'];
31
+ $this->regular_price = $data['regular_price'];
32
+ $this->sale_price = $data['sale_price'];
33
+ $this->date_created = $data['date_created'];
34
+ $this->date_modified = $data['date_modified'];
35
+ $this->status = $data['status'];
36
+ $this->stock_status = $data['stock_status'];
37
+ $this->url = get_permalink($data['id']);
38
+ $this->image_url = null;
39
+ if ( '' !== $data['image_id'] ) {
40
+ $this->image_url = wp_get_attachment_url($data['image_id']);
41
+ }
42
+ }
43
+ }
src/Modules/WooCommerce/Models/WCStoreInformation.php CHANGED
@@ -6,34 +6,33 @@ namespace CreativeMail\Modules\WooCommerce\Models;
6
  use CreativeMail\Helpers\OptionsHelper;
7
  use WC_Countries;
8
 
9
- class WCStoreInformation
10
- {
11
- public $address1;
12
- public $address2;
13
- public $city;
14
- public $postcode;
15
- public $state;
16
- public $country;
17
- public $country_code;
18
- public $currency;
19
- public $currency_symbol;
20
- public $email_from;
21
- public $email_name;
22
 
23
- function __construct()
24
- {
25
- if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
26
- $this->address1 = WC()->countries->get_base_address();
27
- $this->address2 = WC()->countries->get_base_address_2();
28
- $this->city = WC()->countries->get_base_city();
29
- $this->postcode = WC()->countries->get_base_postcode();
30
- $this->state = WC()->countries->get_base_state();
31
- $this->country = WC()->countries->get_countries()[WC()->countries->get_base_country()];
32
- $this->country_code = WC()->countries->get_base_country();
33
- $this->currency_symbol = get_woocommerce_currency_symbol();
34
- $this->currency = get_woocommerce_currency();
35
- $this->email_from = apply_filters('woocommerce_email_from_address', get_option('woocommerce_email_from_address'));
36
- $this->email_name = apply_filters('woocommerce_email_from_name', get_option('woocommerce_email_from_name'));
37
- }
38
- }
 
 
 
 
 
 
 
 
 
 
 
39
  }
6
  use CreativeMail\Helpers\OptionsHelper;
7
  use WC_Countries;
8
 
9
+ class WCStoreInformation {
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
+ public $address1;
12
+ public $address2;
13
+ public $city;
14
+ public $postcode;
15
+ public $state;
16
+ public $country;
17
+ public $country_code;
18
+ public $currency;
19
+ public $currency_symbol;
20
+ public $email_from;
21
+ public $email_name;
22
+
23
+ public function __construct() {
24
+ if ( in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')), true) ) {
25
+ $this->address1 = WC()->countries->get_base_address();
26
+ $this->address2 = WC()->countries->get_base_address_2();
27
+ $this->city = WC()->countries->get_base_city();
28
+ $this->postcode = WC()->countries->get_base_postcode();
29
+ $this->state = WC()->countries->get_base_state();
30
+ $this->country = WC()->countries->get_countries()[ WC()->countries->get_base_country() ];
31
+ $this->country_code = WC()->countries->get_base_country();
32
+ $this->currency_symbol = get_woocommerce_currency_symbol();
33
+ $this->currency = get_woocommerce_currency();
34
+ $this->email_from = apply_filters('woocommerce_email_from_address', get_option('woocommerce_email_from_address'));
35
+ $this->email_name = apply_filters('woocommerce_email_from_name', get_option('woocommerce_email_from_name'));
36
+ }
37
+ }
38
  }
src/blocks/LoadBlock.php CHANGED
@@ -4,30 +4,42 @@
4
  * Class MyPlugin_Blocks
5
  */
6
  namespace CreativeMail\Blocks;
 
7
  class LoadBlock {
8
- private static $instance;
 
9
  public function __construct() {
10
- }
 
 
 
 
 
 
11
  public function add_hooks() {
12
- add_action( 'init', array($this, 'create_blocks') );
13
  }
14
 
15
- /**
16
- * Registers the block using the metadata loaded from the `block.json` file.
17
- * Behind the scenes, it registers also all assets so they can be enqueued
18
- * through the block editor in the corresponding context
19
- */
20
- function create_blocks() {
21
- register_block_type_from_metadata(__DIR__ . '/subscribe' );
22
- }
23
 
24
- public static function get_instance()
25
- {
 
 
 
 
26
 
27
- if (self::$instance === null) {
28
- self::$instance = new LoadBlock();
29
- }
30
 
31
- return self::$instance;
32
- }
33
  }
4
  * Class MyPlugin_Blocks
5
  */
6
  namespace CreativeMail\Blocks;
7
+
8
  class LoadBlock {
9
+ private static $instance;
10
+
11
  public function __construct() {
12
+ }
13
+
14
+ /**
15
+ * Add the blocks hooks.
16
+ *
17
+ * @return void
18
+ */
19
  public function add_hooks() {
20
+ add_action( 'init', array( $this, 'create_blocks' ) );
21
  }
22
 
23
+ /**
24
+ * Registers the block using the metadata loaded from the `block.json` file.
25
+ * Behind the scenes, it registers also all assets, so they can be enqueued
26
+ * through the block editor in the corresponding context
27
+ */
28
+ public function create_blocks() {
29
+ register_block_type_from_metadata(__DIR__ . '/subscribe' );
30
+ }
31
 
32
+ /**
33
+ * Returns the instance of the LoadBlock class.
34
+ *
35
+ * @return LoadBlock
36
+ */
37
+ public static function get_instance() {
38
 
39
+ if ( null === self::$instance ) {
40
+ self::$instance = new LoadBlock();
41
+ }
42
 
43
+ return self::$instance;
44
+ }
45
  }
src/blocks/subscribe/deprecated/deprecated_save.js CHANGED
@@ -16,7 +16,7 @@ export function deprecated_4_0({ attributes, className }) {
16
  tagName="h2"
17
  value={attributes.title}
18
  />
19
- <p className="subTitle">{__(attributes.onSubmission, "cewp4")}</p>
20
  </div>
21
  <form className="cm-contact-form" name="contact-form">
22
  <input
@@ -98,7 +98,8 @@ export function deprecated_4_0({ attributes, className }) {
98
  name="telephone"
99
  type="tel"
100
  pattern="[+]?[0-9\(\)\s+-]{5,20}"
101
- oninvalid={`setCustomValidity('${__("Please enter a valid phone number", "cewp4")}')`}
 
102
  oninput="setCustomValidity('')"
103
  required={attributes.displayFirstName === FIELD_SETTING.REQUIRED}
104
  ></input>
@@ -116,7 +117,8 @@ export function deprecated_4_0({ attributes, className }) {
116
  className="email"
117
  name="email"
118
  type="email"
119
- oninvalid={`setCustomValidity('${__("Please enter a valid email address", "cewp4")}')`}
 
120
  oninput="setCustomValidity('')"
121
  required
122
  ></input>
@@ -130,8 +132,8 @@ export function deprecated_4_0({ attributes, className }) {
130
  checked
131
  ></input>
132
  {__(
133
- "By submitting your information, you are granting us permission to email you. You may unsubscribe at any time.",
134
- "cewp4"
135
  )}
136
  </span>
137
  )}
@@ -147,12 +149,12 @@ export function deprecated_4_0({ attributes, className }) {
147
  htmlFor={`consent_check_${attributes.blockId}`}
148
  className="disclaimer"
149
  >
150
- {__("Can we send you an email from time to time?", "cewp4")}
151
  </label>
152
  </span>
153
  )}
154
  <button className="wp-block-button__link submit-button" type="submit">
155
- {__("Subscribe", "cewp4")}
156
  </button>
157
  </form>
158
  </div>
16
  tagName="h2"
17
  value={attributes.title}
18
  />
19
+ <p className="subTitle">{attributes.onSubmission}</p>
20
  </div>
21
  <form className="cm-contact-form" name="contact-form">
22
  <input
98
  name="telephone"
99
  type="tel"
100
  pattern="[+]?[0-9\(\)\s+-]{5,20}"
101
+ oninvalid={`setCustomValidity('${__('Please enter a valid phone number',
102
+ 'creative-mail-by-constant-contact')}')`}
103
  oninput="setCustomValidity('')"
104
  required={attributes.displayFirstName === FIELD_SETTING.REQUIRED}
105
  ></input>
117
  className="email"
118
  name="email"
119
  type="email"
120
+ oninvalid={`setCustomValidity('${__( 'Please enter a valid email address',
121
+ 'creative-mail-by-constant-contact')}')`}
122
  oninput="setCustomValidity('')"
123
  required
124
  ></input>
132
  checked
133
  ></input>
134
  {__(
135
+ 'By submitting your information, you are granting us permission to email you. You may unsubscribe at any time.',
136
+ 'creative-mail-by-constant-contact'
137
  )}
138
  </span>
139
  )}
149
  htmlFor={`consent_check_${attributes.blockId}`}
150
  className="disclaimer"
151
  >
152
+ {__('Can we send you an email from time to time?', 'creative-mail-by-constant-contact')}
153
  </label>
154
  </span>
155
  )}
156
  <button className="wp-block-button__link submit-button" type="submit">
157
+ {__('Subscribe', 'creative-mail-by-constant-contact')}
158
  </button>
159
  </form>
160
  </div>
src/blocks/subscribe/edit.js CHANGED
@@ -1,478 +1,478 @@
1
  import { __ } from "@wordpress/i18n";
2
  import {
3
- BlockControls,
4
- InspectorControls,
5
- RichText,
6
  } from "@wordpress/block-editor";
7
  import {
8
- SelectControl,
9
- TextareaControl,
10
- TextControl,
11
- Panel,
12
- PanelBody,
13
- PanelRow,
14
- ExternalLink,
15
- Dashicon,
16
  } from "@wordpress/components";
17
 
18
  import "./editor.scss";
19
 
20
  export const FIELD_SETTING = {
21
- NOTSHOW: "notshow",
22
- OPTIONAL: "optional",
23
- REQUIRED: "required",
24
  };
25
 
26
  export const ON_SUBMIT_SETTING = {
27
- SUMMARY: "summary",
28
- MESSAGE: "message",
29
- REDIRECT: "redirect",
30
  };
31
 
32
  const useWPAction = (action, nonce) => {
33
- const [data, setData] = React.useState([]);
34
- const [loading, setLoading] = React.useState(false);
35
- const [hasLoaded, setHasLoaded] = React.useState(false);
36
 
37
- React.useEffect(() => {
38
- if (loading || hasLoaded) return;
39
- setLoading(true);
40
- jQuery
41
- .post(ce4wp_form_submit_data?.url, {
42
- action: action,
43
- nonce: nonce,
44
- })
45
- .done((response) => {
46
- setLoading(false);
47
- setHasLoaded(true);
48
- if (response?.data != null) {
49
- setData(response.data);
50
- }
51
- });
52
- }, [loading, hasLoaded, data]);
53
 
54
- return {
55
- data,
56
- loading,
57
- hasLoaded,
58
- };
59
  };
60
 
61
  const useCustomLists = () => {
62
- const { data, loading, hasLoaded } = useWPAction(
63
- "ce4wp_get_all_custom_lists",
64
- ce4wp_form_submit_data?.listNonce
65
- );
66
 
67
- let customLists = [];
68
- if (data != null && data.length != undefined) {
69
- customLists = data.map((list) => ({
70
- label: list.name,
71
- value: list.id,
72
- }));
73
- }
74
- return {
75
- customLists,
76
- loading,
77
- hasLoaded,
78
- };
79
  };
80
 
81
  const useIsCreativeMailActivated = () => {
82
- const { data, loading, hasLoaded } = useWPAction(
83
- "ce4wp_creative_email_activated",
84
- ce4wp_form_submit_data?.activatedNonce
85
- );
86
- return {
87
- creativeEmailIsActivated: data,
88
- loading,
89
- hasLoaded,
90
- };
91
  };
92
 
93
  export default function Edit({
94
- attributes,
95
- setAttributes,
96
- className,
97
- clientId,
98
  }) {
99
- const { blockId } = attributes;
100
- if (!blockId) {
101
- setAttributes({ blockId: clientId });
102
- }
103
- const { customLists } = useCustomLists();
104
- const { creativeEmailIsActivated } = useIsCreativeMailActivated();
105
- return (
106
- <div className={`wp-block-ce4wp-subscribe ${className ? className : ""}`}>
107
- <BlockControls key="setting">
108
- <InspectorControls key="setting">
109
- <Panel header="Settings">
110
- <PanelBody title="Contact Segmentation" initialOpen={true}>
111
- <PanelRow className="no-flex">
112
- <fieldset>
113
- <i className="subTitle sub-header">
114
- {__(
115
- "Automatically assign a new contact to a list when they subscribe",
116
- "ce4wp"
117
- )}
118
- <br />
119
- <ExternalLink
120
- onClick={() =>
121
- ce4wpNavigateToDashboard(
122
- this,
123
- "fbcd9606-288a-4d82-be7c-449eaf5a3792",
124
- { source: "ce4wp_form_menu" },
125
- ce4wpDashboardStartCallback,
126
- ce4wpDashboardFinishCallback
127
- )
128
- }
129
- >
130
  <span
131
- id="ce4wp-manage-lists"
132
- data-link_reference="836b20fc-9ff1-41b2-912b-a8646caf05a4"
133
- >
134
  {__("Manage your lists", "ce4wp")}
135
  </span>
136
- </ExternalLink>
137
- </i>
138
- <br />
139
- <br />
140
- <SelectControl
141
- label="list"
142
- value={attributes.customList}
143
- options={[
144
- {
145
- label: __("Don't assign to a list", "cewp4"),
146
- value: "",
147
- },
148
- ...customLists,
149
- ]}
150
- onChange={(customList) =>
151
- setAttributes({
152
- customList,
153
- })
154
- }
155
- />
156
- </fieldset>
157
- </PanelRow>
158
- </PanelBody>
159
- <PanelBody title="On submission" initialOpen={true}>
160
- <PanelRow>
161
- <fieldset>
162
- <SelectControl
163
- label="On submission"
164
- value={attributes.onSubmissionSetting}
165
- options={[
166
- {
167
- label: "Show a custom text message",
168
- value: ON_SUBMIT_SETTING.MESSAGE,
169
- },
170
- {
171
- label: "Show a summary of submitted fields",
172
- value: ON_SUBMIT_SETTING.SUMMARY,
173
- },
174
- {
175
- label: "Redirect",
176
- value: ON_SUBMIT_SETTING.REDIRECT,
177
- },
178
- ]}
179
- onChange={(onSubmissionSetting) =>
180
- setAttributes({ onSubmissionSetting })
181
- }
182
- />
183
- </fieldset>
184
- </PanelRow>
185
- {attributes.onSubmissionSetting === ON_SUBMIT_SETTING.MESSAGE && (
186
- <PanelRow>
187
- <fieldset>
188
- <TextareaControl
189
- label="Message text"
190
- value={attributes.onSubmission}
191
- onChange={(onSubmission) =>
192
- setAttributes({ onSubmission })
193
- }
194
- />
195
- </fieldset>
196
- </PanelRow>
197
- )}
198
- {attributes.onSubmissionSetting === ON_SUBMIT_SETTING.REDIRECT && (
199
- <PanelRow>
200
- <fieldset>
201
- <TextControl
202
- label="Redirect link"
203
- value={attributes.redirectLink}
204
- onChange={(redirectLink) =>
205
- setAttributes({ redirectLink })
206
- }
207
- />
208
- </fieldset>
209
- </PanelRow>
210
- )}
211
- </PanelBody>
212
- <PanelBody title="Disclaimer settings" initialOpen={true}>
213
- <PanelRow className="no-flex">
214
- <fieldset>
215
- <SelectControl
216
- label="Permission to mail"
217
- value={attributes.emailPermission}
218
- options={[
219
- {
220
- label: "message",
221
- value: "message",
222
- },
223
- {
224
- label: "checkbox",
225
- value: "checkbox",
226
- },
227
- ]}
228
- onChange={(emailPermission) =>
229
- setAttributes({
230
- ...attributes,
231
- emailPermission: emailPermission,
232
- })
233
- }
234
- />
235
- </fieldset>
236
- </PanelRow>
237
- </PanelBody>
238
- <PanelBody title="Field settings" initialOpen={true}>
239
- <PanelRow className="no-flex">
240
- <fieldset>
241
- <SelectControl
242
- label="First name field"
243
- value={attributes.displayFirstName}
244
- options={[
245
- {
246
- label: "Do not show",
247
- value: FIELD_SETTING.NOTSHOW,
248
- },
249
- {
250
- label: "Optional",
251
- value: FIELD_SETTING.OPTIONAL,
252
- },
253
- {
254
- label: "Required",
255
- value: FIELD_SETTING.REQUIRED,
256
- },
257
- ]}
258
- onChange={(displayFirstName) =>
259
- setAttributes({
260
- displayFirstName: displayFirstName,
261
- })
262
- }
263
- />
264
- </fieldset>
265
- </PanelRow>
266
- <PanelRow className="no-flex">
267
- <fieldset>
268
- <SelectControl
269
- label="Last name field"
270
- value={attributes.displayLastName}
271
- options={[
272
- {
273
- label: "Do not show",
274
- value: FIELD_SETTING.NOTSHOW,
275
- },
276
- {
277
- label: "Optional",
278
- value: FIELD_SETTING.OPTIONAL,
279
- },
280
- {
281
- label: "Required",
282
- value: FIELD_SETTING.REQUIRED,
283
- },
284
- ]}
285
- onChange={(displayLastName) =>
286
- setAttributes({
287
- displayLastName: displayLastName,
288
- })
289
- }
290
- />
291
- </fieldset>
292
- </PanelRow>
293
- <PanelRow className="no-flex">
294
- <fieldset>
295
- <SelectControl
296
- label="Telephone field"
297
- value={attributes.displayTelephone}
298
- options={[
299
- {
300
- label: "Do not show",
301
- value: FIELD_SETTING.NOTSHOW,
302
- },
303
- {
304
- label: "Optional",
305
- value: FIELD_SETTING.OPTIONAL,
306
- },
307
- {
308
- label: "Required",
309
- value: FIELD_SETTING.REQUIRED,
310
- },
311
- ]}
312
- onChange={(displayTelephone) =>
313
- setAttributes({
314
- displayTelephone: displayTelephone,
315
- })
316
- }
317
- />
318
- </fieldset>
319
- </PanelRow>
320
- </PanelBody>
321
- </Panel>
322
- </InspectorControls>
323
- </BlockControls>
324
- <form name="contact-form">
325
- <RichText
326
- tagName="h2"
327
- onChange={(title) => {
328
- setAttributes({ title: title });
329
- }}
330
- value={attributes.title}
331
- />
332
- <RichText
333
- tagName="p"
334
- className="subTitle"
335
- onChange={(subTitle) => {
336
- setAttributes({ subTitle: subTitle });
337
- }}
338
- value={attributes.subTitle}
339
- />
340
- {creativeEmailIsActivated === false && (
341
- <div
342
- className="ce4wp-inline-notification ce4wp-inline-warning ce4wp-banner-clickable"
343
- onClick={() =>
344
- ce4wpNavigateToDashboard(
345
- this,
346
- "d25f690a-217a-4d68-9c58-8693965d4673",
347
- { source: "ce4wp_form_menu" },
348
- ce4wpDashboardStartCallback,
349
- ce4wpDashboardFinishCallback
350
- )
351
- }
352
- >
353
- <Dashicon className="ce4wp-inline-warning-icon" icon="warning" />
354
- <div className="ce4wp-inline-warning-text">
355
- {__(
356
- "Set up Creative Mail before you use this form on your website."
357
- )}
358
- </div>
359
- <Dashicon
360
- className="ce4wp-inline-warning-arrow"
361
- icon="arrow-right-alt2"
362
- />
363
- </div>
364
- )}
365
- {attributes.displayFirstName !== FIELD_SETTING.NOTSHOW && (
366
- <div className="inputBlock">
367
- <RichText
368
- tagName="label"
369
- className="firstNameLabel"
370
- onChange={(firstNameLabel) => {
371
- setAttributes({ firstNameLabel: firstNameLabel });
372
- }}
373
- value={attributes.firstNameLabel}
374
- />
375
- {attributes.displayFirstName === FIELD_SETTING.REQUIRED && (
376
- <p
377
- className="required-text subTitle"
378
- style={{ color: "#ee0000" }}
379
- >
380
- *
381
- </p>
382
- )}
383
- <input name="first_name" type="text"></input>
384
- </div>
385
- )}
386
- {attributes.displayLastName !== FIELD_SETTING.NOTSHOW && (
387
- <div className="inputBlock">
388
- <RichText
389
- tagName="label"
390
- className="lastNameLabel"
391
- onChange={(lastNameLabel) => {
392
- setAttributes({ lastNameLabel: lastNameLabel });
393
- }}
394
- value={attributes.lastNameLabel}
395
- />
396
- {attributes.displayLastName === FIELD_SETTING.REQUIRED && (
397
- <p
398
- className="required-text subTitle"
399
- style={{ color: "#ee0000" }}
400
- >
401
- *
402
- </p>
403
- )}
404
- <input name="last_name" type="text"></input>
405
- </div>
406
- )}
407
- {attributes.displayTelephone !== FIELD_SETTING.NOTSHOW && (
408
- <div class="inputBlock">
409
- <RichText
410
- tagName="label"
411
- className="lastNameLabel"
412
- onChange={(telephoneLabel) => {
413
- setAttributes({ telephoneLabel: telephoneLabel });
414
- }}
415
- value={attributes.telephoneLabel}
416
- />
417
- {attributes.displayTelephone === FIELD_SETTING.REQUIRED && (
418
- <p
419
- className="required-text subTitle"
420
- style={{ color: "#ee0000" }}
421
- >
422
- *
423
- </p>
424
- )}
425
- <input name="telephone" type="text"></input>
426
- </div>
427
- )}
428
- <div className="inputBlock">
429
- <RichText
430
- tagName="label"
431
- className="emailLabel"
432
- onChange={(emailLabel) => {
433
- setAttributes({ emailLabel: emailLabel });
434
- }}
435
- value={attributes.emailLabel}
436
- />
437
- <p className="required-text subTitle" style={{ color: "#ee0000" }}>
438
- *
439
- </p>
440
- <input className="textwidget" name="email" type="text"></input>
441
- </div>
442
- {attributes.emailPermission == "message" && (
443
- <div className="disclaimer">
444
- <RichText
445
- tagName="label"
446
- className="disclaimer-text"
447
- onChange={(disclaimer) => {
448
- setAttributes({ disclaimer });
449
- }}
450
- value={attributes.disclaimer}
451
- />
452
- </div>
453
- )}
454
- {attributes.emailPermission == "checkbox" && (
455
- <div className="disclaimer">
456
- <input
457
- type="checkbox"
458
- name={`consent_check_${clientId}`}
459
- id={`consent_check_${clientId}`}
460
- />
461
- <RichText
462
- htmlFor={`consent_check_${clientId}`}
463
- tagName="label"
464
- className="consentLabel disclaimer-label"
465
- onChange={(consentLabel) => {
466
- setAttributes({ consentLabel });
467
- }}
468
- value={attributes.consentLabel}
469
- />
470
- </div>
471
- )}
472
- <button className="wp-block-button__link submit-button" type="button">
473
- {__("Subscribe", "cewp4")}
474
- </button>
475
- </form>
476
- </div>
477
- );
478
  }
1
  import { __ } from "@wordpress/i18n";
2
  import {
3
+ BlockControls,
4
+ InspectorControls,
5
+ RichText,
6
  } from "@wordpress/block-editor";
7
  import {
8
+ SelectControl,
9
+ TextareaControl,
10
+ TextControl,
11
+ Panel,
12
+ PanelBody,
13
+ PanelRow,
14
+ ExternalLink,
15
+ Dashicon,
16
  } from "@wordpress/components";
17
 
18
  import "./editor.scss";
19
 
20
  export const FIELD_SETTING = {
21
+ NOTSHOW: "notshow",
22
+ OPTIONAL: "optional",
23
+ REQUIRED: "required",
24
  };
25
 
26
  export const ON_SUBMIT_SETTING = {
27
+ SUMMARY: "summary",
28
+ MESSAGE: "message",
29
+ REDIRECT: "redirect",
30
  };
31
 
32
  const useWPAction = (action, nonce) => {
33
+ const [data, setData] = React.useState([]);
34
+ const [loading, setLoading] = React.useState(false);
35
+ const [hasLoaded, setHasLoaded] = React.useState(false);
36
 
37
+ React.useEffect(() => {
38
+ if (loading || hasLoaded) return;
39
+ setLoading(true);
40
+ jQuery
41
+ .post(ce4wp_form_submit_data?.url, {
42
+ action: action,
43
+ nonce: nonce,
44
+ })
45
+ .done((response) => {
46
+ setLoading(false);
47
+ setHasLoaded(true);
48
+ if (response?.data != null) {
49
+ setData(response.data);
50
+ }
51
+ });
52
+ }, [loading, hasLoaded, data]);
53
 
54
+ return {
55
+ data,
56
+ loading,
57
+ hasLoaded,
58
+ };
59
  };
60
 
61
  const useCustomLists = () => {
62
+ const { data, loading, hasLoaded } = useWPAction(
63
+ "ce4wp_get_all_custom_lists",
64
+ ce4wp_form_submit_data?.listNonce
65
+ );
66
 
67
+ let customLists = [];
68
+ if (data != null && data.length != undefined) {
69
+ customLists = data.map((list) => ({
70
+ label: list.name,
71
+ value: list.id,
72
+ }));
73
+ }
74
+ return {
75
+ customLists,
76
+ loading,
77
+ hasLoaded,
78
+ };
79
  };
80
 
81
  const useIsCreativeMailActivated = () => {
82
+ const { data, loading, hasLoaded } = useWPAction(
83
+ "ce4wp_creative_email_activated",
84
+ ce4wp_form_submit_data?.activatedNonce
85
+ );
86
+ return {
87
+ creativeEmailIsActivated: data,
88
+ loading,
89
+ hasLoaded,
90
+ };
91
  };
92
 
93
  export default function Edit({
94
+ attributes,
95
+ setAttributes,
96
+ className,
97
+ clientId,
98
  }) {
99
+ const { blockId } = attributes;
100
+ if (!blockId) {
101
+ setAttributes({ blockId: clientId });
102
+ }
103
+ const { customLists } = useCustomLists();
104
+ const { creativeEmailIsActivated } = useIsCreativeMailActivated();
105
+ return (
106
+ <div className={`wp-block-ce4wp-subscribe ${className ? className : ""}`}>
107
+ <BlockControls key="setting">
108
+ <InspectorControls key="setting">
109
+ <Panel header="Settings">
110
+ <PanelBody title="Contact Segmentation" initialOpen={true}>
111
+ <PanelRow className="no-flex">
112
+ <fieldset>
113
+ <i className="subTitle sub-header">
114
+ {__(
115
+ "Automatically assign a new contact to a list when they subscribe",
116
+ "ce4wp"
117
+ )}
118
+ <br />
119
+ <ExternalLink
120
+ onClick={() =>
121
+ ce4wpNavigateToDashboard(
122
+ this,
123
+ "fbcd9606-288a-4d82-be7c-449eaf5a3792",
124
+ { source: "ce4wp_form_menu" },
125
+ ce4wpDashboardStartCallback,
126
+ ce4wpDashboardFinishCallback
127
+ )
128
+ }
129
+ >
130
  <span
131
+ id="ce4wp-manage-lists"
132
+ data-link_reference="836b20fc-9ff1-41b2-912b-a8646caf05a4"
133
+ >
134
  {__("Manage your lists", "ce4wp")}
135
  </span>
136
+ </ExternalLink>
137
+ </i>
138
+ <br />
139
+ <br />
140
+ <SelectControl
141
+ label="list"
142
+ value={attributes.customList}
143
+ options={[
144
+ {
145
+ label: __("Don't assign to a list", "cewp4"),
146
+ value: "",
147
+ },
148
+ ...customLists,
149
+ ]}
150
+ onChange={(customList) =>
151
+ setAttributes({
152
+ customList,
153
+ })
154
+ }
155
+ />
156
+ </fieldset>
157
+ </PanelRow>
158
+ </PanelBody>
159
+ <PanelBody title="On submission" initialOpen={true}>
160
+ <PanelRow>
161
+ <fieldset>
162
+ <SelectControl
163
+ label="On submission"
164
+ value={attributes.onSubmissionSetting}
165
+ options={[
166
+ {
167
+ label: "Show a custom text message",
168
+ value: ON_SUBMIT_SETTING.MESSAGE,
169
+ },
170
+ {
171
+ label: "Show a summary of submitted fields",
172
+ value: ON_SUBMIT_SETTING.SUMMARY,
173
+ },
174
+ {
175
+ label: "Redirect",
176
+ value: ON_SUBMIT_SETTING.REDIRECT,
177
+ },
178
+ ]}
179
+ onChange={(onSubmissionSetting) =>
180
+ setAttributes({ onSubmissionSetting })
181
+ }
182
+ />
183
+ </fieldset>
184
+ </PanelRow>
185
+ {attributes.onSubmissionSetting === ON_SUBMIT_SETTING.MESSAGE && (
186
+ <PanelRow>
187
+ <fieldset>
188
+ <TextareaControl
189
+ label="Message text"
190
+ value={attributes.onSubmission}
191
+ onChange={(onSubmission) =>
192
+ setAttributes({ onSubmission })
193
+ }
194
+ />
195
+ </fieldset>
196
+ </PanelRow>
197
+ )}
198
+ {attributes.onSubmissionSetting === ON_SUBMIT_SETTING.REDIRECT && (
199
+ <PanelRow>
200
+ <fieldset>
201
+ <TextControl
202
+ label="Redirect link"
203
+ value={attributes.redirectLink}
204
+ onChange={(redirectLink) =>
205
+ setAttributes({ redirectLink })
206
+ }
207
+ />
208
+ </fieldset>
209
+ </PanelRow>
210
+ )}
211
+ </PanelBody>
212
+ <PanelBody title="Disclaimer settings" initialOpen={true}>
213
+ <PanelRow className="no-flex">
214
+ <fieldset>
215
+ <SelectControl
216
+ label="Permission to mail"
217
+ value={attributes.emailPermission}
218
+ options={[
219
+ {
220
+ label: "message",
221
+ value: "message",
222
+ },
223
+ {
224
+ label: "checkbox",
225
+ value: "checkbox",
226
+ },
227
+ ]}
228
+ onChange={(emailPermission) =>
229
+ setAttributes({
230
+ ...attributes,
231
+ emailPermission: emailPermission,
232
+ })
233
+ }
234
+ />
235
+ </fieldset>
236
+ </PanelRow>
237
+ </PanelBody>
238
+ <PanelBody title="Field settings" initialOpen={true}>
239
+ <PanelRow className="no-flex">
240
+ <fieldset>
241
+ <SelectControl
242
+ label="First name field"
243
+ value={attributes.displayFirstName}
244
+ options={[
245
+ {
246
+ label: "Do not show",
247
+ value: FIELD_SETTING.NOTSHOW,
248
+ },
249
+ {
250
+ label: "Optional",
251
+ value: FIELD_SETTING.OPTIONAL,
252
+ },
253
+ {
254
+ label: "Required",
255
+ value: FIELD_SETTING.REQUIRED,
256
+ },
257
+ ]}
258
+ onChange={(displayFirstName) =>
259
+ setAttributes({
260
+ displayFirstName: displayFirstName,
261
+ })
262
+ }
263
+ />
264
+ </fieldset>
265
+ </PanelRow>
266
+ <PanelRow className="no-flex">
267
+ <fieldset>
268
+ <SelectControl
269
+ label="Last name field"
270
+ value={attributes.displayLastName}
271
+ options={[
272
+ {
273
+ label: "Do not show",
274
+ value: FIELD_SETTING.NOTSHOW,
275
+ },
276
+ {
277
+ label: "Optional",
278
+ value: FIELD_SETTING.OPTIONAL,
279
+ },
280
+ {
281
+ label: "Required",
282
+ value: FIELD_SETTING.REQUIRED,
283
+ },
284
+ ]}
285
+ onChange={(displayLastName) =>
286
+ setAttributes({
287
+ displayLastName: displayLastName,
288
+ })
289
+ }
290
+ />
291
+ </fieldset>
292
+ </PanelRow>
293
+ <PanelRow className="no-flex">
294
+ <fieldset>
295
+ <SelectControl
296
+ label="Telephone field"
297
+ value={attributes.displayTelephone}
298
+ options={[
299
+ {
300
+ label: "Do not show",
301
+ value: FIELD_SETTING.NOTSHOW,
302
+ },
303
+ {
304
+ label: "Optional",
305
+ value: FIELD_SETTING.OPTIONAL,
306
+ },
307
+ {
308
+ label: "Required",
309
+ value: FIELD_SETTING.REQUIRED,
310
+ },
311
+ ]}
312
+ onChange={(displayTelephone) =>
313
+ setAttributes({
314
+ displayTelephone: displayTelephone,
315
+ })
316
+ }
317
+ />
318
+ </fieldset>
319
+ </PanelRow>
320
+ </PanelBody>
321
+ </Panel>
322
+ </InspectorControls>
323
+ </BlockControls>
324
+ <form name="contact-form">
325
+ <RichText
326
+ tagName="h2"
327
+ onChange={(title) => {
328
+ setAttributes({ title: title });
329
+ }}
330
+ value={attributes.title}
331
+ />
332
+ <RichText
333
+ tagName="p"
334
+ className="subTitle"
335
+ onChange={(subTitle) => {
336
+ setAttributes({ subTitle: subTitle });
337
+ }}
338
+ value={attributes.subTitle}
339
+ />
340
+ {creativeEmailIsActivated === false && (
341
+ <div
342
+ className="ce4wp-inline-notification ce4wp-inline-warning ce4wp-banner-clickable"
343
+ onClick={() =>
344
+ ce4wpNavigateToDashboard(
345
+ this,
346
+ "d25f690a-217a-4d68-9c58-8693965d4673",
347
+ { source: "ce4wp_form_menu" },
348
+ ce4wpDashboardStartCallback,
349
+ ce4wpDashboardFinishCallback
350
+ )
351
+ }
352
+ >
353
+ <Dashicon className="ce4wp-inline-warning-icon" icon="warning" />
354
+ <div className="ce4wp-inline-warning-text">
355
+ {__(
356
+ "Set up Creative Mail before you use this form on your website."
357
+ )}
358
+ </div>
359
+ <Dashicon
360
+ className="ce4wp-inline-warning-arrow"
361
+ icon="arrow-right-alt2"
362
+ />
363
+ </div>
364
+ )}
365
+ {attributes.displayFirstName !== FIELD_SETTING.NOTSHOW && (
366
+ <div className="inputBlock">
367
+ <RichText
368
+ tagName="label"
369
+ className="firstNameLabel"
370
+ onChange={(firstNameLabel) => {
371
+ setAttributes({ firstNameLabel: firstNameLabel });
372
+ }}
373
+ value={attributes.firstNameLabel}
374
+ />
375
+ {attributes.displayFirstName === FIELD_SETTING.REQUIRED && (
376
+ <p
377
+ className="required-text subTitle"
378
+ style={{ color: "#ee0000" }}
379
+ >
380
+ *
381
+ </p>
382
+ )}
383
+ <input name="first_name" type="text"></input>
384
+ </div>
385
+ )}
386
+ {attributes.displayLastName !== FIELD_SETTING.NOTSHOW && (
387
+ <div className="inputBlock">
388
+ <RichText
389
+ tagName="label"
390
+ className="lastNameLabel"
391
+ onChange={(lastNameLabel) => {
392
+ setAttributes({ lastNameLabel: lastNameLabel });
393
+ }}
394
+ value={attributes.lastNameLabel}
395
+ />
396
+ {attributes.displayLastName === FIELD_SETTING.REQUIRED && (
397
+ <p
398
+ className="required-text subTitle"
399
+ style={{ color: "#ee0000" }}
400
+ >
401
+ *
402
+ </p>
403
+ )}
404
+ <input name="last_name" type="text"></input>
405
+ </div>
406
+ )}
407
+ {attributes.displayTelephone !== FIELD_SETTING.NOTSHOW && (
408
+ <div class="inputBlock">
409
+ <RichText
410
+ tagName="label"
411
+ className="lastNameLabel"
412
+ onChange={(telephoneLabel) => {
413
+ setAttributes({ telephoneLabel: telephoneLabel });
414
+ }}
415
+ value={attributes.telephoneLabel}
416
+ />
417
+ {attributes.displayTelephone === FIELD_SETTING.REQUIRED && (
418
+ <p
419
+ className="required-text subTitle"
420
+ style={{ color: "#ee0000" }}
421
+ >
422
+ *
423
+ </p>
424
+ )}
425
+ <input name="telephone" type="text"></input>
426
+ </div>
427
+ )}
428
+ <div className="inputBlock">
429
+ <RichText
430
+ tagName="label"
431
+ className="emailLabel"
432
+ onChange={(emailLabel) => {
433
+ setAttributes({ emailLabel: emailLabel });
434
+ }}
435
+ value={attributes.emailLabel}
436
+ />
437
+ <p className="required-text subTitle" style={{ color: "#ee0000" }}>
438
+ *
439
+ </p>
440
+ <input className="textwidget" name="email" type="text"></input>
441
+ </div>
442
+ {attributes.emailPermission == "message" && (
443
+ <div className="disclaimer">
444
+ <RichText
445
+ tagName="label"
446
+ className="disclaimer-text"
447
+ onChange={(disclaimer) => {
448
+ setAttributes({ disclaimer });
449
+ }}
450
+ value={attributes.disclaimer}
451
+ />
452
+ </div>
453
+ )}
454
+ {attributes.emailPermission == "checkbox" && (
455
+ <div className="disclaimer">
456
+ <input
457
+ type="checkbox"
458
+ name={`consent_check_${clientId}`}
459
+ id={`consent_check_${clientId}`}
460
+ />
461
+ <RichText
462
+ htmlFor={`consent_check_${clientId}`}
463
+ tagName="label"
464
+ className="consentLabel disclaimer-label"
465
+ onChange={(consentLabel) => {
466
+ setAttributes({ consentLabel });
467
+ }}
468
+ value={attributes.consentLabel}
469
+ />
470
+ </div>
471
+ )}
472
+ <button className="wp-block-button__link submit-button" type="button">
473
+ {__("Subscribe", "cewp4")}
474
+ </button>
475
+ </form>
476
+ </div>
477
+ );
478
  }
src/blocks/subscribe/index.js CHANGED
@@ -26,7 +26,10 @@ registerBlockType("ce4wp/subscribe", {
26
  // Remove the support for wide alignment.
27
  alignWide: false,
28
  },
29
- keywords: [__("contact"), __("form"), __("email"), __("mail")],
 
 
 
30
  deprecated: [
31
  {
32
  attributes: {
26
  // Remove the support for wide alignment.
27
  alignWide: false,
28
  },
29
+ keywords: [ __('contact', 'creative-mail-by-constant-contact'),
30
+ __('form', 'creative-mail-by-constant-contact'),
31
+ __('email', 'creative-mail-by-constant-contact'),
32
+ __('mail', 'creative-mail-by-constant-contact')],
33
  deprecated: [
34
  {
35
  attributes: {
src/blocks/subscribe/save.js CHANGED
@@ -33,7 +33,7 @@ export default function save({ attributes, className }) {
33
  tagName="h2"
34
  value={attributes.title}
35
  />
36
- <p className="subTitle">{__(attributes.onSubmission, "cewp4")}</p>
37
  </div>
38
  )}
39
  {attributes.onSubmissionSetting === ON_SUBMIT_SETTING.SUMMARY && (
@@ -150,8 +150,8 @@ export default function save({ attributes, className }) {
150
  type="tel"
151
  pattern="[+]?[0-9\(\)\s+-]{5,20}"
152
  oninvalid={`setCustomValidity('${__(
153
- "Please enter a valid phone number",
154
- "cewp4"
155
  )}')`}
156
  oninput="setCustomValidity('')"
157
  required={attributes.displayTelephone === FIELD_SETTING.REQUIRED}
@@ -171,8 +171,8 @@ export default function save({ attributes, className }) {
171
  name="email"
172
  type="email"
173
  oninvalid={`setCustomValidity('${__(
174
- "Please enter a valid email address",
175
- "cewp4"
176
  )}')`}
177
  oninput="setCustomValidity('')"
178
  required
@@ -206,7 +206,7 @@ export default function save({ attributes, className }) {
206
  </div>
207
  )}
208
  <button className="wp-block-button__link submit-button" type="submit">
209
- {__("Subscribe", "cewp4")}
210
  </button>
211
  </form>
212
  </div>
33
  tagName="h2"
34
  value={attributes.title}
35
  />
36
+ <p className="subTitle">{attributes.onSubmission}</p>
37
  </div>
38
  )}
39
  {attributes.onSubmissionSetting === ON_SUBMIT_SETTING.SUMMARY && (
150
  type="tel"
151
  pattern="[+]?[0-9\(\)\s+-]{5,20}"
152
  oninvalid={`setCustomValidity('${__(
153
+ 'Please enter a valid phone number',
154
+ 'creative-mail-by-constant-contact'
155
  )}')`}
156
  oninput="setCustomValidity('')"
157
  required={attributes.displayTelephone === FIELD_SETTING.REQUIRED}
171
  name="email"
172
  type="email"
173
  oninvalid={`setCustomValidity('${__(
174
+ 'Please enter a valid email address',
175
+ 'creative-mail-by-constant-contact'
176
  )}')`}
177
  oninput="setCustomValidity('')"
178
  required
206
  </div>
207
  )}
208
  <button className="wp-block-button__link submit-button" type="submit">
209
+ {__('Subscribe', 'creative-mail-by-constant-contact')}
210
  </button>
211
  </form>
212
  </div>
src/views/activated-integrations.php CHANGED
@@ -5,246 +5,262 @@ use CreativeMail\Helpers\EnvironmentHelper;
5
 
6
  $available_integrations = CreativeMail::get_instance()->get_integration_manager()->get_active_plugins();
7
  $activated_integrations = CreativeMail::get_instance()->get_integration_manager()->get_activated_integrations();
8
- $activated_templates = CreativeMail::get_instance()->get_email_manager()->get_managed_email_notifications();
9
 
10
  ?>
11
 
12
  <script type="application/javascript">
13
- function showConsentModal () {
14
- var form = document.getElementById("activated_plugins_form");
15
- var checkboxes = form.querySelectorAll("input[type='checkbox']:checked");
16
- if (checkboxes.length > 0) {
17
- document.getElementById('consent-modal').style.display = "block";
18
- } else {
19
- submitForm();
20
- }
21
- }
22
-
23
- function closeConsentModal () {
24
- document.getElementById('consent-modal').style.display = "none";
25
- }
26
-
27
- function submitForm() {
28
- document.getElementById('consent-modal-activated-loader').classList.remove("ce4wp-hidden");
29
- document.getElementById('consent-modal-activated-content').style.display = "none";
30
- document.getElementById('activated_plugins_form').submit()
31
- }
32
-
33
- // Let customer know that contacts will be synced if WooCommerce email templates are enabled even if the integration is disabled
34
- function showWooCommerceTemplateConsentModal() {
35
- var wooCommerceModal = document.getElementById('woocommerce-consent-modal');
36
- if (wooCommerceModal) {
37
- wooCommerceModal.style.display = "block";
38
- }
39
- }
40
-
41
- function closeWooCommerceTemplateConsentModal (activateCheckbox) {
42
- var wooCommerceModal = document.getElementById('woocommerce-consent-modal');
43
- var wooCommerceCheckbox = document.getElementById('activated-plugins-check-woocommerce');
44
-
45
- if (wooCommerceCheckbox && activateCheckbox === true) {
46
- document.getElementById('activated-plugins-check-woocommerce').checked = true;
47
- }
48
-
49
- if (wooCommerceModal) {
50
- document.getElementById('woocommerce-consent-modal').style.display = "none";
51
- }
52
- }
53
-
54
- function onChecked(slug){
55
- var card = document.getElementById('activated-plugins-' + slug);
56
- if(card !== undefined && card !== null) {
57
- card.classList.toggle("ce4wp-selected")
58
- }
59
-
60
- var checkbox = document.getElementById('activated-plugins-check-' + slug);
61
- if (card.id === 'activated-plugins-woocommerce' && checkbox.checked === false) {
62
- showWooCommerceTemplateConsentModal();
63
- }
64
- }
65
  </script>
66
 
67
  <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);">
68
- <?= __( 'Select one or more plugins to enable the synchronization of its contacts with Creative Mail.', 'ce4wp') ?>
69
  </p>
70
  <br />
71
  <form id="activated_plugins_form" name="plugins" action="" method="post">
72
- <input type="hidden" name="action" value="change_activated_plugins" />
73
- <input name="activated_plugins_nonce" type="hidden" value="<?= wp_create_nonce('activated_plugins') ?>" />
74
- <div style="color: rgba(0, 0, 0, 0.6);" class="ce4wp-grid">
75
- <?php
76
- foreach ($available_integrations as $available_integration) {
77
- if ($available_integration->is_hidden_from_active_list()) {
78
- continue;
79
- }
80
- $active = in_array($available_integration, $activated_integrations);
81
- $checked = $active === true ? 'checked' : '';
82
- $path = '/assets/p/universal/wordpress-plugin/'.$available_integration->get_slug() .'.png';
83
- $plugin_image = EnvironmentHelper::get_app_url().$path;
84
-
85
- echo '<div class="ce4wp-grid-item">
86
- <div id="activated-plugins-' . esc_attr($available_integration->get_slug()) .'" class="ce4wp-settings-card" >
87
- <label for="activated-plugins-check-' . esc_attr($available_integration->get_slug()) .'">
88
- <div class="ce4wp-grid">
89
- <div class="ce4wp-grid-item ce4wp-grid-xs-2">
90
- <div class="ce4wp-settings-card-image" style="background-image: url(' . esc_attr($plugin_image) . ')" title="' . esc_attr($available_integration->get_slug()) . '"></div>
91
- </div>
92
- <div class="ce4wp-grid-item ce4wp-grid-xs-8">
93
- <span class="ce4wp-settings-card-title">' . esc_html($available_integration->get_name()) . '</span>
94
- </div>
95
- <div class="ce4wp-grid-item ce4wp-grid-xs-2" style="line-height: 48px;">
96
- <label class="ce4wp-checkbox">
97
- <input onclick="onChecked(&quot;' . esc_attr($available_integration->get_slug()) .'&quot;)" type="checkbox" name="activated_plugins[]" id="activated-plugins-check-' . esc_attr($available_integration->get_slug()) .'" value="' . esc_attr($available_integration->get_slug()) . '" ' . esc_attr($checked) . ' />
98
- <span></span>
99
- </label>
100
- </div>
101
- </div>
102
- </label>
103
- </div>
104
- </div>';
105
- }
106
- ?>
107
- </div>
108
- <div class="ce-kvp">
109
- <br />
110
- <input name="save_button" type="submit" class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-button-contained-primary ce4wp-mt-2" id="save-activated-plugins" value="Save" onclick="showConsentModal(); return false;" />
111
- <!-- -->
112
- </div>
113
-
114
- <!-- Consent modal -->
115
- <div id="consent-modal" role="presentation" class="ce4wp-dialog-root" height="auto" variant="default" style="display: none;">
116
- <div class="ce4wp-backdrop-root" aria-hidden="true" style="opacity: 1; "></div>
117
-
118
- <div class="ce4wp-dialog-container" role="none presentation" tabindex="-1"
119
- style="opacity: 1; ">
120
-
121
- <div class="ce4wp-dialog-wrapper" role="dialog">
122
- <div width="100%" class="ce4wp-dialog-header">
123
- <div class="ce4wp-dialog-header-title">
124
- <div class="ce4wp-dialog-header-title-wrapper">
125
- <div class="ce4wp-dialog-header-title-wrapper-content">
126
- <h3 class="ce4wp-typography-root ce4wp-typography-h3"><?= __( 'Yes, these contacts expect to hear from me', 'ce4wp') ?></h3>
127
- </div>
128
- </div>
129
- </div>
130
- <div class="ce4wp-dialog-header-close">
131
- <div class="ce4wp-dialog-header-close-wrapper" onclick="closeConsentModal()">
132
- <div class="ce4wp-dialog-header-close-wrapper-button">
133
- <svg width="24" height="24" viewBox="0 0 24 24" fill="black" xmlns="http://www.w3.org/2000/svg">
134
- <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
135
- </svg>
136
- </div>
137
- </div>
138
- </div>
139
- </div>
140
- <div id='consent-modal-activated-loader' height="auto" class="ce4wp-dialog-content ce4wp-hidden">
141
- <div class="ce4wp-loader" role="progressbar" style="width: 40px; height: 40px;">
142
- <svg class="core-test-MuiCircularProgress-svg" viewBox="22 22 44 44">
143
- <circle class="core-test-MuiCircularProgress-circle core-test-MuiCircularProgress-circleIndeterminate" cx="44" cy="44" r="20.2" fill="none" stroke-width="3.6">
144
- </circle>
145
- </svg>
146
- </div>
147
- </div>
148
- <div id='consent-modal-activated-content'>
149
- <div height="auto" class="ce4wp-dialog-content">
150
- <div>
151
- <div class="ce4wp-pb-3">
152
- <span><?= __( 'Each time you add contacts, they must meet the following conditions.', 'ce4wp') ?></span>
153
- </div>
154
- <div class="ce4wp-consent">
155
- <div class="ce4wp-pb-3">
156
- <h4 class="ce4wp-typography-root ce4wp-typography-h4"><?= __('I have the consent of each contact on my list', 'ce4wp') ?></h4>
157
- <span><?= __( 'You must have the prior consent of each contact added to your Constant Contact account. Your account cannot contain purchased, rented, third party or appended lists. In addition, you may not add auto-response addresses, transactional addresses, or user group addresses.', 'ce4wp') ?></span>
158
- </div>
159
- <h4 class="ce4wp-typography-root ce4wp-typography-h4"><?= __('I am not adding role addresses or distribution lists', 'ce4wp') ?></h4>
160
- <span><?= __( 'Role addresses, such as sales@ or marketing@, and distribution lists often mail to more than one person and result in higher than normal spam complaints. You must remove these from your list prior to upload.', 'ce4wp') ?></span>
161
- </div>
162
- <div class="ce4wp-pb-3">
163
- <span><?= __('Getting your email delivered is important to us. We may contact you to review your list before we send your email, if you add contacts that are likely to cause higher than normal bounces or for other reasons that we know may cause spam complaints. Thanks for helping to eliminate spam.', 'ce4wp') ?></span>
164
- </div>
165
- </div>
166
- </div>
167
- <div class="ce4wp-dialog-footer">
168
- <div class="ce4wp-dialog-footer-close">
169
- <div class="ce4wp-dialog-footer-close-wrapper">
170
- <button class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-button-contained-primary" type="button" onclick="submitForm()" >
171
- <span class="MuiButton-label"><?= __( 'Got it!', 'ce4wp') ?></span>
172
- </button>
173
- </div>
174
- </div>
175
- </div>
176
- </div>
177
- </div>
178
- </div>
179
- </div>
180
-
181
- <!-- WooCommerce Template Consent modal -->
182
- <?php
183
- function get_active_options($option)
184
- {
185
- return $option->active === true;
186
- }
187
-
188
- if (sizeof(array_filter($activated_templates, 'get_active_options')) > 0) {
189
- echo'
190
- <div id="woocommerce-consent-modal" role="presentation" class="ce4wp-dialog-root" height="auto" variant="default" style="display: none;">
191
- <div class="ce4wp-backdrop-root" aria-hidden="true" style="opacity: 1; "></div>
192
- <div class="ce4wp-dialog-container" role="none presentation" tabindex="-1" style="opacity: 1; ">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  <div class="ce4wp-dialog-wrapper" role="dialog">
194
- <div width="100%" class="ce4wp-dialog-header">
195
- <div class="ce4wp-dialog-header-title">
196
- <div class="ce4wp-dialog-header-title-wrapper">
197
- <div class="ce4wp-dialog-header-title-wrapper-content">
198
- <h3 class="ce4wp-typography-root ce4wp-typography-h3">' . __('Disabling WooCommerce', 'ce4wp') . '</h3>
 
 
199
  </div>
200
- </div>
201
- </div>
202
- <div class="ce4wp-dialog-header-close">
203
- <div class="ce4wp-dialog-header-close-wrapper" onclick="closeWooCommerceTemplateConsentModal(true)">
204
- <div class="ce4wp-dialog-header-close-wrapper-button">
205
- <svg width="24" height="24" viewBox="0 0 24 24" fill="black" xmlns="http://www.w3.org/2000/svg">
206
- <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
207
- </svg>
208
  </div>
209
- </div>
210
  </div>
211
- </div>
212
- <div id="consent-modal-activated-loader" height="auto" class="ce4wp-dialog-content ce4wp-hidden">
213
- <div class="ce4wp-loader" role="progressbar" style="width: 40px; height: 40px;">
214
- <svg class="core-test-MuiCircularProgress-svg" viewBox="22 22 44 44">
215
- <circle class="core-test-MuiCircularProgress-circle core-test-MuiCircularProgress-circleIndeterminate" cx="44" cy="44" r="20.2" fill="none" stroke-width="3.6"></circle>
216
- </svg>
217
- </div>
218
- </div>
219
- <div id="consent-modal-activated-content">
220
- <div height="auto" class="ce4wp-dialog-content">
221
- <div>
222
- <div class="ce4wp-pb-3">
223
- <span>' . __( 'Before you disable the WooCommerce integration, please keep in mind the following:', 'ce4wp') . '</span>
224
- </div>
225
- <div class="ce4wp-pb-3">
226
- <span>' . __( 'If you have enabled CreativeMail to handle WooCommerce emails, contacts\' email addresses will continue to be synced.', 'ce4wp') . '</span>
227
  </div>
228
- <div class="ce4wp-pb-3">
229
- <span>' . __( 'If you wish to stop contacts from being synced, please make sure to disable all WooCommerce emails from being handled by CreativeMail.', 'ce4wp') . '</span>
230
- </div>
231
- </div>
232
  </div>
233
- <div class="ce4wp-dialog-footer">
234
- <div class="ce4wp-dialog-footer-close">
235
- <div class="ce4wp-dialog-footer-close-wrapper">
236
- <button class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-button-contained-primary" type="button" onclick="closeWooCommerceTemplateConsentModal(false)">
237
- <span class="MuiButton-label">' . __('Got it!', 'ce4wp') . '</span>
238
- </button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
  </div>
240
- </div>
241
  </div>
242
- </div>
243
  </div>
244
- </div>
245
  </div>
 
246
  ';
247
- }
248
- ?>
249
  </form>
250
 
5
 
6
  $available_integrations = CreativeMail::get_instance()->get_integration_manager()->get_active_plugins();
7
  $activated_integrations = CreativeMail::get_instance()->get_integration_manager()->get_activated_integrations();
8
+ $activated_templates = CreativeMail::get_instance()->get_email_manager()->get_managed_email_notifications();
9
 
10
  ?>
11
 
12
  <script type="application/javascript">
13
+ function showConsentModal () {
14
+ var form = document.getElementById("activated_plugins_form");
15
+ var checkboxes = form.querySelectorAll("input[type='checkbox']:checked");
16
+ if (checkboxes.length > 0) {
17
+ document.getElementById('consent-modal').style.display = "block";
18
+ } else {
19
+ submitForm();
20
+ }
21
+ }
22
+
23
+ function closeConsentModal () {
24
+ document.getElementById('consent-modal').style.display = "none";
25
+ }
26
+
27
+ function submitForm() {
28
+ document.getElementById('consent-modal-activated-loader').classList.remove("ce4wp-hidden");
29
+ document.getElementById('consent-modal-activated-content').style.display = "none";
30
+ document.getElementById('activated_plugins_form').submit();
31
+ }
32
+
33
+ // Let customer know that contacts will be synced if WooCommerce email templates are enabled even if the integration is disabled.
34
+ function showWooCommerceTemplateConsentModal() {
35
+ var wooCommerceModal = document.getElementById('woocommerce-consent-modal');
36
+
37
+ if (wooCommerceModal) {
38
+ wooCommerceModal.style.display = "block";
39
+ }
40
+ }
41
+
42
+ function closeWooCommerceTemplateConsentModal (activateCheckbox) {
43
+ var wooCommerceModal = document.getElementById('woocommerce-consent-modal');
44
+ var wooCommerceCheckbox = document.getElementById('activated-plugins-check-woocommerce');
45
+
46
+ if (wooCommerceCheckbox && activateCheckbox === true) {
47
+ document.getElementById('activated-plugins-check-woocommerce').checked = true;
48
+ }
49
+ if (wooCommerceModal) {
50
+ document.getElementById('woocommerce-consent-modal').style.display = "none";
51
+ }
52
+ }
53
+
54
+ function onChecked(slug){
55
+ var card = document.getElementById('activated-plugins-' + slug);
56
+ var checkbox = document.getElementById('activated-plugins-check-' + slug);
57
+
58
+ if( card !== undefined && card !== null) {
59
+ card.classList.toggle("ce4wp-selected")
60
+ }
61
+ if ( card.id === 'activated-plugins-woocommerce' && checkbox.checked === false) {
62
+ showWooCommerceTemplateConsentModal();
63
+ }
64
+ }
65
  </script>
66
 
67
  <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);">
68
+ <?php esc_html_e( 'Select one or more plugins to enable the synchronization of its contacts with Creative Mail.', 'creative-mail-by-constant-contact'); ?>
69
  </p>
70
  <br />
71
  <form id="activated_plugins_form" name="plugins" action="" method="post">
72
+ <input type="hidden" name="action" value="change_activated_plugins" />
73
+ <input name="activated_plugins_nonce" type="hidden" value="<?php echo esc_html(wp_create_nonce('activated_plugins')); ?>" />
74
+
75
+ <div style="color: rgba(0, 0, 0, 0.6);" class="ce4wp-grid">
76
+ <?php
77
+ foreach ( $available_integrations as $available_integration ) {
78
+ if ( $available_integration->is_hidden_from_active_list() ) {
79
+ continue;
80
+ }
81
+ $active = in_array($available_integration, $activated_integrations, true);
82
+ $checked = true === $active ? 'checked' : '';
83
+ $ce4wp_path = '/assets/p/universal/wordpress-plugin/' . $available_integration->get_slug() . '.png';
84
+ $plugin_image = EnvironmentHelper::get_app_url() . $ce4wp_path;
85
+
86
+ echo '<div class="ce4wp-grid-item">
87
+ <div id="activated-plugins-' . esc_attr($available_integration->get_slug()) . '" class="ce4wp-settings-card" >
88
+ <label for="activated-plugins-check-' . esc_attr($available_integration->get_slug()) . '">
89
+ <div class="ce4wp-grid">
90
+ <div class="ce4wp-grid-item ce4wp-grid-xs-2">
91
+ <div class="ce4wp-settings-card-image" style="background-image: url(' . esc_attr($plugin_image) . ')" title="' . esc_attr($available_integration->get_slug()) . '"></div>
92
+ </div>
93
+ <div class="ce4wp-grid-item ce4wp-grid-xs-8">
94
+ <span class="ce4wp-settings-card-title">' . esc_html($available_integration->get_name()) . '</span>
95
+ </div>
96
+ <div class="ce4wp-grid-item ce4wp-grid-xs-2" style="line-height: 48px;">
97
+ <label class="ce4wp-checkbox">
98
+ <input onclick="onChecked(&quot;' . esc_attr($available_integration->get_slug()) . '&quot;)" type="checkbox" name="activated_plugins[]" id="activated-plugins-check-' . esc_attr($available_integration->get_slug()) . '" value="' . esc_attr($available_integration->get_slug()) . '" ' . esc_attr($checked) . ' />
99
+ <span></span>
100
+ </label>
101
+ </div>
102
+ </div>
103
+ </label>
104
+ </div>
105
+ </div>';
106
+ }
107
+ ?>
108
+ </div>
109
+ <div class="ce-kvp">
110
+ <br />
111
+ <input name="save_button" type="submit" class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-button-contained-primary ce4wp-mt-2" id="save-activated-plugins" value="Save" onclick="showConsentModal(); return false;" />
112
+ </div>
113
+
114
+ <!-- Consent modal -->
115
+ <div id="consent-modal" role="presentation" class="ce4wp-dialog-root" height="auto" variant="default" style="display: none;">
116
+ <div class="ce4wp-backdrop-root" aria-hidden="true" style="opacity: 1; "></div>
117
+ <div class="ce4wp-dialog-container" role="none presentation" tabindex="-1" style="opacity: 1; ">
118
+ <div class="ce4wp-dialog-wrapper" role="dialog">
119
+ <div width="100%" class="ce4wp-dialog-header">
120
+ <div class="ce4wp-dialog-header-title">
121
+ <div class="ce4wp-dialog-header-title-wrapper">
122
+ <div class="ce4wp-dialog-header-title-wrapper-content">
123
+ <h3 class="ce4wp-typography-root ce4wp-typography-h3">
124
+ <?php esc_html_e( 'Yes, these contacts expect to hear from me', 'creative-mail-by-constant-contact'); ?>
125
+ </h3>
126
+ </div>
127
+ </div>
128
+ </div>
129
+ <div class="ce4wp-dialog-header-close">
130
+ <div class="ce4wp-dialog-header-close-wrapper" onclick="closeConsentModal()">
131
+ <div class="ce4wp-dialog-header-close-wrapper-button">
132
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="black" xmlns="http://www.w3.org/2000/svg">
133
+ <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
134
+ </svg>
135
+ </div>
136
+ </div>
137
+ </div>
138
+ </div>
139
+ <div id='consent-modal-activated-loader' height="auto" class="ce4wp-dialog-content ce4wp-hidden">
140
+ <div class="ce4wp-loader" role="progressbar" style="width: 40px; height: 40px;">
141
+ <svg class="core-test-MuiCircularProgress-svg" viewBox="22 22 44 44">
142
+ <circle class="core-test-MuiCircularProgress-circle core-test-MuiCircularProgress-circleIndeterminate"
143
+ cx="44"
144
+ cy="44" r="20.2"
145
+ fill="none"
146
+ stroke-width="3.6">
147
+ </circle>
148
+ </svg>
149
+ </div>
150
+ </div>
151
+ <div id='consent-modal-activated-content'>
152
+ <div height="auto" class="ce4wp-dialog-content">
153
+ <div>
154
+ <div class="ce4wp-pb-3">
155
+ <span>
156
+ <?php esc_html_e( 'Each time you add contacts, they must meet the following conditions.', 'creative-mail-by-constant-contact'); ?>
157
+ </span>
158
+ </div>
159
+ <div class="ce4wp-consent">
160
+ <div class="ce4wp-pb-3">
161
+ <h4 class="ce4wp-typography-root ce4wp-typography-h4">
162
+ <?php esc_html_e('I have the consent of each contact on my list', 'creative-mail-by-constant-contact'); ?>
163
+ </h4>
164
+ <span>
165
+ <?php esc_html_e( 'You must have the prior consent of each contact added to your Constant Contact account. Your account cannot contain purchased, rented, third party or appended lists. In addition, you may not add auto-response addresses, transactional addresses, or user group addresses.', 'creative-mail-by-constant-contact'); ?>
166
+ </span>
167
+ </div>
168
+ <h4 class="ce4wp-typography-root ce4wp-typography-h4">
169
+ <?php esc_html_e('I am not adding role addresses or distribution lists', 'creative-mail-by-constant-contact'); ?>
170
+ </h4>
171
+ <span>
172
+ <?php esc_html_e( 'Role addresses, such as sales@ or marketing@, and distribution lists often mail to more than one person and result in higher than normal spam complaints. You must remove these from your list prior to upload.', 'creative-mail-by-constant-contact'); ?>
173
+ </span>
174
+ </div>
175
+ <div class="ce4wp-pb-3">
176
+ <span>
177
+ <?php esc_html_e('Getting your email delivered is important to us. We may contact you to review your list before we send your email, if you add contacts that are likely to cause higher than normal bounces or for other reasons that we know may cause spam complaints. Thanks for helping to eliminate spam.', 'creative-mail-by-constant-contact'); ?>
178
+ </span>
179
+ </div>
180
+ </div>
181
+ </div>
182
+ <div class="ce4wp-dialog-footer">
183
+ <div class="ce4wp-dialog-footer-close">
184
+ <div class="ce4wp-dialog-footer-close-wrapper">
185
+ <button class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-button-contained-primary" type="button" onclick="submitForm()" >
186
+ <span class="MuiButton-label">
187
+ <?php esc_html_e( 'Got it!', 'creative-mail-by-constant-contact'); ?>
188
+ </span>
189
+ </button>
190
+ </div>
191
+ </div>
192
+ </div>
193
+ </div>
194
+ </div>
195
+ </div>
196
+ </div>
197
+
198
+ <!-- WooCommerce Template Consent modal. -->
199
+ <?php
200
+ function get_active_options( $option ) {
201
+ return true === $option->active;
202
+ }
203
+
204
+ if ( count(array_filter($activated_templates, 'get_active_options')) > 0 ) {
205
+ echo '
206
+ <div id="woocommerce-consent-modal" role="presentation" class="ce4wp-dialog-root" height="auto" variant="default" style="display: none;">
207
+ <div class="ce4wp-backdrop-root" aria-hidden="true" style="opacity: 1; "></div>
208
+ <div class="ce4wp-dialog-container" role="none presentation" tabindex="-1" style="opacity: 1; ">
209
  <div class="ce4wp-dialog-wrapper" role="dialog">
210
+ <div width="100%" class="ce4wp-dialog-header">
211
+ <div class="ce4wp-dialog-header-title">
212
+ <div class="ce4wp-dialog-header-title-wrapper">
213
+ <div class="ce4wp-dialog-header-title-wrapper-content">
214
+ <h3 class="ce4wp-typography-root ce4wp-typography-h3">' . esc_html__('Disabling WooCommerce', 'creative-mail-by-constant-contact') . '</h3>
215
+ </div>
216
+ </div>
217
  </div>
218
+ <div class="ce4wp-dialog-header-close">
219
+ <div class="ce4wp-dialog-header-close-wrapper" onclick="closeWooCommerceTemplateConsentModal(true)">
220
+ <div class="ce4wp-dialog-header-close-wrapper-button">
221
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="black" xmlns="http://www.w3.org/2000/svg">
222
+ <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
223
+ </svg>
224
+ </div>
225
+ </div>
226
  </div>
 
227
  </div>
228
+ <div id="consent-modal-activated-loader" height="auto" class="ce4wp-dialog-content ce4wp-hidden">
229
+ <div class="ce4wp-loader" role="progressbar" style="width: 40px; height: 40px;">
230
+ <svg class="core-test-MuiCircularProgress-svg" viewBox="22 22 44 44">
231
+ <circle class="core-test-MuiCircularProgress-circle core-test-MuiCircularProgress-circleIndeterminate" cx="44" cy="44" r="20.2" fill="none" stroke-width="3.6"></circle>
232
+ </svg>
 
 
 
 
 
 
 
 
 
 
 
233
  </div>
 
 
 
 
234
  </div>
235
+ <div id="consent-modal-activated-content">
236
+ <div height="auto" class="ce4wp-dialog-content">
237
+ <div>
238
+ <div class="ce4wp-pb-3">
239
+ <span>' . esc_html__( 'Before you disable the WooCommerce integration, please keep in mind the following:', 'creative-mail-by-constant-contact') . '</span>
240
+ </div>
241
+ <div class="ce4wp-pb-3">
242
+ <span>' . esc_html__( 'If you have enabled CreativeMail to handle WooCommerce emails, contacts\' email addresses will continue to be synced.', 'creative-mail-by-constant-contact') . '</span>
243
+ </div>
244
+ <div class="ce4wp-pb-3">
245
+ <span>' . esc_html__( 'If you wish to stop contacts from being synced, please make sure to disable all WooCommerce emails from being handled by CreativeMail.', 'creative-mail-by-constant-contact') . '</span>
246
+ </div>
247
+ </div>
248
+ </div>
249
+ <div class="ce4wp-dialog-footer">
250
+ <div class="ce4wp-dialog-footer-close">
251
+ <div class="ce4wp-dialog-footer-close-wrapper">
252
+ <button class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-button-contained-primary" type="button" onclick="closeWooCommerceTemplateConsentModal(false)">
253
+ <span class="MuiButton-label">' . esc_html__('Got it!', 'creative-mail-by-constant-contact') . '</span>
254
+ </button>
255
+ </div>
256
+ </div>
257
  </div>
 
258
  </div>
 
259
  </div>
 
260
  </div>
261
+ </div>
262
  ';
263
+ }
264
+ ?>
265
  </form>
266
 
src/views/admin-dashboard-widget/campaigns.php CHANGED
@@ -1,45 +1,55 @@
1
  <style>
2
  .ce4wp-campaigns {
3
- margin: 0 -12px;
4
  }
5
 
6
  .ce4wp-campaigns__item {
7
- display: flex;
8
- justify-content: space-between;
9
- background-color: #fafafa;
10
- padding: 0 12px;
11
- border-top: 1px solid #ddd;
12
  }
13
 
14
  .ce4wp-campaigns__item:last-of-type {
15
- border-bottom: 1px solid #ddd;
16
  }
17
 
18
  .ce4wp-campaigns__item p {
19
- margin: 0.5em 0;
20
  }
21
 
22
  .ce4wp-campaign-actions {
23
- margin-top: 12px;
24
  }
25
  </style>
26
 
27
- <h3><?= __( 'Your recent campaigns', 'ce4wp' ); ?></h3>
 
 
28
  <section class="ce4wp-campaigns">
29
- <div class="ce4wp-campaigns__item">
30
- <p><?= __('Active:', 'ce4wp' ); ?></p>
31
- <p>
32
- <strong>8</strong>
33
- </p>
34
- </div>
35
- <div class="ce4wp-campaigns__item">
36
- <p><?= __( 'Inactive:', 'ce4wp' ); ?></p>
37
- <p>
38
- <strong>2</strong>
39
- </p>
40
- </div>
 
 
 
 
41
  </section>
42
  <section class="ce4wp-campaign-actions">
43
- <button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, '93b1417d-2efb-406d-a9a6-aa8af8f813a3', { source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)"><?= __( 'Create a new campaign', 'ce4wp' ); ?></button>
44
- <button class="button" onclick="ce4wpNavigateToDashboard(this, '5166faec-1dbb-4434-bad0-bb2f75898f92', { source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)"><?= __( 'View all campaigns', 'ce4wp' ); ?></button>
 
 
 
 
45
  </section>
1
  <style>
2
  .ce4wp-campaigns {
3
+ margin: 0 -12px;
4
  }
5
 
6
  .ce4wp-campaigns__item {
7
+ display: flex;
8
+ justify-content: space-between;
9
+ background-color: #fafafa;
10
+ padding: 0 12px;
11
+ border-top: 1px solid #ddd;
12
  }
13
 
14
  .ce4wp-campaigns__item:last-of-type {
15
+ border-bottom: 1px solid #ddd;
16
  }
17
 
18
  .ce4wp-campaigns__item p {
19
+ margin: 0.5em 0;
20
  }
21
 
22
  .ce4wp-campaign-actions {
23
+ margin-top: 12px;
24
  }
25
  </style>
26
 
27
+ <h3>
28
+ <?php esc_html_e( 'Your recent campaigns', 'creative-mail-by-constant-contact' ); ?>
29
+ </h3>
30
  <section class="ce4wp-campaigns">
31
+ <div class="ce4wp-campaigns__item">
32
+ <p>
33
+ <?php esc_html_e('Active:', 'creative-mail-by-constant-contact' ); ?>
34
+ </p>
35
+ <p>
36
+ <strong>8</strong>
37
+ </p>
38
+ </div>
39
+ <div class="ce4wp-campaigns__item">
40
+ <p>
41
+ <?php esc_html_e( 'Inactive:', 'creative-mail-by-constant-contact' ); ?>
42
+ </p>
43
+ <p>
44
+ <strong>2</strong>
45
+ </p>
46
+ </div>
47
  </section>
48
  <section class="ce4wp-campaign-actions">
49
+ <button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, '93b1417d-2efb-406d-a9a6-aa8af8f813a3', { source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
50
+ <?php esc_html_e( 'Create a new campaign', 'creative-mail-by-constant-contact' ); ?>
51
+ </button>
52
+ <button class="button" onclick="ce4wpNavigateToDashboard(this, '5166faec-1dbb-4434-bad0-bb2f75898f92', { source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
53
+ <?php esc_html_e( 'View all campaigns', 'creative-mail-by-constant-contact' ); ?>
54
+ </button>
55
  </section>
src/views/admin-dashboard-widget/divider.php CHANGED
@@ -1 +1,6 @@
 
 
 
 
 
1
  <hr style="margin: 12px -12px 10px;" />
1
+ <?php
2
+ /**
3
+ * This is just an HTML Divider Template.
4
+ */
5
+ ?>
6
  <hr style="margin: 12px -12px 10px;" />
src/views/admin-dashboard-widget/exception.php CHANGED
@@ -1,11 +1,18 @@
1
  <div style="display: flex;">
2
- <section style="flex: 1;">
3
- <p style="margin-top: 0;"><?= __( 'Well... this is embarrassing!', 'ce4wp' ); ?></p>
4
- <p><?= __( 'Creative Mail ran into an error.', 'ce4wp' ); ?></p>
5
- <p><?= __( 'Please try again at a later time.', 'ce4wp') ?></p>
6
- </section>
7
- <img
8
- src="<?= CE4WP_PLUGIN_URL . 'assets/images/admin-dashboard-widget/creative-mail.png'; ?>"
9
- style="margin-top: -11px; margin-right: -12px; height: 10em;"
10
- />
 
 
 
 
 
 
 
11
  </div>
1
  <div style="display: flex;">
2
+ <section style="flex: 1;">
3
+ <p style="margin-top: 0;">
4
+ <?php esc_html_e( 'Well... this is embarrassing!', 'creative-mail-by-constant-contact' ); ?>
5
+ </p>
6
+ <p>
7
+ <?php esc_html_e( 'Creative Mail ran into an error.', 'creative-mail-by-constant-contact' ); ?>
8
+ </p>
9
+ <p>
10
+ <?php esc_html_e( 'Please try again at a later time.', 'creative-mail-by-constant-contact'); ?>
11
+
12
+ </p>
13
+ </section>
14
+ <img
15
+ src="<?php echo esc_url( CE4WP_PLUGIN_URL . 'assets/images/admin-dashboard-widget/creative-mail.png' ); ?>"
16
+ style="margin-top: -11px; margin-right: -12px; height: 10em;"
17
+ />
18
  </div>
src/views/admin-dashboard-widget/most-recent-campaigns.php CHANGED
@@ -1,103 +1,105 @@
1
  <style>
2
- .ce4wp-campaigns {
3
- margin: 0 -12px;
4
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- .ce4wp-campaigns .dashicons {
7
- color: #606a73;
8
- }
9
 
10
- .ce4wp-campaigns__item {
11
- display: flex;
12
- background-color: #fafafa;
13
- padding: 6px 12px;
14
- border-top: 1px solid #ddd;
15
- }
16
 
17
- .ce4wp-campaigns__item:last-of-type {
18
- border-bottom: 1px solid #ddd;
19
- }
20
 
21
- .ce4wp-campaigns__item p {
22
- margin: 0.5em 0;
23
- }
24
 
25
- .ce4wp-campaign-actions {
26
- margin-top: 12px;
27
- }
 
 
 
 
28
 
29
- .ce4wp-campaigns__item__section {
30
- display: flex;
31
- flex-direction: column;
32
- align-items: flex-start;
33
- justify-content: center;
34
- }
35
 
36
- .ce4wp-campaigns__item__section + .ce4wp-campaigns__item__section {
37
- margin-left: 12px;
38
- }
39
-
40
- .ce4wp-campaigns__item__section.ce4wp-campaigns__item__section--grow {
41
- flex: 1;
42
- }
43
-
44
- .ce4wp-campaigns__item__title {
45
- text-decoration: none;
46
- }
47
- .ce4wp-campaigns__item__title:hover {
48
- text-decoration: underline;
49
- cursor: pointer;
50
- }
51
-
52
- p.ce4wp-campaigns__item__subtitle {
53
- margin: 0;
54
- }
55
-
56
- .no-decoration {
57
- text-decoration: none;
58
- }
59
  </style>
60
 
61
- <h3><?= __( 'Your recent campaigns', 'ce4wp' ); ?></h3>
 
 
62
  <section class="ce4wp-campaigns">
63
- <?php
64
- // @phpstan-ignore-next-line
65
- foreach ( $ce_most_recent_campaigns as $campaign ) { ?>
66
- <div class="ce4wp-campaigns__item">
67
- <section class="ce4wp-campaigns__item__section">
68
- <?php if ( $campaign->is_draft ) { ?>
69
- <span class="dashicons dashicons-edit"></span>
70
- <?php } else { ?>
71
- <span class="dashicons dashicons-email"></span>
72
- <?php } ?>
73
- </section>
74
- <section class="ce4wp-campaigns__item__section ce4wp-campaigns__item__section--grow">
75
- <?php if ( $campaign->is_draft ) { ?>
76
- <a class="ce4wp-campaigns__item__title" onclick="ce4wpNavigateToDashboard(this, 'c182bb37-9cef-4962-a706-7fa14ffef01e', { campaignId: '<?= esc_attr( $campaign->id ); ?>', source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
77
- <strong><?= esc_html( $campaign->name ); ?></strong>
78
- </a>
79
- <?php } else { ?>
80
- <a class="ce4wp-campaigns__item__title" onclick="ce4wpNavigateToDashboard(this, 'bd38068c-329b-4c9f-9b2d-fb03a9278bbb', { campaignId: '<?= esc_attr( $campaign->id ); ?>', source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
81
- <strong><?= esc_html( $campaign->name ); ?></strong>
82
- </a>
83
- <?php } ?>
84
- <p class="ce4wp-campaigns__item__subtitle">
85
- <?= esc_html( $campaign->status ); ?>
86
- </p>
87
- </section>
88
- <?php if ( isset( $campaign->open_rate ) ) { ?>
89
- <section class="ce4wp-campaigns__item__section">
90
- <p><?= __( 'Open Rate', 'ce4wp' ); ?>: <strong><?= esc_html( $campaign->open_rate ); ?></strong>%</p>
91
- </section>
92
- <?php } ?>
93
- </div>
94
- <?php } ?>
 
 
 
 
95
  </section>
96
  <section class="ce4wp-campaign-actions">
97
- <button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, '93b1417d-2efb-406d-a9a6-aa8af8f813a3', { source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
98
- <?= __( 'Create a new campaign', 'ce4wp' ); ?>
99
- </button>
100
- <button class="button" onclick="ce4wpNavigateToDashboard(this, '5166faec-1dbb-4434-bad0-bb2f75898f92', { source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
101
- <?= __( 'View all campaigns', 'ce4wp' ); ?>
102
- </button>
103
  </section>
1
  <style>
2
+ .ce4wp-campaigns {
3
+ margin: 0 -12px;
4
+ }
5
+ .ce4wp-campaigns .dashicons {
6
+ color: #606a73;
7
+ }
8
+ .ce4wp-campaigns__item {
9
+ display: flex;
10
+ background-color: #fafafa;
11
+ padding: 6px 12px;
12
+ border-top: 1px solid #ddd;
13
+ }
14
+ .ce4wp-campaigns__item:last-of-type {
15
+ border-bottom: 1px solid #ddd;
16
+ }
17
+ .ce4wp-campaigns__item p {
18
+ margin: 0.5em 0;
19
+ }
20
 
21
+ .ce4wp-campaign-actions {
22
+ margin-top: 12px;
23
+ }
24
 
25
+ .ce4wp-campaigns__item__section {
26
+ display: flex;
27
+ flex-direction: column;
28
+ align-items: flex-start;
29
+ justify-content: center;
30
+ }
31
 
32
+ .ce4wp-campaigns__item__section + .ce4wp-campaigns__item__section {
33
+ margin-left: 12px;
34
+ }
35
 
36
+ .ce4wp-campaigns__item__section.ce4wp-campaigns__item__section--grow {
37
+ flex: 1;
38
+ }
39
 
40
+ .ce4wp-campaigns__item__title {
41
+ text-decoration: none;
42
+ }
43
+ .ce4wp-campaigns__item__title:hover {
44
+ text-decoration: underline;
45
+ cursor: pointer;
46
+ }
47
 
48
+ p.ce4wp-campaigns__item__subtitle {
49
+ margin: 0;
50
+ }
 
 
 
51
 
52
+ .no-decoration {
53
+ text-decoration: none;
54
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  </style>
56
 
57
+ <h3>
58
+ <?php esc_html_e( 'Your recent campaigns', 'creative-mail-by-constant-contact' ); ?>
59
+ </h3>
60
  <section class="ce4wp-campaigns">
61
+ <?php
62
+ // @phpstan-ignore-next-line
63
+ foreach ( $ce_most_recent_campaigns as $campaign ) {
64
+ ?>
65
+ <div class="ce4wp-campaigns__item">
66
+ <section class="ce4wp-campaigns__item__section">
67
+ <?php if ( $campaign->is_draft ) { ?>
68
+ <span class="dashicons dashicons-edit"></span>
69
+ <?php } else { ?>
70
+ <span class="dashicons dashicons-email"></span>
71
+ <?php } ?>
72
+ </section>
73
+ <section class="ce4wp-campaigns__item__section ce4wp-campaigns__item__section--grow">
74
+ <?php if ( $campaign->is_draft ) { ?>
75
+ <a class="ce4wp-campaigns__item__title" onclick="ce4wpNavigateToDashboard(this, 'c182bb37-9cef-4962-a706-7fa14ffef01e', { campaignId: '<?php echo esc_attr( $campaign->id ); ?>', source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
76
+ <strong><?php echo esc_html( $campaign->name ); ?></strong>
77
+ </a>
78
+ <?php } else { ?>
79
+ <a class="ce4wp-campaigns__item__title" onclick="ce4wpNavigateToDashboard(this, 'bd38068c-329b-4c9f-9b2d-fb03a9278bbb', { campaignId: '<?php echo esc_attr( $campaign->id ); ?>', source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
80
+ <strong><?php echo esc_html( $campaign->name ); ?></strong>
81
+ </a>
82
+ <?php } ?>
83
+ <p class="ce4wp-campaigns__item__subtitle">
84
+ <?php echo esc_html( $campaign->status ); ?>
85
+ </p>
86
+ </section>
87
+ <?php if ( isset( $campaign->open_rate ) ) { ?>
88
+ <section class="ce4wp-campaigns__item__section">
89
+ <p>
90
+ <?php esc_html_e( 'Open Rate', 'creative-mail-by-constant-contact' ); ?>:
91
+ <strong><?php echo esc_html( $campaign->open_rate ); ?></strong>%
92
+ </p>
93
+ </section>
94
+ <?php } ?>
95
+ </div>
96
+ <?php } ?>
97
  </section>
98
  <section class="ce4wp-campaign-actions">
99
+ <button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, '93b1417d-2efb-406d-a9a6-aa8af8f813a3', { source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
100
+ <?php esc_html_e( 'Create a new campaign', 'creative-mail-by-constant-contact' ); ?>
101
+ </button>
102
+ <button class="button" onclick="ce4wpNavigateToDashboard(this, '5166faec-1dbb-4434-bad0-bb2f75898f92', { source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
103
+ <?php esc_html_e( 'View all campaigns', 'creative-mail-by-constant-contact' ); ?>
104
+ </button>
105
  </section>
src/views/admin-dashboard-widget/no-campaign.php CHANGED
@@ -1,12 +1,15 @@
1
  <div style="display: flex;">
2
- <section style="flex: 1;">
3
- <p style="margin-top: 0;">
4
- <?= __( 'Thanks for signing up with Creative Mail. Let’s create your first campaign!', 'ce4wp' ); ?>
5
- </p>
6
- <button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, '93b1417d-2efb-406d-a9a6-aa8af8f813a3', { source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)"><?= __( 'Create a campaign', 'ce4wp' ); ?></button>
7
- </section>
8
- <img
9
- src="<?= CE4WP_PLUGIN_URL . 'assets/images/admin-dashboard-widget/airplane.svg'; ?>"
10
- style="margin-top: -11px; margin-right: -12px; height: 8em;"
11
- />
 
 
 
12
  </div>
1
  <div style="display: flex;">
2
+ <section style="flex: 1;">
3
+ <p style="margin-top: 0;">
4
+ <?php esc_html_e( 'Thanks for signing up with Creative Mail. Let’s create your first campaign!', 'creative-mail-by-constant-contact' ); ?>
5
+ </p>
6
+ <button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, '93b1417d-2efb-406d-a9a6-aa8af8f813a3', { source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
7
+ <?php esc_html_e( 'Create a campaign', 'creative-mail-by-constant-contact' ); ?>
8
+ </button>
9
+ </section>
10
+ <img
11
+ src="<?php echo esc_url( CE4WP_PLUGIN_URL . 'assets/images/admin-dashboard-widget/airplane.svg' ); ?>"
12
+ style="margin-top: -11px; margin-right: -12px; height: 8em;"
13
+ alt="<?php esc_attr_e( 'Creative Mail paper airplane image.', 'creative-mail-by-constant-contact' ); ?>"
14
+ />
15
  </div>
src/views/admin-dashboard-widget/no-ce-account.php CHANGED
@@ -1,14 +1,15 @@
1
  <div style="display: flex;">
2
- <section style="flex: 1;">
3
- <p style="margin-top: 0;">
4
- <?= __('Our intelligent email editor makes it easy to create professional emails to engage your audience.', 'ce4wp'); ?>
5
- </p>
6
- <button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, 'd25f690a-217a-4d68-9c58-8693965d4673', { source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
7
- <?= __("Let's go!", 'ce4wp'); ?>
8
- </button>
9
- </section>
10
- <img
11
- src="<?= CE4WP_PLUGIN_URL . 'assets/images/admin-dashboard-widget/creative-mail.png'; ?>"
12
- style="margin-top: -11px; margin-right: -12px; height: 10em;"
13
- />
 
14
  </div>
1
  <div style="display: flex;">
2
+ <section style="flex: 1;">
3
+ <p style="margin-top: 0;">
4
+ <?php esc_html_e('Our intelligent email editor makes it easy to create professional emails to engage your audience.', 'creative-mail-by-constant-contact'); ?>
5
+ </p>
6
+ <button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, 'd25f690a-217a-4d68-9c58-8693965d4673', { source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
7
+ <?php esc_html_e("Let's go!", 'creative-mail-by-constant-contact'); ?>
8
+ </button>
9
+ </section>
10
+ <img
11
+ src="<?php echo esc_url( CE4WP_PLUGIN_URL . 'assets/images/admin-dashboard-widget/creative-mail.png' ); ?>"
12
+ style="margin-top: -11px; margin-right: -12px; height: 10em;"
13
+ alt="<?php esc_attr_e('Creative Mail Dashboard Widget image.', 'creative-mail-by-constant-contact'); ?>"
14
+ />
15
  </div>
src/views/admin-dashboard-widget/no-woocommerce.php CHANGED
@@ -1,14 +1,21 @@
1
  <div style="display: flex;">
2
- <section style="flex: 1;">
3
- <p style="margin-top: 0;">
4
- <?= __( 'Easily manage and brand all of your important transactional WooCommerce store emails.', 'ce4wp' ); ?>
5
- </p>
6
- <button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, '1fabdbe2-95ed-4e1e-a2f3-ba0278f5096f', { source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
7
- <?= __( "Let's go!", 'ce4wp' ); ?>
8
- </button>
9
- </section>
10
- <img
11
- src="<?= CE4WP_PLUGIN_URL . 'assets/images/admin-dashboard-widget/no-woocommerce.svg'; ?>"
12
- style="height: 8em; margin-left: 1em;"
13
- />
 
 
 
 
 
 
 
14
  </div>
1
  <div style="display: flex;">
2
+ <section style="flex: 1;">
3
+ <p style="margin-top: 0;">
4
+ <?php esc_html_e( 'Easily manage and brand all of your important transactional WooCommerce store emails.', 'creative-mail-by-constant-contact' ); ?>
5
+ </p>
6
+ <button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, '1fabdbe2-95ed-4e1e-a2f3-ba0278f5096f', { source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
7
+ <?php esc_html_e( "Let's go!", 'creative-mail-by-constant-contact' ); ?>
8
+ </button>
9
+ </section>
10
+ <img
11
+ src="<?php echo esc_url( CE4WP_PLUGIN_URL . 'assets/images/admin-dashboard-widget/no-woocommerce.svg' ); ?>"
12
+ style="height: 8em; margin-left: 1em;"
13
+ alt="
14
+ <?php
15
+ esc_attr_e(
16
+ 'Creative Mail WooCommerce logo and envelope with a truck on the right corner.',
17
+ 'creative-mail-by-constant-contact' );
18
+ ?>
19
+ "
20
+ />
21
  </div>
src/views/admin-dashboard-widget/woocommerce.php CHANGED
@@ -1,39 +1,47 @@
1
  <style>
2
  .ce4wp-woocommerce {
3
- margin: 0 -12px -12px;
4
  }
5
 
6
  .ce4wp-woocommerce__item {
7
- display: flex;
8
- justify-content: space-between;
9
- background-color: #fafafa;
10
- padding: 0 12px;
11
- border-top: 1px solid #ddd;
12
  }
13
 
14
  .ce4wp-woocommerce__item p {
15
- margin: 0.5em 0;
16
  }
17
  </style>
18
 
19
- <h3><?= __( 'Transactional WooCommerce email', 'ce4wp' ); ?></h3>
 
 
20
  <section class="ce4wp-woocommerce">
21
- <div class="ce4wp-woocommerce__item">
22
- <p><?= __( 'Active', 'ce4wp' ); ?>:</p>
23
- <p>
24
- <strong>
25
- <?php // @phpstan-ignore-next-line
26
- echo $number_of_active_notifications; ?>
27
- </strong>
28
- </p>
29
- </div>
30
- <div class="ce4wp-woocommerce__item">
31
- <p><?php echo __( 'Inactive', 'ce4wp' ); ?>:</p>
32
- <p>
33
- <strong>
34
- <?php // @phpstan-ignore-next-line
35
- echo $number_of_possible_notifications - $number_of_active_notifications; ?>
36
- </strong>
37
- </p>
38
- </div>
 
 
 
 
 
 
39
  </section>
1
  <style>
2
  .ce4wp-woocommerce {
3
+ margin: 0 -12px -12px;
4
  }
5
 
6
  .ce4wp-woocommerce__item {
7
+ display: flex;
8
+ justify-content: space-between;
9
+ background-color: #fafafa;
10
+ padding: 0 12px;
11
+ border-top: 1px solid #ddd;
12
  }
13
 
14
  .ce4wp-woocommerce__item p {
15
+ margin: 0.5em 0;
16
  }
17
  </style>
18
 
19
+ <h3>
20
+ <?php esc_html_e( 'Transactional WooCommerce email', 'creative-mail-by-constant-contact' ); ?>
21
+ </h3>
22
  <section class="ce4wp-woocommerce">
23
+ <div class="ce4wp-woocommerce__item">
24
+ <p>
25
+ <?php esc_html_e( 'Active', 'creative-mail-by-constant-contact' ); ?>:
26
+ </p>
27
+ <p>
28
+ <strong>
29
+ <?php
30
+ // @phpstan-ignore-next-line
31
+ echo esc_attr( $number_of_active_notifications );
32
+ ?>
33
+ </strong>
34
+ </p>
35
+ </div>
36
+ <div class="ce4wp-woocommerce__item">
37
+ <p><?php esc_html_e( 'Inactive', 'creative-mail-by-constant-contact' ); ?>:</p>
38
+ <p>
39
+ <strong>
40
+ <?php
41
+ // @phpstan-ignore-next-line
42
+ echo esc_attr( $number_of_possible_notifications - $number_of_active_notifications );
43
+ ?>
44
+ </strong>
45
+ </p>
46
+ </div>
47
  </section>
src/views/admin-feedback-notice/after-week-notice.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $ce4wp_weekly_notice_nonce = wp_create_nonce( 'ce4wp-weekly-notice-nonce' );
3
+ ?>
4
+ <div class="updated">
5
+ <p>
6
+ <?php esc_html_e( 'Awesome, you\'ve been using', 'creative-mail-by-constant-contact' ); ?>
7
+ <a href="admin.php?page=creativemail">
8
+ <?php esc_html_e( 'Creative Mail', 'creative-mail-by-constant-contact' ); ?>
9
+ </a>
10
+ <?php esc_html_e( 'for more than 1 week. May we ask you to give it a 5-star rating on WordPress?', 'creative-mail-by-constant-contact' ); ?>
11
+ | <a href="
12
+ <?php echo esc_attr('https://wordpress.org/plugins/creative-mail-by-constant-contact/'); ?>
13
+ " target="_blank">
14
+ <?php esc_html_e( 'Ok, you deserved it', 'creative-mail-by-constant-contact' ); ?>
15
+ </a>
16
+ | <a href="<?php echo esc_attr('?ce4wp-ignore-notice=0&ce4wp-weekly-notice-nonce=' . $ce4wp_weekly_notice_nonce); ?>">
17
+ <?php esc_html_e( 'I already did', 'creative-mail-by-constant-contact' ); ?>
18
+ </a>
19
+ | <a href="<?php echo esc_attr('?ce4wp-ignore-notice=0&ce4wp-weekly-notice-nonce=' . $ce4wp_weekly_notice_nonce); ?>">
20
+ <?php esc_html_e( 'No, not good enough', 'creative-mail-by-constant-contact' ); ?>
21
+ </a>
22
+ </p>
23
+ </div>
src/views/admin-feedback-notice/few-contacts.php CHANGED
@@ -1,11 +1,17 @@
1
  <div id="ce4wp-admin-feedback-notice" class="notice notice-warning" hidden>
2
- <img class="icon" src="<?= CE4WP_PLUGIN_URL . 'assets/images/airplane-purple.svg'; ?>" />
3
- <section class="content">
4
- <p>
5
- <strong><?= __( 'Time for an audience shout out?', 'ce4wp' ); ?></strong>
6
- </p>
7
- <p><?= __( 'These contacts are already in Creative Mail, send a quick campaign...', 'ce4wp' ); ?></p>
8
- </section>
9
- <button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, 'd25f690a-217a-4d68-9c58-8693965d4673', { source: 'feedback_notice' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)"><?= __( 'Get started', 'ce4wp' ); ?></button>
10
- <span id="close" onclick="hideAdminFeedbackNotice('feedback_notice_few_contacts')"></span>
 
 
 
 
 
 
11
  </div>
1
  <div id="ce4wp-admin-feedback-notice" class="notice notice-warning" hidden>
2
+ <img class="icon" src="<?php echo esc_url( CE4WP_PLUGIN_URL . 'assets/images/airplane-purple.svg' ); ?>" />
3
+ <section class="content">
4
+ <p>
5
+ <strong>
6
+ <?php esc_html_e( 'Time for an audience shout out?', 'creative-mail-by-constant-contact' ); ?>
7
+ </strong>
8
+ </p>
9
+ <p>
10
+ <?php esc_html_e( 'These contacts are already in Creative Mail, send a quick campaign...', 'creative-mail-by-constant-contact' ); ?>
11
+ </p>
12
+ </section>
13
+ <button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, 'd25f690a-217a-4d68-9c58-8693965d4673', { source: 'feedback_notice' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
14
+ <?php esc_html_e( 'Get started', 'creative-mail-by-constant-contact' ); ?>
15
+ </button>
16
+ <span id="close" onclick="hideAdminFeedbackNotice('feedback_notice_few_contacts')"></span>
17
  </div>
src/views/admin-feedback-notice/many-contacts.php CHANGED
@@ -1,19 +1,24 @@
1
  <div id="ce4wp-admin-feedback-notice" class="notice notice-warning" hidden>
2
- <img class="icon" src="<?php echo CE4WP_PLUGIN_URL . 'assets/images/airplane-purple.svg'; ?>" />
3
- <section class="content">
4
- <p>
5
- <strong><?php echo __( 'Awesome... your audience is growing!', 'ce4wp' ); ?></strong>
6
- </p>
7
- <p>
8
- <?php echo __( 'Your', 'ce4wp' ); ?>
9
- <strong>
10
- <?php // @phpstan-ignore-next-line
11
- echo $ce_number_of_contacts;
12
- ?>
13
- </strong>
14
- <?php echo __( 'contacts are ready for a Creative Mail email campaign. Send one now!', 'ce4wp' ); ?>
15
- </p>
16
- </section>
17
- <button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, 'd25f690a-217a-4d68-9c58-8693965d4673', { source: 'feedback_notice' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)"><?= __( 'Get started', 'ce4wp' ); ?></button>
18
- <span id="close" onclick="hideAdminFeedbackNotice('feedback_notice_many_contacts')"></span>
 
 
 
 
 
19
  </div>
1
  <div id="ce4wp-admin-feedback-notice" class="notice notice-warning" hidden>
2
+ <img class="icon" src="<?php echo esc_url( CE4WP_PLUGIN_URL . 'assets/images/airplane-purple.svg' ); ?>" />
3
+ <section class="content">
4
+ <p>
5
+ <strong>
6
+ <?php esc_html_e( 'Awesome... your audience is growing!', 'creative-mail-by-constant-contact' ); ?>
7
+ </strong>
8
+ </p>
9
+ <p>
10
+ <?php esc_html_e( 'Your', 'creative-mail-by-constant-contact' ); ?>
11
+ <strong>
12
+ <?php
13
+ // @phpstan-ignore-next-line
14
+ echo esc_attr( $ce_number_of_contacts );
15
+ ?>
16
+ </strong>
17
+ <?php esc_html_e( 'contacts are ready for a Creative Mail email campaign. Send one now!', 'creative-mail-by-constant-contact' ); ?>
18
+ </p>
19
+ </section>
20
+ <button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, 'd25f690a-217a-4d68-9c58-8693965d4673', { source: 'feedback_notice' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
21
+ <?php esc_html_e( 'Get started', 'creative-mail-by-constant-contact' ); ?>
22
+ </button>
23
+ <span id="close" onclick="hideAdminFeedbackNotice('feedback_notice_many_contacts')"></span>
24
  </div>
src/views/admin-feedback-notice/sync-disabled.php CHANGED
@@ -1,17 +1,21 @@
1
  <div id="ce4wp-admin-feedback-notice" class="notice notice-warning" hidden>
2
- <span class="icon dashicons dashicons-groups"></span>
3
- <section class="content">
4
- <p>
5
- <strong>
6
- <?= __( 'Should we sync your contacts with', 'ce4wp' ); ?>
7
- <img class="ce-logo" src="<?= CE4WP_PLUGIN_URL . 'assets/images/admin-dashboard-widget/logo.svg'; ?>" />
8
- ?
9
- </strong>
10
- </p>
11
- <p><?= __( 'Grow your business or blog with the power of email marketing.', 'ce4wp' ); ?></p>
12
- </section>
13
- <a href="<?= esc_url( admin_url( 'admin.php?page=creativemail_settings' ) ); ?>">
14
- <button class="button button-primary"><?= __( 'Sync my contacts', 'ce4wp' ); ?></button>
15
- </a>
16
- <span id="close" onclick="hideAdminFeedbackNotice('feedback_notice_sync_disabled')"></span>
 
 
 
 
17
  </div>
1
  <div id="ce4wp-admin-feedback-notice" class="notice notice-warning" hidden>
2
+ <span class="icon dashicons dashicons-groups"></span>
3
+ <section class="content">
4
+ <p>
5
+ <strong>
6
+ <?php esc_html_e( 'Should we sync your contacts with', 'creative-mail-by-constant-contact' ); ?>
7
+ <img class="ce-logo" src="<?php echo esc_url(CE4WP_PLUGIN_URL . 'assets/images/admin-dashboard-widget/logo.svg'); ?>" />
8
+ ?
9
+ </strong>
10
+ </p>
11
+ <p>
12
+ <?php esc_html_e( 'Grow your business or blog with the power of email marketing.', 'creative-mail-by-constant-contact' ); ?>
13
+ </p>
14
+ </section>
15
+ <a href="<?php echo esc_url( admin_url( 'admin.php?page=creativemail_settings' ) ); ?>">
16
+ <button class="button button-primary">
17
+ <?php esc_html_e( 'Sync my contacts', 'creative-mail-by-constant-contact' ); ?>
18
+ </button>
19
+ </a>
20
+ <span id="close" onclick="hideAdminFeedbackNotice('feedback_notice_sync_disabled')"></span>
21
  </div>
src/views/admin-get-started-banner.php CHANGED
@@ -1,58 +1,64 @@
1
  <script>
2
  function hideAdminGetStartedBanner () {
3
- document.querySelector('.notice-ce4wp-getting-started').hidden = true;
4
- fetch('<?php // @phpstan-ignore-next-line
5
- echo $ce_hide_banner_url;
6
- ?>', { method: 'POST' })
7
  }
8
  </script>
9
 
10
  <style>
11
  .notice-ce4wp-getting-started {
12
- padding: 1em 3em 1.5em 2em;
13
- display: flex;
14
- position: relative;
15
- overflow: hidden;
16
  }
17
 
18
  .notice-ce4wp-getting-started .content {
19
- flex: 1;
20
  }
21
 
22
  .notice-ce4wp-getting-started .content p {
23
- margin-top: 0;
24
  }
25
 
26
  .notice-ce4wp-getting-started img {
27
- margin: -1em 0 -3em;
28
- align-self: flex-start;
29
  }
30
 
31
  .notice-ce4wp-getting-started #close {
32
- position: absolute;
33
- top: .25em;
34
- right: .25em;
35
- font-size: 2em;
36
- user-select: none;
37
- cursor: pointer;
38
- color: rgba(0, 0, 0, .5);
39
  }
40
 
41
  .notice-ce4wp-getting-started[hidden] {
42
- display: none !important;
43
  }
44
  </style>
45
 
46
  <div class="notice notice-warning notice-ce4wp-getting-started">
47
- <section class="content">
48
- <h1>
49
- <strong><?= __( 'Grow your business with Creative Mail', 'ce4wp') ?></strong>
50
- </h1>
51
- <p><?= __( 'Our intelligent email editor makes it easy to create a professional email.', 'ce4wp') ?></p>
52
- <a href="<?= esc_url( admin_url( 'admin.php?page=creativemail' ) ); ?>">
53
- <button class="button button-primary"><?= __( 'Start free', 'ce4wp') ?></button>
54
- </a>
55
- </section>
56
- <img src="<?= CE4WP_PLUGIN_URL . 'assets/images/admin-get-started-banner.svg'; ?>" />
57
- <span id="close" onclick="hideAdminGetStartedBanner()">&#10005;</span>
 
 
 
 
 
 
58
  </div>
1
  <script>
2
  function hideAdminGetStartedBanner () {
3
+ document.querySelector('.notice-ce4wp-getting-started').hidden = true;
4
+ fetch('<?php // @phpstan-ignore-next-line
5
+ echo esc_html($ce_hide_banner_url);
6
+ ?>', { method: 'POST' })
7
  }
8
  </script>
9
 
10
  <style>
11
  .notice-ce4wp-getting-started {
12
+ padding: 1em 3em 1.5em 2em;
13
+ display: flex;
14
+ position: relative;
15
+ overflow: hidden;
16
  }
17
 
18
  .notice-ce4wp-getting-started .content {
19
+ flex: 1;
20
  }
21
 
22
  .notice-ce4wp-getting-started .content p {
23
+ margin-top: 0;
24
  }
25
 
26
  .notice-ce4wp-getting-started img {
27
+ margin: -1em 0 -3em;
28
+ align-self: flex-start;
29
  }
30
 
31
  .notice-ce4wp-getting-started #close {
32
+ position: absolute;
33
+ top: .25em;
34
+ right: .25em;
35
+ font-size: 2em;
36
+ user-select: none;
37
+ cursor: pointer;
38
+ color: rgba(0, 0, 0, .5);
39
  }
40
 
41
  .notice-ce4wp-getting-started[hidden] {
42
+ display: none !important;
43
  }
44
  </style>
45
 
46
  <div class="notice notice-warning notice-ce4wp-getting-started">
47
+ <section class="content">
48
+ <h1>
49
+ <strong>
50
+ <?php esc_html_e( 'Grow your business with Creative Mail', 'creative-mail-by-constant-contact'); ?>
51
+ </strong>
52
+ </h1>
53
+ <p>
54
+ <?php esc_html_e( 'Our intelligent email editor makes it easy to create a professional email.', 'creative-mail-by-constant-contact'); ?>
55
+ </p>
56
+ <a href="<?php echo esc_url( admin_url( 'admin.php?page=creativemail' ) ); ?>">
57
+ <button class="button button-primary">
58
+ <?php esc_html_e( 'Start free', 'creative-mail-by-constant-contact'); ?>
59
+ </button>
60
+ </a>
61
+ </section>
62
+ <img src="<?php echo esc_url(CE4WP_PLUGIN_URL . 'assets/images/admin-get-started-banner.svg'); ?>" />
63
+ <span id="close" onclick="hideAdminGetStartedBanner()">&#10005;</span>
64
  </div>
src/views/available-integrations.php CHANGED
@@ -4,44 +4,44 @@ use CreativeMail\CreativeMail;
4
  use CreativeMail\Helpers\EnvironmentHelper;
5
 
6
  $supported_integrations = CreativeMail::get_instance()->get_integration_manager()->get_supported_integrations(true);
7
- $active_plugin_count = count(CreativeMail::get_instance()->get_integration_manager()->get_active_plugins());
8
- $title = $active_plugin_count == 0 ? 'We support contact synchronization from the following plugins:' : 'Plugins we also support';
9
- $title_class = $active_plugin_count == 0 ? 'ce4wp-body2' : 'ce4wp-plugin-support-title';
10
 
11
  ?>
12
  <script type="application/javascript">
13
- function showPluginModal(name, url) {
14
- if (url == null) {
15
- return
16
- }
17
- // Check if url is relative
18
- if (url.indexOf('plugin-install.php') >= 0) {
19
- document.getElementById('plugin-store-title').textContent = name;
20
- document.getElementById('plugin-store-iframe').src = url;
21
- document.getElementById('plugin-store-iframe').title = name;
22
- document.getElementById('plugin-store-modal').style.display = "block";
23
- } else {
24
- var win = window.open(url, '_blank');
25
- win.focus();
26
- }
27
- }
28
 
29
- function closePluginModal() {
30
- document.getElementById('plugin-store-modal').style.display = "none";
31
- }
32
  </script>
33
- <span class="ce4wp-typography-root <?php echo $title_class ?>" style="margin: 40px 0 20px 0; display: block">
34
- <?= __($title, 'ce4wp') ?>
35
  </span>
36
  <div style="color: rgba(0, 0, 0, 0.6);" class="ce4wp-grid">
37
- <?php
38
- foreach ($supported_integrations as $supported_integration) {
39
- if ($supported_integration->is_hidden_from_suggestions()) {
40
- continue;
41
- }
42
- $path = '/assets/p/universal/wordpress-plugin/' . $supported_integration->get_slug() . '.png';
43
- $plugin_image = EnvironmentHelper::get_app_url() . $path;
44
- echo '<div class="ce4wp-grid-item">
45
  <div class="ce4wp-settings-card" onclick="showPluginModal(&quot;' . esc_html($supported_integration->get_name()) . '&quot;,&quot;' . esc_attr($supported_integration->get_url()) . '&quot;)">
46
  <div class="ce4wp-grid">
47
  <div class="ce4wp-grid-item ce4wp-grid-xs-2">
@@ -57,52 +57,46 @@ $title_class = $active_plugin_count == 0 ? 'ce4wp-body2' : 'ce4wp-plugin-support
57
  </div>
58
  </div>
59
  ';
60
- }
61
- ?>
62
  </div>
63
 
64
  <!-- plugin store modal -->
65
- <div id="plugin-store-modal" role="presentation" class="ce4wp-dialog-root" height="auto" variant="default"
66
- style="display: none;">
67
- <div class="ce4wp-backdrop-root" aria-hidden="true" style="opacity: 1; "></div>
68
-
69
- <div class="ce4wp-dialog-container" role="none presentation" tabindex="-1"
70
- style="opacity: 1; ">
71
-
72
- <div class="ce4wp-dialog-wrapper" style="max-width: 1200px" role="dialog">
73
- <div width="100%" class="ce4wp-dialog-header">
74
- <div class="ce4wp-dialog-header-title">
75
- <div class="ce4wp-dialog-header-title-wrapper">
76
- <div class="ce4wp-dialog-header-title-wrapper-content">
77
- <h3 class="ce4wp-typography-root ce4wp-typography-h3" id="plugin-store-title"></h3>
78
- </div>
79
- </div>
80
- </div>
81
- <div class="ce4wp-dialog-header-close">
82
- <div class="ce4wp-dialog-header-close-wrapper" onclick="closePluginModal()">
83
- <div class="ce4wp-dialog-header-close-wrapper-button">
84
- <svg width="24" height="24" viewBox="0 0 24 24" fill="black"
85
- xmlns="http://www.w3.org/2000/svg">
86
- <path
87
- d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
88
- </svg>
89
- </div>
90
- </div>
91
- </div>
92
- </div>
93
- <div height="auto" class="ce4wp-dialog-content">
94
- <iframe frameborder="0"
95
- hspace="0"
96
- allowtransparency="true"
97
- src=""
98
- id="plugin-store-iframe"
99
- name="store-iframe"
100
- style="width: 100%; height: calc(100vh - 400px)"
101
- title="">This feature requires inline frames. You have iframes disabled or your browser does not
102
- support them.
103
- </iframe>
104
- </div>
105
- </div>
106
- </div>
107
  </div>
108
 
4
  use CreativeMail\Helpers\EnvironmentHelper;
5
 
6
  $supported_integrations = CreativeMail::get_instance()->get_integration_manager()->get_supported_integrations(true);
7
+ $active_plugin_count = count(CreativeMail::get_instance()->get_integration_manager()->get_active_plugins());
8
+ $ce4wp_title = 0 == $active_plugin_count ? 'We support contact synchronization from the following plugins:' : 'Plugins we also support';
9
+ $title_class = 0 == $active_plugin_count ? 'ce4wp-body2' : 'ce4wp-plugin-support-title';
10
 
11
  ?>
12
  <script type="application/javascript">
13
+ function showPluginModal(name, url) {
14
+ if (url == null) {
15
+ return
16
+ }
17
+ // Check if url is relative.
18
+ if (url.indexOf('plugin-install.php') >= 0) {
19
+ document.getElementById('plugin-store-title').textContent = name;
20
+ document.getElementById('plugin-store-iframe').src = url;
21
+ document.getElementById('plugin-store-iframe').title = name;
22
+ document.getElementById('plugin-store-modal').style.display = "block";
23
+ } else {
24
+ var win = window.open(url, '_blank');
25
+ win.focus();
26
+ }
27
+ }
28
 
29
+ function closePluginModal() {
30
+ document.getElementById('plugin-store-modal').style.display = "none";
31
+ }
32
  </script>
33
+ <span class="ce4wp-typography-root <?php echo esc_attr($title_class); ?>" style="margin: 40px 0 20px 0; display: block">
34
+ <?php echo esc_html($ce4wp_title); ?>
35
  </span>
36
  <div style="color: rgba(0, 0, 0, 0.6);" class="ce4wp-grid">
37
+ <?php
38
+ foreach ( $supported_integrations as $supported_integration ) {
39
+ if ( $supported_integration->is_hidden_from_suggestions() ) {
40
+ continue;
41
+ }
42
+ $ce4wp_path = '/assets/p/universal/wordpress-plugin/' . $supported_integration->get_slug() . '.png';
43
+ $plugin_image = EnvironmentHelper::get_app_url() . $ce4wp_path;
44
+ echo '<div class="ce4wp-grid-item">
45
  <div class="ce4wp-settings-card" onclick="showPluginModal(&quot;' . esc_html($supported_integration->get_name()) . '&quot;,&quot;' . esc_attr($supported_integration->get_url()) . '&quot;)">
46
  <div class="ce4wp-grid">
47
  <div class="ce4wp-grid-item ce4wp-grid-xs-2">
57
  </div>
58
  </div>
59
  ';
60
+ }
61
+ ?>
62
  </div>
63
 
64
  <!-- plugin store modal -->
65
+ <div id="plugin-store-modal" role="presentation" class="ce4wp-dialog-root" height="auto" variant="default" style="display: none;">
66
+ <div class="ce4wp-backdrop-root" aria-hidden="true" style="opacity: 1; "></div>
67
+ <div class="ce4wp-dialog-container" role="none presentation" tabindex="-1" style="opacity: 1; ">
68
+ <div class="ce4wp-dialog-wrapper" style="max-width: 1200px" role="dialog">
69
+ <div width="100%" class="ce4wp-dialog-header">
70
+ <div class="ce4wp-dialog-header-title">
71
+ <div class="ce4wp-dialog-header-title-wrapper">
72
+ <div class="ce4wp-dialog-header-title-wrapper-content">
73
+ <h3 class="ce4wp-typography-root ce4wp-typography-h3" id="plugin-store-title"></h3>
74
+ </div>
75
+ </div>
76
+ </div>
77
+ <div class="ce4wp-dialog-header-close">
78
+ <div class="ce4wp-dialog-header-close-wrapper" onclick="closePluginModal()">
79
+ <div class="ce4wp-dialog-header-close-wrapper-button">
80
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="black" xmlns="http://www.w3.org/2000/svg">
81
+ <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
82
+ </svg>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ </div>
87
+ <div height="auto" class="ce4wp-dialog-content">
88
+ <iframe frameborder="0"
89
+ hspace="0"
90
+ allowtransparency="true"
91
+ src=""
92
+ id="plugin-store-iframe"
93
+ name="store-iframe"
94
+ style="width: 100%; height: calc(100vh - 400px)"
95
+ title="">
96
+ <?php esc_html_e( 'This feature requires inline frames. You have iframes disabled or your browser does not support them.', 'creative-mail-by-constant-contact' ); ?>
97
+ </iframe>
98
+ </div>
99
+ </div>
100
+ </div>
 
 
 
 
 
 
101
  </div>
102
 
src/views/contact-sync.php CHANGED
@@ -3,24 +3,26 @@ use CreativeMail\CreativeMail;
3
  use CreativeMail\Helpers\EnvironmentHelper;
4
  use CreativeMail\Helpers\OptionsHelper;
5
 
6
- $activated_plugins = CreativeMail::get_instance()->get_integration_manager()->get_active_plugins();
7
- $contact_sync_available = !empty(array_filter($activated_plugins, function ($item) {
8
- return !$item->is_hidden_from_active_list();
9
- }));
10
- $supported_plugin_available = !empty(CreativeMail::get_instance()->get_integration_manager()->get_supported_integrations(true))
11
- ?>
12
 
13
  <div class="ce4wp-card">
14
- <div class="ce4wp-px-4 ce4wp-py-4">
15
- <h2 class="ce4wp-typography-root ce4wp-typography-h2 ce4wp-mb-2"><?= __( 'Contact Sync', 'ce4wp' ); ?></h2>
16
- <?php
17
- if ($contact_sync_available) {
18
- include 'activated-integrations.php';
19
- }
20
- if($supported_plugin_available){
21
- include 'available-integrations.php';
22
- }
23
- include 'creative-mail-form-banner.php'
24
- ?>
25
- </div>
 
 
26
  </div>
3
  use CreativeMail\Helpers\EnvironmentHelper;
4
  use CreativeMail\Helpers\OptionsHelper;
5
 
6
+ $activated_plugins = CreativeMail::get_instance()->get_integration_manager()->get_active_plugins();
7
+ $contact_sync_available = ! empty(array_filter($activated_plugins, function ( $item ) {
8
+ return ! $item->is_hidden_from_active_list();
9
+ }));
10
+ $supported_plugin_available = ! empty(CreativeMail::get_instance()->get_integration_manager()->get_supported_integrations(true))
11
+ ?>
12
 
13
  <div class="ce4wp-card">
14
+ <div class="ce4wp-px-4 ce4wp-py-4">
15
+ <h2 class="ce4wp-typography-root ce4wp-typography-h2 ce4wp-mb-2">
16
+ <?php esc_html_e( 'Contact Sync', 'creative-mail-by-constant-contact' ); ?>
17
+ </h2>
18
+ <?php
19
+ if ( $contact_sync_available ) {
20
+ include 'activated-integrations.php';
21
+ }
22
+ if ( $supported_plugin_available ) {
23
+ include 'available-integrations.php';
24
+ }
25
+ require 'creative-mail-form-banner.php'
26
+ ?>
27
+ </div>
28
  </div>
src/views/creative-mail-form-banner.php CHANGED
@@ -1,69 +1,74 @@
1
  <script type="application/javascript">
2
- function ce4wpShowPluginModal() {
3
- document.getElementById('ce4wp-show-me-how-modal').style.display = "block";
4
- }
5
 
6
- function ce4wpClosePluginModal() {
7
- document.getElementById('ce4wp-show-me-how-modal').style.display = "none";
8
- }
9
  </script>
10
  <div class="ce4wp-banner">
11
- <div class="ce4wp-banner-image">
12
- <img src="<?php echo CE4WP_PLUGIN_URL . 'assets/images/banner-image_collect.svg'; ?>" alt="Creative mail form is here">
13
- </div>
14
- <div class="ce4wp-content">
15
- <h2><?= __( 'The Creative Mail form is here!', 'ce4wp' ); ?></h2>
16
- <p class="ce4wp-typography-body">
17
- <?= __( 'Contacts that sign up can now be assigned to a contact list automatically. Add the Creative Mail block anywhere on your site.', 'ce4wp' ); ?>
18
- <a class="ce4wp_bold_link" onclick="ce4wpShowPluginModal()">
19
- <?= __( 'Show me how!', 'ce4wp' ); ?>
20
- </a>
21
- </p>
22
- </div>
 
 
23
  </div>
24
  <!-- show me how modal -->
25
- <div id="ce4wp-show-me-how-modal" role="presentation" class="ce4wp-dialog-root ce4wp-show-me-how-modal" height="auto" variant="default"
26
- style="display: none;">
27
- <div class="ce4wp-backdrop-root" aria-hidden="true" style="opacity: 1; "></div>
28
-
29
- <div class="ce4wp-dialog-container" role="none presentation" tabindex="-1"
30
- style="opacity: 1; ">
31
-
32
- <div class="ce4wp-dialog-wrapper" style="max-width: 700px" role="dialog">
33
- <div width="100%" class="ce4wp-dialog-header ce4wp-show-me-how-header" style='background-image: url("<?php echo CE4WP_PLUGIN_URL . 'assets/images/post-boxes.svg'; ?>")'>
34
- <div class="ce4wp-dialog-header-close">
35
- <div class="ce4wp-dialog-header-close-wrapper" onclick="ce4wpClosePluginModal()">
36
- <div class="ce4wp-dialog-header-close-wrapper-button">
37
- <svg width="24" height="24" viewBox="0 0 24 24" fill="black"
38
- xmlns="http://www.w3.org/2000/svg">
39
- <path
40
- d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
41
- </svg>
42
- </div>
43
- </div>
44
- </div>
45
- </div>
46
- <div height="auto" class="ce4wp-dialog-content">
47
- <div class="ce4wp-d-flex ">
48
- <div>
49
- <img class="ce4wp-show-me-how-screenshot" src="<?php echo CE4WP_PLUGIN_URL . 'assets/images/screenshot-creative-mail-form.png'; ?>" alt="Creative Mail screenshot">
50
- </div>
51
- <div class="ce4wp-ml-6">
52
- <p class="ce4wp-typography-body">
53
- <?= __( 'Adding a subscription form to your WordPress site is easy. Actually we’ve already prepared a form for you.', 'ce4wp' ); ?>
54
- </p>
55
- </br>
56
- <p class="ce4wp-typography-body">
57
- <?= __( 'Just go to any page on your site in the WordPress editor and click the “Add block” button. Select the
58
- Creative Mail contact form from the block recipes and you’re set.', 'ce4wp' ); ?>
59
- </p>
60
- </br>
61
- <p class="ce4wp-typography-body">
62
- <?= __( 'It’s that easy.', 'ce4wp' ); ?>
63
- </p>
64
- </div>
65
- </div>
66
- </div>
67
- </div>
68
- </div>
 
 
 
69
  </div>
1
  <script type="application/javascript">
2
+ function ce4wpShowPluginModal() {
3
+ document.getElementById('ce4wp-show-me-how-modal').style.display = "block";
4
+ }
5
 
6
+ function ce4wpClosePluginModal() {
7
+ document.getElementById('ce4wp-show-me-how-modal').style.display = "none";
8
+ }
9
  </script>
10
  <div class="ce4wp-banner">
11
+ <div class="ce4wp-banner-image">
12
+ <img src="<?php echo esc_url( CE4WP_PLUGIN_URL . 'assets/images/banner-image_collect.svg' ); ?>" alt="Creative mail form is here">
13
+ </div>
14
+ <div class="ce4wp-content">
15
+ <h2>
16
+ <?php esc_html_e( 'The Creative Mail form is here!', 'creative-mail-by-constant-contact' ); ?>
17
+ </h2>
18
+ <p class="ce4wp-typography-body">
19
+ <?php esc_html_e( 'Contacts that sign up can now be assigned to a contact list automatically. Add the Creative Mail block anywhere on your site.', 'creative-mail-by-constant-contact' ); ?>
20
+ <a class="ce4wp_bold_link" onclick="ce4wpShowPluginModal()">
21
+ <?php esc_html_e( 'Show me how!', 'creative-mail-by-constant-contact' ); ?>
22
+ </a>
23
+ </p>
24
+ </div>
25
  </div>
26
  <!-- show me how modal -->
27
+ <div id="ce4wp-show-me-how-modal"
28
+ role="presentation"
29
+ class="ce4wp-dialog-root ce4wp-show-me-how-modal"
30
+ height="auto"
31
+ variant="default"
32
+ style="display: none;">
33
+ <div class="ce4wp-backdrop-root" aria-hidden="true" style="opacity: 1; "></div>
34
+ <div class="ce4wp-dialog-container" role="none presentation" tabindex="-1" style="opacity: 1; ">
35
+ <div class="ce4wp-dialog-wrapper" style="max-width: 700px" role="dialog">
36
+ <div width="100%" class="ce4wp-dialog-header ce4wp-show-me-how-header" style='background-image: url("<?php echo esc_url( CE4WP_PLUGIN_URL . 'assets/images/post-boxes.svg' ); ?>")'>
37
+ <div class="ce4wp-dialog-header-close">
38
+ <div class="ce4wp-dialog-header-close-wrapper" onclick="ce4wpClosePluginModal()">
39
+ <div class="ce4wp-dialog-header-close-wrapper-button">
40
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="black"
41
+ xmlns="http://www.w3.org/2000/svg">
42
+ <path
43
+ d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
44
+ </svg>
45
+ </div>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ <div height="auto" class="ce4wp-dialog-content">
50
+ <div class="ce4wp-d-flex ">
51
+ <div>
52
+ <img class="ce4wp-show-me-how-screenshot" src="<?php echo esc_url( CE4WP_PLUGIN_URL . 'assets/images/screenshot-creative-mail-form.png' ); ?>" alt="Creative Mail screenshot">
53
+ </div>
54
+ <div class="ce4wp-ml-6">
55
+ <p class="ce4wp-typography-body">
56
+ <?php esc_html_e( 'Adding a subscription form to your WordPress site is easy. Actually we’ve already prepared a form for you.', 'creative-mail-by-constant-contact' ); ?>
57
+ </p>
58
+ </br>
59
+ <p class="ce4wp-typography-body">
60
+ <?php
61
+ esc_html_e( 'Just go to any page on your site in the WordPress editor and click the “Add block” button. Select the
62
+ Creative Mail contact form from the block recipes and you’re set.', 'creative-mail-by-constant-contact' );
63
+ ?>
64
+ </p>
65
+ </br>
66
+ <p class="ce4wp-typography-body">
67
+ <?php esc_html_e( 'It’s that easy.', 'creative-mail-by-constant-contact' ); ?>
68
+ </p>
69
+ </div>
70
+ </div>
71
+ </div>
72
+ </div>
73
+ </div>
74
  </div>
src/views/dashboard-open-creative-mail.php CHANGED
@@ -1,47 +1,62 @@
1
  <p class="ce4wp-typography-root ce4wp-subtitle ce4wp-mt-4 ce4wp-mb-4">
2
- <?= __( 'You’re all set! Creative Mail and WordPress have been linked.', 'ce4wp'); ?>
3
- </p>
4
  <div id="ce4wploaded">
5
- <a id='ce4wp-go-button' onclick="ce4wpNavigateToDashboard(this, 'd25f690a-217a-4d68-9c58-8693965d4673', { source: 'ce4wp_dashboard' }, ce4wpDashboardStartCallback, ce4wpDashboardFinishCallback)" class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-button-contained-primary ce4wp-mt-2" tabindex="0" type="button" data-element-type="button">
6
- <span class="ce4wp-button-label ce4wp-hide-on-mobile" style="width: 100%;"><?= __( 'Open your Creative Mail dashboard', 'ce4wp'); ?><span class="ce4wp-button-endIcon">
7
- <svg class="ce4wp-Svgicon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
8
- <path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"></path>
9
- </svg>
10
- </span>
11
- </span>
12
- <span class="ce4wp-button-label ce4wp-show-on-mobile" style="width: 100%;"><?= __( 'Open Creative Mail dashboard', 'ce4wp'); ?>
13
- </span>
14
- </a>
15
- <h6 id='ce4wp-sub-apps-title' class="ce4wp-typography-root ce4wp-typography-h6 ce4wp-mt-4 ce4wp-mb-3">
16
- <?= __( 'Or jump straight into:', 'ce4wp'); ?>
17
- </h6>
18
- <div id='ce4wp-sub-apps-container' class="ce4wp-grid ce4wp-mt-3">
19
- <div class="ce4wp-grid-item" onclick="ce4wpNavigateToDashboard(this, '1fabdbe2-95ed-4e1e-a2f3-ba0278f5096f', { source: 'ce4wp_dashboard' }, ce4wpDashboardStartCallback, ce4wpDashboardFinishCallback)">
20
- <div class="ce4wp-grid-item-card ce4wp-mb-4">
21
- <div class="ce4wp-grid-item-card-media" title="WooCommerce emails" style="background-image: url(<?php echo CE4WP_PLUGIN_URL . 'assets/images/tile-img-woocommerce.svg'; ?>);"></div>
22
- <div class="ce4wp-grid-item-card-content-root">
23
- <h4 class="ce4wp-typography-root ce4wp-typography-h4"><?= __( 'WooCommerce emails', 'ce4wp'); ?></h4>
24
- <p class="ce4wp-pt-2 ce4wp-typography-root ce4wp-body2"><?= __( 'Spice up your transactional WooCommerce store emails.', 'ce4wp'); ?></p>
25
- </div>
26
- </div>
27
- </div>
28
- <div class="ce4wp-grid-item" onclick="ce4wpNavigateToDashboard(this, 'd5baea05-c603-4cca-852e-f8e82414f6b0', { source: 'ce4wp_dashboard' }, ce4wpDashboardStartCallback, ce4wpDashboardFinishCallback)">
29
- <div class="ce4wp-grid-item-card ce4wp-mb-4">
30
- <div class="ce4wp-grid-item-card-media" title="Email Automations" style="background-image: url(<?php echo CE4WP_PLUGIN_URL . 'assets/images/tile-img-automations.svg'; ?>);"></div>
31
- <div class="ce4wp-grid-item-card-content-root">
32
- <h4 class="ce4wp-typography-root ce4wp-typography-h4"><?= __( 'Email Automations', 'ce4wp'); ?></h4>
33
- <p class="ce4wp-pt-2 ce4wp-typography-root ce4wp-body2"><?= __( 'Engage your audience without lifting a finger.', 'ce4wp'); ?></p>
34
- </div>
35
- </div>
36
- </div>
37
- <div class="ce4wp-grid-item" onclick="ce4wpNavigateToDashboard(this, '836b20fc-9ff1-41b2-912b-a8646caf05a4', { source: 'ce4wp_dashboard' }, ce4wpDashboardStartCallback, ce4wpDashboardFinishCallback)">
38
- <div class="ce4wp-grid-item-card ce4wp-mb-4">
39
- <div class="ce4wp-grid-item-card-media" title="Contact Management" style="background-image: url(<?php echo CE4WP_PLUGIN_URL . 'assets/images/tile-img-contactmanagement.svg'; ?>);"></div>
40
- <div class="ce4wp-grid-item-card-content-root">
41
- <h4 class="ce4wp-typography-root ce4wp-typography-h4"><?= __( 'Contact Management', 'ce4wp'); ?></h4>
42
- <p class="ce4wp-pt-2 ce4wp-typography-root ce4wp-body2"><?= __( 'Manage your contacts and email lists, all in one place.', 'ce4wp'); ?></p>
43
- </div>
44
- </div>
45
- </div>
46
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  </div>
1
  <p class="ce4wp-typography-root ce4wp-subtitle ce4wp-mt-4 ce4wp-mb-4">
2
+ <?php esc_html_e( 'You’re all set! Creative Mail and WordPress have been linked.', 'creative-mail-by-constant-contact'); ?>
3
+ </p>
4
  <div id="ce4wploaded">
5
+ <a id='ce4wp-go-button' onclick="ce4wpNavigateToDashboard(this, 'd25f690a-217a-4d68-9c58-8693965d4673', { source: 'ce4wp_dashboard' }, ce4wpDashboardStartCallback, ce4wpDashboardFinishCallback)" class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-button-contained-primary ce4wp-mt-2" tabindex="0" type="button" data-element-type="button">
6
+ <span class="ce4wp-button-label ce4wp-hide-on-mobile" style="width: 100%;">
7
+ <?php esc_html_e( 'Open your Creative Mail dashboard', 'creative-mail-by-constant-contact'); ?>
8
+ <span class="ce4wp-button-endIcon">
9
+ <svg class="ce4wp-Svgicon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
10
+ <path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"></path>
11
+ </svg>
12
+ </span>
13
+ </span>
14
+ <span class="ce4wp-button-label ce4wp-show-on-mobile" style="width: 100%;">
15
+ <?php esc_html_e( 'Open Creative Mail dashboard', 'creative-mail-by-constant-contact'); ?>
16
+ </span>
17
+ </a>
18
+ <h6 id='ce4wp-sub-apps-title' class="ce4wp-typography-root ce4wp-typography-h6 ce4wp-mt-4 ce4wp-mb-3">
19
+ <?php esc_html_e( 'Or jump straight into:', 'creative-mail-by-constant-contact'); ?>
20
+ </h6>
21
+ <div id='ce4wp-sub-apps-container' class="ce4wp-grid ce4wp-mt-3">
22
+ <div class="ce4wp-grid-item" onclick="ce4wpNavigateToDashboard(this, '1fabdbe2-95ed-4e1e-a2f3-ba0278f5096f', { source: 'ce4wp_dashboard' }, ce4wpDashboardStartCallback, ce4wpDashboardFinishCallback)">
23
+ <div class="ce4wp-grid-item-card ce4wp-mb-4">
24
+ <div class="ce4wp-grid-item-card-media" title="WooCommerce emails" style="background-image: url(<?php echo esc_url( CE4WP_PLUGIN_URL . 'assets/images/tile-img-woocommerce.svg' ); ?>);"></div>
25
+ <div class="ce4wp-grid-item-card-content-root">
26
+ <h4 class="ce4wp-typography-root ce4wp-typography-h4">
27
+ <?php esc_html_e( 'WooCommerce emails', 'creative-mail-by-constant-contact'); ?>
28
+ </h4>
29
+ <p class="ce4wp-pt-2 ce4wp-typography-root ce4wp-body2">
30
+ <?php esc_html_e( 'Spice up your transactional WooCommerce store emails.', 'creative-mail-by-constant-contact'); ?>
31
+ </p>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ <div class="ce4wp-grid-item" onclick="ce4wpNavigateToDashboard(this, 'd5baea05-c603-4cca-852e-f8e82414f6b0', { source: 'ce4wp_dashboard' }, ce4wpDashboardStartCallback, ce4wpDashboardFinishCallback)">
36
+ <div class="ce4wp-grid-item-card ce4wp-mb-4">
37
+ <div class="ce4wp-grid-item-card-media" title="Email Automations" style="background-image: url(<?php echo esc_url( CE4WP_PLUGIN_URL . 'assets/images/tile-img-automations.svg' ); ?>);"></div>
38
+ <div class="ce4wp-grid-item-card-content-root">
39
+ <h4 class="ce4wp-typography-root ce4wp-typography-h4">
40
+ <?php esc_html_e( 'Email Automations', 'creative-mail-by-constant-contact'); ?>
41
+ </h4>
42
+ <p class="ce4wp-pt-2 ce4wp-typography-root ce4wp-body2">
43
+ <?php esc_html_e( 'Engage your audience without lifting a finger.', 'creative-mail-by-constant-contact'); ?>
44
+ </p>
45
+ </div>
46
+ </div>
47
+ </div>
48
+ <div class="ce4wp-grid-item" onclick="ce4wpNavigateToDashboard(this, '836b20fc-9ff1-41b2-912b-a8646caf05a4', { source: 'ce4wp_dashboard' }, ce4wpDashboardStartCallback, ce4wpDashboardFinishCallback)">
49
+ <div class="ce4wp-grid-item-card ce4wp-mb-4">
50
+ <div class="ce4wp-grid-item-card-media" title="Contact Management" style="background-image: url(<?php echo esc_url( CE4WP_PLUGIN_URL . 'assets/images/tile-img-contactmanagement.svg' ); ?>);"></div>
51
+ <div class="ce4wp-grid-item-card-content-root">
52
+ <h4 class="ce4wp-typography-root ce4wp-typography-h4">
53
+ <?php esc_html_e( 'Contact Management', 'creative-mail-by-constant-contact'); ?>
54
+ </h4>
55
+ <p class="ce4wp-pt-2 ce4wp-typography-root ce4wp-body2">
56
+ <?php esc_html_e( 'Manage your contacts and email lists, all in one place.', 'creative-mail-by-constant-contact'); ?>
57
+ </p>
58
+ </div>
59
+ </div>
60
+ </div>
61
+ </div>
62
  </div>
src/views/dashboard.php CHANGED
@@ -1,68 +1,72 @@
1
  <div class="ce4wp-admin-wrapper">
2
- <header class="ce4wp-swoosh-header"></header>
3
 
4
- <div class="ce4wp-swoosh-container">
5
- <div style="margin-top: 0px;">
6
- <div class="ce4wp-backdrop">
7
- <div class="ce4wp-backdrop-container">
8
- <div class="ce4wp-backdrop-header">
9
- <div class="ce4wp-logo-poppins"></div>
10
- <div>
11
- <img src="<?php echo CE4WP_PLUGIN_URL . 'assets/images/airplane.svg'; ?>" class="ce4wp-airplane" alt="Paper airplane decoration">
12
- </div>
13
- </div>
14
- <div class="ce4wp-card">
15
- <div class="ce4wp-px-4 ce4wp-pt-4">
16
- <h1 class="ce4wp-typography-root ce4wp-typography-h1 ce4wp-inline-block ce4wp-mb-3">
17
- <?= __( 'Intelligent email marketing for', 'ce4wp'); ?><br><?= __( 'WordPress and WooCommerce', 'ce4wp'); ?>
18
- </h1>
19
- <?php
20
- if (in_array('password-protected/password-protected.php', apply_filters('active_plugins', get_option('active_plugins'))) && (bool) get_option( 'password_protected_status' ) ) {
21
- include 'password-protected-notice.php';
22
- }
23
- else {
24
- include 'dashboard-open-creative-mail.php';
25
- }
26
- ?>
27
- <div id="ce4wpskeleton" style="display: none;">
28
- <div class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-mt-2 skeleton-pulse" style="width: 300px; color: #8C8C8C;">
29
- <span class="ce4wp-button-label" style="width: 100%;"><?= __( 'Loading your account...', 'ce4wp'); ?></span>
30
- </div>
31
- <div class="ce4wp-typography-root ce4wp-typography-h6 ce4wp-mt-4 ce4wp-mb-3 skeleton-pulse ce4wp-subapps-skeleton"></div>
32
- <div class="ce4wp-grid ce4wp-mt-3">
33
- <div class="ce4wp-grid-item">
34
- <div class="ce4wp-grid-item-card ce4wp-mb-4">
35
- <div class="ce4wp-grid-item-card-media skeleton-pulse ce4wp-grid-item-card-media-skeleton"></div>
36
- <div class="ce4wp-grid-item-card-content-root skeleton-pulse">
37
- <div class="ce4wp-grid-item-card-content-skeleton-title"></div>
38
- <div class="ce4wp-grid-item-card-content-skeleton-description"></div>
39
- </div>
40
- </div>
41
- </div>
42
- <div class="ce4wp-grid-item">
43
- <div class="ce4wp-grid-item-card ce4wp-mb-4">
44
- <div class="ce4wp-grid-item-card-media skeleton-pulse ce4wp-grid-item-card-media-skeleton"></div>
45
- <div class="ce4wp-grid-item-card-content-root skeleton-pulse">
46
- <div class="ce4wp-grid-item-card-content-skeleton-title"></div>
47
- <div class="ce4wp-grid-item-card-content-skeleton-description"></div>
48
- </div>
49
- </div>
50
- </div>
51
- <div class="ce4wp-grid-item">
52
- <div class="ce4wp-grid-item-card ce4wp-mb-4">
53
- <div class="ce4wp-grid-item-card-media skeleton-pulse ce4wp-grid-item-card-media-skeleton"></div>
54
- <div class="ce4wp-grid-item-card-content-root skeleton-pulse">
55
- <div class="ce4wp-grid-item-card-content-skeleton-title"></div>
56
- <div class="ce4wp-grid-item-card-content-skeleton-description"></div>
57
- </div>
58
- </div>
59
- </div>
60
- </div>
61
- </div>
62
- </div>
63
- </div>
64
- </div>
65
- </div>
66
- </div>
67
- </div>
 
 
 
 
68
  </div>
1
  <div class="ce4wp-admin-wrapper">
2
+ <header class="ce4wp-swoosh-header"></header>
3
 
4
+ <div class="ce4wp-swoosh-container">
5
+ <div style="margin-top: 0;">
6
+ <div class="ce4wp-backdrop">
7
+ <div class="ce4wp-backdrop-container">
8
+ <div class="ce4wp-backdrop-header">
9
+ <div class="ce4wp-logo-poppins"></div>
10
+ <div>
11
+ <img src="<?php echo esc_url( CE4WP_PLUGIN_URL . 'assets/images/airplane.svg' ); ?>" class="ce4wp-airplane" alt="Paper airplane decoration">
12
+ </div>
13
+ </div>
14
+ <div class="ce4wp-card">
15
+ <div class="ce4wp-px-4 ce4wp-pt-4">
16
+ <h1 class="ce4wp-typography-root ce4wp-typography-h1 ce4wp-inline-block ce4wp-mb-3">
17
+ <?php esc_html_e( 'Intelligent email marketing for', 'creative-mail-by-constant-contact'); ?>
18
+ <br>
19
+ <?php esc_html_e( 'WordPress and WooCommerce', 'creative-mail-by-constant-contact'); ?>
20
+ </h1>
21
+ <?php
22
+ if ( in_array('password-protected/password-protected.php', apply_filters('active_plugins', get_option('active_plugins')), true)
23
+ && (bool) get_option( 'password_protected_status' ) ) {
24
+ include 'password-protected-notice.php';
25
+ } else {
26
+ include 'dashboard-open-creative-mail.php';
27
+ }
28
+ ?>
29
+ <div id="ce4wpskeleton" style="display: none;">
30
+ <div class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-mt-2 skeleton-pulse" style="width: 300px; color: #8C8C8C;">
31
+ <span class="ce4wp-button-label" style="width: 100%;">
32
+ <?php esc_html_e( 'Loading your account...', 'creative-mail-by-constant-contact'); ?>
33
+ </span>
34
+ </div>
35
+ <div class="ce4wp-typography-root ce4wp-typography-h6 ce4wp-mt-4 ce4wp-mb-3 skeleton-pulse ce4wp-subapps-skeleton"></div>
36
+ <div class="ce4wp-grid ce4wp-mt-3">
37
+ <div class="ce4wp-grid-item">
38
+ <div class="ce4wp-grid-item-card ce4wp-mb-4">
39
+ <div class="ce4wp-grid-item-card-media skeleton-pulse ce4wp-grid-item-card-media-skeleton"></div>
40
+ <div class="ce4wp-grid-item-card-content-root skeleton-pulse">
41
+ <div class="ce4wp-grid-item-card-content-skeleton-title"></div>
42
+ <div class="ce4wp-grid-item-card-content-skeleton-description"></div>
43
+ </div>
44
+ </div>
45
+ </div>
46
+ <div class="ce4wp-grid-item">
47
+ <div class="ce4wp-grid-item-card ce4wp-mb-4">
48
+ <div class="ce4wp-grid-item-card-media skeleton-pulse ce4wp-grid-item-card-media-skeleton"></div>
49
+ <div class="ce4wp-grid-item-card-content-root skeleton-pulse">
50
+ <div class="ce4wp-grid-item-card-content-skeleton-title"></div>
51
+ <div class="ce4wp-grid-item-card-content-skeleton-description"></div>
52
+ </div>
53
+ </div>
54
+ </div>
55
+ <div class="ce4wp-grid-item">
56
+ <div class="ce4wp-grid-item-card ce4wp-mb-4">
57
+ <div class="ce4wp-grid-item-card-media skeleton-pulse ce4wp-grid-item-card-media-skeleton"></div>
58
+ <div class="ce4wp-grid-item-card-content-root skeleton-pulse">
59
+ <div class="ce4wp-grid-item-card-content-skeleton-title"></div>
60
+ <div class="ce4wp-grid-item-card-content-skeleton-description"></div>
61
+ </div>
62
+ </div>
63
+ </div>
64
+ </div>
65
+ </div>
66
+ </div>
67
+ </div>
68
+ </div>
69
+ </div>
70
+ </div>
71
+ </div>
72
  </div>
src/views/onboarding-content.php CHANGED
@@ -1,47 +1,51 @@
1
  <h6 class="ce4wp-typography-root ce4wp-typography-h6 ce4wp-mt-4 ce4wp-mb-2">
2
- <?= __('With Creative Mail your blog posts, store promotions, announcements, event updates and more can be delivered straight into the inbox of your customers and prospects.', 'ce4wp') ?>
3
  </h6>
4
  <h6 class="ce4wp-typography-root ce4wp-typography-h6 ce4wp-mt-4 ce4wp-mb-2">
5
- <?= __('The fine print:', 'ce4wp') ?>
6
  </h6>
7
  <ul class="ce4wp-list-root pb-4 ce4wp-list-padding">
8
- <li class="ce4wp-list-item-root" style="max-width: 550px;">
9
- <div class="ce4wp-list-item-icon-root ce4wp-pr-3 ce4wp-mt-2">
10
- <svg class="ce4wp-svg-icon-root ce4wp-svg-icon-color" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
11
- <path d="M4.75 8.12891L12.6953 0.183594L13.75 1.23828L4.75 10.2383L0.566406 6.05469L1.62109 5L4.75 8.12891Z" fill="#7A5CBD"/>
12
- </svg>
13
- </div>
14
- <div class="ce4wp-list-item-text-root ce4wp-d-flex ce4wp-flex-column ce4wp-m-0">
15
- <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);">
16
- <?= __('By using Creative Mail you’ll share basic information about your site (including your site name and URL) with Constant Contact so that we can retrieve your blog posts, media files and store products for use in your emails;', 'ce4wp') ?>
17
- </p>
18
- </div>
19
- </li>
20
- <li class="ce4wp-list-item-root" style="max-width: 550px;">
21
- <div class="ce4wp-list-item-icon-root ce4wp-pr-3 ce4wp-mt-2">
22
- <svg class="ce4wp-svg-icon-root ce4wp-svg-icon-color" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
23
- <path d="M4.75 8.12891L12.6953 0.183594L13.75 1.23828L4.75 10.2383L0.566406 6.05469L1.62109 5L4.75 8.12891Z" fill="#7A5CBD"/>
24
- </svg>
25
- </div>
26
- <div class="ce4wp-list-item-text-root ce4wp-d-flex ce4wp-flex-column ce4wp-m-0">
27
- <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);">
28
- <?= __('Creative Mail uses tools, including cookies, to improve the performance and experience of the product. For more information you can read our', 'ce4wp') ?> <a href="https://www.endurance.com/privacy/privacy" target="_blank"><?= __('privacy notice', 'ce4wp') ?></a>.
29
- </p>
30
- </div>
31
- </li>
 
 
 
32
  </ul>
33
  <a id='ce4wp-go-button'
34
- target="_blank"
35
- class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-button-contained-primary ce4wp-mb-4 ce4wp-mt-2"
36
- tabindex="0"
37
- type="button"
38
- data-element-type="button"
39
- onclick="ce4wpNavigateToDashboard(this, undefined, { source: 'onboarding' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
40
- <span class="ce4wp-button-label" style="width: 100%;">
41
- <?= __('I Agree and let\'s get started!', 'ce4wp') ?><span class="ce4wp-button-endIcon">
42
- <svg class="ce4wp-Svgicon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
43
- <path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"></path>
44
- </svg>
45
- </span>
46
- </span>
 
47
  </a>
1
  <h6 class="ce4wp-typography-root ce4wp-typography-h6 ce4wp-mt-4 ce4wp-mb-2">
2
+ <?php esc_html_e('With Creative Mail your blog posts, store promotions, announcements, event updates and more can be delivered straight into the inbox of your customers and prospects.', 'creative-mail-by-constant-contact'); ?>
3
  </h6>
4
  <h6 class="ce4wp-typography-root ce4wp-typography-h6 ce4wp-mt-4 ce4wp-mb-2">
5
+ <?php esc_html_e('The fine print:', 'creative-mail-by-constant-contact'); ?>
6
  </h6>
7
  <ul class="ce4wp-list-root pb-4 ce4wp-list-padding">
8
+ <li class="ce4wp-list-item-root" style="max-width: 550px;">
9
+ <div class="ce4wp-list-item-icon-root ce4wp-pr-3 ce4wp-mt-2">
10
+ <svg class="ce4wp-svg-icon-root ce4wp-svg-icon-color" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
11
+ <path d="M4.75 8.12891L12.6953 0.183594L13.75 1.23828L4.75 10.2383L0.566406 6.05469L1.62109 5L4.75 8.12891Z" fill="#7A5CBD"/>
12
+ </svg>
13
+ </div>
14
+ <div class="ce4wp-list-item-text-root ce4wp-d-flex ce4wp-flex-column ce4wp-m-0">
15
+ <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);">
16
+ <?php esc_html_e('By using Creative Mail you’ll share basic information about your site (including your site name and URL) with Constant Contact so that we can retrieve your blog posts, media files and store products for use in your emails;', 'creative-mail-by-constant-contact'); ?>
17
+ </p>
18
+ </div>
19
+ </li>
20
+ <li class="ce4wp-list-item-root" style="max-width: 550px;">
21
+ <div class="ce4wp-list-item-icon-root ce4wp-pr-3 ce4wp-mt-2">
22
+ <svg class="ce4wp-svg-icon-root ce4wp-svg-icon-color" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
23
+ <path d="M4.75 8.12891L12.6953 0.183594L13.75 1.23828L4.75 10.2383L0.566406 6.05469L1.62109 5L4.75 8.12891Z" fill="#7A5CBD"/>
24
+ </svg>
25
+ </div>
26
+ <div class="ce4wp-list-item-text-root ce4wp-d-flex ce4wp-flex-column ce4wp-m-0">
27
+ <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);">
28
+ <?php esc_html_e('Creative Mail uses tools, including cookies, to improve the performance and experience of the product. For more information you can read our', 'creative-mail-by-constant-contact'); ?>
29
+ <a href="https://www.endurance.com/privacy/privacy" target="_blank">
30
+ <?php esc_html_e('privacy notice', 'creative-mail-by-constant-contact'); ?>
31
+ </a>.
32
+ </p>
33
+ </div>
34
+ </li>
35
  </ul>
36
  <a id='ce4wp-go-button'
37
+ target="_blank"
38
+ class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-button-contained-primary ce4wp-mb-4 ce4wp-mt-2"
39
+ tabindex="0"
40
+ type="button"
41
+ data-element-type="button"
42
+ onclick="ce4wpNavigateToDashboard(this, undefined, { source: 'onboarding' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
43
+ <span class="ce4wp-button-label" style="width: 100%;">
44
+ <?php esc_html_e('I Agree and let\'s get started!', 'creative-mail-by-constant-contact'); ?>
45
+ <span class="ce4wp-button-endIcon">
46
+ <svg class="ce4wp-Svgicon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
47
+ <path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"></path>
48
+ </svg>
49
+ </span>
50
+ </span>
51
  </a>
src/views/onboarding.php CHANGED
@@ -1,42 +1,44 @@
1
  <div class="ce4wp-admin-wrapper">
2
- <header class="ce4wp-swoosh-header"></header>
3
 
4
- <div class="ce4wp-swoosh-container">
5
- <div style="margin-top: 0px;">
6
- <div class="ce4wp-backdrop">
7
- <div class="ce4wp-backdrop-container">
8
- <div class="ce4wp-backdrop-header">
9
- <div class="ce4wp-logo-poppins"></div>
10
- <div>
11
- <img src="<?php echo CE4WP_PLUGIN_URL . 'assets/images/airplane.svg'; ?>" class="ce4wp-airplane" alt="Paper airplane decoration">
12
- </div>
13
- </div>
14
- <div class="ce4wp-card">
15
- <div class="ce4wp-px-4 ce4wp-pt-4">
16
- <h1 class="ce4wp-typography-root ce4wp-typography-h1">
17
- <?= __( 'Intelligent email marketing for', 'ce4wp') ?><br /><?= __( 'WordPress and WooCommerce', 'ce4wp') ?>
18
- </h1>
19
- <?php
20
- if (in_array('password-protected/password-protected.php', apply_filters('active_plugins', get_option('active_plugins'))) && (bool) get_option( 'password_protected_status' ) ) {
21
- include 'password-protected-notice.php';
22
- }
23
- else {
24
- include 'onboarding-content.php';
25
- }
26
- ?>
27
- </div>
28
- </div>
29
- </div>
30
- </div>
31
- </div>
32
- </div>
 
 
33
  </div>
34
 
35
  <script type="application/javascript">
36
- let blurred = false;
37
- window.onblur = function() {
38
- blurred = true;
39
- document.getElementById('ce4wp-go-button').style.display = "none";
40
- };
41
- window.onfocus = function() { blurred && (location.reload()); };
42
  </script>
1
  <div class="ce4wp-admin-wrapper">
2
+ <header class="ce4wp-swoosh-header"></header>
3
 
4
+ <div class="ce4wp-swoosh-container">
5
+ <div style="margin-top: 0;">
6
+ <div class="ce4wp-backdrop">
7
+ <div class="ce4wp-backdrop-container">
8
+ <div class="ce4wp-backdrop-header">
9
+ <div class="ce4wp-logo-poppins"></div>
10
+ <div>
11
+ <img src="<?php echo esc_url( CE4WP_PLUGIN_URL . 'assets/images/airplane.svg' ); ?>" class="ce4wp-airplane" alt="Paper airplane decoration">
12
+ </div>
13
+ </div>
14
+ <div class="ce4wp-card">
15
+ <div class="ce4wp-px-4 ce4wp-pt-4">
16
+ <h1 class="ce4wp-typography-root ce4wp-typography-h1">
17
+ <?php esc_html_e( 'Intelligent email marketing for', 'creative-mail-by-constant-contact'); ?>
18
+ <br />
19
+ <?php esc_html_e( 'WordPress and WooCommerce', 'creative-mail-by-constant-contact'); ?>
20
+ </h1>
21
+ <?php
22
+ if ( in_array('password-protected/password-protected.php', apply_filters('active_plugins', get_option('active_plugins')), true)
23
+ && (bool) get_option( 'password_protected_status' ) ) {
24
+ include 'password-protected-notice.php';
25
+ } else {
26
+ include 'onboarding-content.php';
27
+ }
28
+ ?>
29
+ </div>
30
+ </div>
31
+ </div>
32
+ </div>
33
+ </div>
34
+ </div>
35
  </div>
36
 
37
  <script type="application/javascript">
38
+ let blurred = false;
39
+ window.onblur = function() {
40
+ blurred = true;
41
+ document.getElementById('ce4wp-go-button').style.display = "none";
42
+ };
43
+ window.onfocus = function() { blurred && (location.reload()); };
44
  </script>
src/views/password-protected-notice.php CHANGED
@@ -1,12 +1,17 @@
1
  <p class="ce4wp-typography-root ce4wp-typography-h6 ce4wp-mt-4 ce4wp-mb-4">
2
- <?= __( 'With Creative Mail your blog posts, store promotions, announcements, event updates and more can be delivered straight into the inbox of your customers and prospects.', 'ce4wp'); ?>
3
  </p>
4
- <img src="<?php echo CE4WP_PLUGIN_URL . 'assets/images/airplane-folding.png'; ?>" height=100 class="ce4wp-airplane-folding" alt="Paper airplane decoration">
 
 
 
5
  <p class="ce4wp-typography-root ce4wp-typography-h6 ce4wp-mt-4 ce4wp-mb-4">
6
- <?= __( 'We see that you’re using the Password Protected plugin. Creative Mail needs to interact with your WordPress site but this plugin makes that impossible.', 'ce4wp'); ?>
7
  </p>
8
  <p class="ce4wp-typography-root ce4wp-typography-h6-darker ce4wp-mt-4 ce4wp-mb-4">
9
- <?= __( 'Please disable the Password Protected plugin to start using CreativeMail.', 'ce4wp'); ?>
10
  </p>
11
- <a class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-button-contained-orange" href='plugins.php' ><?= __( 'Go to Plugin Settings', 'ce4wp' ); ?></a>
 
 
12
 
1
  <p class="ce4wp-typography-root ce4wp-typography-h6 ce4wp-mt-4 ce4wp-mb-4">
2
+ <?php esc_html_e( 'With Creative Mail your blog posts, store promotions, announcements, event updates and more can be delivered straight into the inbox of your customers and prospects.', 'creative-mail-by-constant-contact'); ?>
3
  </p>
4
+ <img src="<?php echo esc_url( CE4WP_PLUGIN_URL . 'assets/images/airplane-folding.png' ); ?>"
5
+ height=100
6
+ class="ce4wp-airplane-folding"
7
+ alt="Paper airplane decoration">
8
  <p class="ce4wp-typography-root ce4wp-typography-h6 ce4wp-mt-4 ce4wp-mb-4">
9
+ <?php esc_html_e( 'We see that you’re using the Password Protected plugin. Creative Mail needs to interact with your WordPress site but this plugin makes that impossible.', 'creative-mail-by-constant-contact'); ?>
10
  </p>
11
  <p class="ce4wp-typography-root ce4wp-typography-h6-darker ce4wp-mt-4 ce4wp-mb-4">
12
+ <?php esc_html_e( 'Please disable the Password Protected plugin to start using CreativeMail.', 'creative-mail-by-constant-contact'); ?>
13
  </p>
14
+ <a class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-button-contained-orange" href='plugins.php' >
15
+ <?php esc_html_e( 'Go to Plugin Settings', 'creative-mail-by-constant-contact' ); ?>
16
+ </a>
17
 
src/views/pending-setup.php CHANGED
@@ -1,24 +1,28 @@
1
  <p class="ce4wp-typography-root ce4wp-body2 ce4wp-mt-3" style="color: rgba(0, 0, 0, 0.6);">
2
- <?= __( 'Power your WooCommerce Store or WordPress Blog with simple & free email marketing from Constant Contact.
3
- With the official Creative Mail for WooCommerce plugin, your products, blog posts, images and store links
4
- are automatically included as rich shoppable email marketing content for your customers.', 'ce4wp' ); ?>
5
  </p>
6
  <p class="ce4wp-typography-root ce4wp-body2 ce4wp-mt-3" style="color: rgba(0, 0, 0, 0.6);">
7
- <?= __( 'Our included CRM also intelligently pulls in and identifies your WordPress site contacts and WooCommerce store customers.
8
- That makes it easy to build audiences and send targeted customer campaigns.', 'ce4wp' ); ?>
 
 
9
  </p>
10
  <p class="ce4wp-typography-root ce4wp-body2 ce4wp-mt-3" style="color: rgba(0, 0, 0, 0.6);">
11
- <?= __( 'Get free email marketing, 98% deliverability, and Constant Contact rock solid reliability all without ever needing to leave your WP Admin.', 'ce4wp' ); ?>
12
  </p>
13
-
14
-
15
  <p class="ce4wp-typography-root ce4wp-body2 ce4wp-mt-3" style="color: rgba(0, 0, 0, 0.6);">
16
- <?= __( 'Having problems setting up your account, click the \'reset\' button below to start over.', 'ce4wp' ); ?>
17
  </p>
18
  <div class="ce4wp-kvp">
19
- <form name="disconnect" action="" method="post">
20
- <input name="disconnect_nonce" type="hidden" value="<?=wp_create_nonce('disconnect')?>" />
21
- <input type="hidden" name="action" value="disconnect" />
22
- <input name="disconnect_button" type="submit" class="ce4wp-button-text-primary destructive ce4wp-right" id="disconnect-instance" value="Reset" />
23
- </form>
 
 
 
 
24
  </div>
1
  <p class="ce4wp-typography-root ce4wp-body2 ce4wp-mt-3" style="color: rgba(0, 0, 0, 0.6);">
2
+ <?php esc_html_e( 'Power your WooCommerce Store or WordPress Blog with simple & free email marketing from Constant Contact.
3
+ With the official Creative Mail for WooCommerce plugin, your products, blog posts, images and store links
4
+ are automatically included as rich shoppable email marketing content for your customers.', 'creative-mail-by-constant-contact' ); ?>
5
  </p>
6
  <p class="ce4wp-typography-root ce4wp-body2 ce4wp-mt-3" style="color: rgba(0, 0, 0, 0.6);">
7
+ <?php
8
+ esc_html_e( 'Our included CRM also intelligently pulls in and identifies your WordPress site contacts and WooCommerce store customers.
9
+ That makes it easy to build audiences and send targeted customer campaigns.', 'creative-mail-by-constant-contact' );
10
+ ?>
11
  </p>
12
  <p class="ce4wp-typography-root ce4wp-body2 ce4wp-mt-3" style="color: rgba(0, 0, 0, 0.6);">
13
+ <?php esc_html_e( 'Get free email marketing, 98% deliverability, and Constant Contact rock solid reliability all without ever needing to leave your WP Admin.', 'creative-mail-by-constant-contact' ); ?>
14
  </p>
 
 
15
  <p class="ce4wp-typography-root ce4wp-body2 ce4wp-mt-3" style="color: rgba(0, 0, 0, 0.6);">
16
+ <?php esc_html_e( 'Having problems setting up your account, click the \'reset\' button below to start over.', 'creative-mail-by-constant-contact' ); ?>
17
  </p>
18
  <div class="ce4wp-kvp">
19
+ <form name="disconnect" action="" method="post">
20
+ <input name="disconnect_nonce" type="hidden" value="<?php echo esc_html(wp_create_nonce('disconnect')); ?>" />
21
+ <input type="hidden" name="action" value="disconnect" />
22
+ <input id="disconnect-instance"
23
+ name="disconnect_button"
24
+ type="submit"
25
+ class="ce4wp-button-text-primary destructive ce4wp-right"
26
+ value="Reset" />
27
+ </form>
28
  </div>
src/views/settings-internal.php CHANGED
@@ -3,45 +3,73 @@ use CreativeMail\Helpers\EnvironmentHelper;
3
  ?>
4
 
5
  <div class="ce4wp-card">
6
- <div class="ce4wp-px-4 ce4wp-py-4">
7
- <h2 class="ce4wp-typography-root ce4wp-typography-h2 ce4wp-mb-2"><?php echo __( 'Technical details', 'ce4wp' ); ?></h2>
8
-
9
- <div class="ce4wp-kvp">
10
- <h4 class="ce4wp-typography-root ce4wp-typography-h4 ce4wp-mb-2"><?php echo __( 'Instance UUID', 'ce4wp' ); ?></h4>
11
- <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);">
12
- <?php // @phpstan-ignore-next-line
13
- echo esc_html($this->instance_uuid)
14
- ?>
15
- </p>
16
- </div>
17
-
18
- <div class="ce4wp-kvp">
19
- <h4 class="ce4wp-typography-root ce4wp-typography-h4 ce4wp-mb-2"><?php echo __( 'Instance Id', 'ce4wp' ); ?></h4>
20
- <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);">
21
- <?php // @phpstan-ignore-next-line
22
- echo esc_html($this->instance_id)
23
- ?>
24
- </p>
25
- </div>
26
-
27
- <div class="ce4wp-kvp">
28
- <h4 class="ce4wp-typography-root ce4wp-typography-h4 ce4wp-mb-2"><?php echo __( 'Environment', 'ce4wp' ); ?></h4>
29
- <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);"><?php echo esc_html(EnvironmentHelper::get_environment()) ?></p>
30
- </div>
31
-
32
- <div class="ce4wp-kvp">
33
- <h4 class="ce4wp-typography-root ce4wp-typography-h4 ce4wp-mb-2"><?php echo __( 'Plugin version', 'ce4wp' ); ?></h4>
34
- <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);"><?php echo esc_html(CE4WP_PLUGIN_VERSION) . '.' . esc_html(CE4WP_BUILD_NUMBER) ?></p>
35
- </div>
36
-
37
- <div class="ce4wp-kvp">
38
- <h4 class="ce4wp-typography-root ce4wp-typography-h4 ce4wp-mb-2"><?php echo __( 'App', 'ce4wp' ); ?></h4>
39
- <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);"><?php echo esc_js(EnvironmentHelper::get_app_url()) ?></p>
40
- </div>
41
-
42
- <div class="ce4wp-kvp">
43
- <h4 class="ce4wp-typography-root ce4wp-typography-h4 ce4wp-mb-2"><?php echo __( 'App Gateway', 'ce4wp' ); ?></h4>
44
- <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);"><?php echo esc_js(EnvironmentHelper::get_app_gateway_url()) ?></p>
45
- </div>
46
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  </div>
3
  ?>
4
 
5
  <div class="ce4wp-card">
6
+ <div class="ce4wp-px-4 ce4wp-py-4">
7
+ <h2 class="ce4wp-typography-root ce4wp-typography-h2 ce4wp-mb-2">
8
+ <?php esc_html_e( 'Technical details', 'creative-mail-by-constant-contact' ); ?>
9
+ </h2>
10
+
11
+ <div class="ce4wp-kvp">
12
+ <h4 class="ce4wp-typography-root ce4wp-typography-h4 ce4wp-mb-2">
13
+ <?php esc_html_e( 'Instance UUID', 'creative-mail-by-constant-contact' ); ?>
14
+
15
+ </h4>
16
+ <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);">
17
+ <?php
18
+ // @phpstan-ignore-next-line
19
+ echo esc_html($this->instance_uuid)
20
+ ?>
21
+ </p>
22
+ </div>
23
+
24
+ <div class="ce4wp-kvp">
25
+ <h4 class="ce4wp-typography-root ce4wp-typography-h4 ce4wp-mb-2">
26
+ <?php esc_html_e( 'Instance Id', 'creative-mail-by-constant-contact' ); ?>
27
+ </h4>
28
+ <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);">
29
+ <?php
30
+ // @phpstan-ignore-next-line
31
+ echo esc_html($this->instance_id)
32
+ ?>
33
+ </p>
34
+ </div>
35
+
36
+ <div class="ce4wp-kvp">
37
+ <h4 class="ce4wp-typography-root ce4wp-typography-h4 ce4wp-mb-2">
38
+ <?php esc_html_e( 'Environment', 'creative-mail-by-constant-contact' ); ?>
39
+ </h4>
40
+ <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);">
41
+ <?php echo esc_html(EnvironmentHelper::get_environment()); ?>
42
+ </p>
43
+ </div>
44
+
45
+ <div class="ce4wp-kvp">
46
+ <h4 class="ce4wp-typography-root ce4wp-typography-h4 ce4wp-mb-2">
47
+ <?php esc_html_e( 'Plugin version', 'creative-mail-by-constant-contact' ); ?>
48
+ </h4>
49
+ <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);">
50
+ <?php echo esc_html(CE4WP_PLUGIN_VERSION) . '.' . esc_html(CE4WP_BUILD_NUMBER); ?>
51
+
52
+ </p>
53
+ </div>
54
+
55
+ <div class="ce4wp-kvp">
56
+ <h4 class="ce4wp-typography-root ce4wp-typography-h4 ce4wp-mb-2">
57
+ <?php esc_html_e( 'App', 'creative-mail-by-constant-contact' ); ?>
58
+ </h4>
59
+ <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);">
60
+ <?php echo esc_js(EnvironmentHelper::get_app_url()); ?>
61
+
62
+ </p>
63
+ </div>
64
+
65
+ <div class="ce4wp-kvp">
66
+ <h4 class="ce4wp-typography-root ce4wp-typography-h4 ce4wp-mb-2">
67
+ <?php esc_html_e( 'App Gateway', 'creative-mail-by-constant-contact' ); ?>
68
+ </h4>
69
+ <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);">
70
+ <?php echo esc_js(EnvironmentHelper::get_app_gateway_url()); ?>
71
+
72
+ </p>
73
+ </div>
74
+ </div>
75
  </div>
src/views/settings.php CHANGED
@@ -4,116 +4,140 @@ use CreativeMail\CreativeMail;
4
  use CreativeMail\Helpers\EnvironmentHelper;
5
  use CreativeMail\Helpers\OptionsHelper;
6
 
7
- if ($_SERVER['REQUEST_METHOD'] === 'POST') {
8
- if( $_POST['action'] === 'disconnect' && wp_verify_nonce( $_POST['disconnect_nonce'], 'disconnect' ) ) {
9
- OptionsHelper::clear_options(true);
10
- // @phpstan-ignore-next-line
11
- $this->instance_id = null;
12
- }
 
 
13
 
14
- if( $_POST['action'] === 'change_activated_plugins' && wp_verify_nonce( $_POST['activated_plugins_nonce'], 'activated_plugins' ) ) {
15
- $activated_plugins = array();
16
- if (isset($_POST['activated_plugins'])) {
17
- $keys = $_POST["activated_plugins"];
18
- foreach ($keys as $key) {
19
- array_push($activated_plugins, sanitize_key($key));
20
- }
21
- }
22
- CreativeMail::get_instance()->get_integration_manager()->set_activated_plugins($activated_plugins);
23
- }
 
24
 
25
- if ( $_POST['action'] === 'change_marketing_information' && wp_verify_nonce( $_POST['marketing_consent_nonce'], 'marketing_consent' ) ) {
26
- if( array_key_exists( 'ce4wp_show_marketing_checkbox', $_POST ) && sanitize_key( $_POST[ 'ce4wp_show_marketing_checkbox' ] ) === 'on') {
27
- OptionsHelper::set_checkout_checkbox_enabled('1');
28
- } else {
29
- OptionsHelper::set_checkout_checkbox_enabled('0');
30
- }
31
- OptionsHelper::set_checkout_checkbox_text(sanitize_text_field($_POST['ce4wp_checkbox_text']));
32
- }
 
 
 
 
 
 
 
 
 
33
  }
34
 
35
- $contact_sync_available = !empty(CreativeMail::get_instance()->get_integration_manager()->get_active_plugins());
36
- $supported_plugin_available = !empty(CreativeMail::get_instance()->get_integration_manager()->get_supported_integrations(true))
37
  ?>
38
 
39
  <div class="ce4wp-admin-wrapper">
40
- <header class="ce4wp-swoosh-header"></header>
41
 
42
- <div class="ce4wp-swoosh-container">
43
- <div style="margin-top: 0px;">
44
- <div class="ce4wp-backdrop">
45
- <div class="ce4wp-backdrop-container">
46
- <div class="ce4wp-backdrop-header">
47
- <div class="ce4wp-logo-poppins"></div>
48
- <div>
49
- <img src="<?php echo CE4WP_PLUGIN_URL . 'assets/images/airplane.svg'; ?>" class="ce4wp-airplane" alt="Paper airplane decoration">
50
- </div>
51
- </div>
52
 
53
- <div class="ce4wp-card">
54
- <div class="ce4wp-px-4 ce4wp-py-4">
55
- <h2 class="ce4wp-typography-root ce4wp-typography-h2 ce4wp-mb-2"><?= __( 'Creative Mail by Constant Contact', 'ce4wp' ); ?></h2>
 
 
56
 
57
- <?php
58
- if (OptionsHelper::get_instance_id()) {
59
- include 'unlink.php';
60
- }
61
- else {
62
- include 'pending-setup.php';
63
- }
64
- ?>
65
- </div>
66
- </div>
67
- <?php
68
- if (OptionsHelper::get_instance_id()) {
69
- include 'contact-sync.php';
70
- }
71
- if (EnvironmentHelper::is_test_environment()) {
72
- include 'settings-internal.php';
73
- }
74
- ?>
75
 
76
- <div class="ce4wp-card">
77
- <div class="ce4wp-px-4 ce4wp-py-4">
78
- <h2 class="ce4wp-typography-root ce4wp-typography-h2 ce4wp-mb-2"><?= __( 'Customer Email Marketing', 'ce4wp' ); ?></h2>
 
 
79
 
80
- <form name="plugins" action="" method="post">
81
- <input name="marketing_consent_nonce" type="hidden" value="<?=wp_create_nonce('marketing_consent')?>" />
82
- <input type="hidden" name="action" value="change_marketing_information" />
83
- <table class="form-table">
84
- <tbody>
85
- <tr>
86
- <td class="forminp forminp-text ce4wp-px-0">
87
- <label class="ce4wp-checkbox">
88
- <input type="checkbox" name="ce4wp_show_marketing_checkbox" <?php echo ( esc_attr ( OptionsHelper::get_checkout_checkbox_enabled() == '1' ? 'checked' : '' ) );?> />
89
- <span class="ce4wp-typography-root ce4wp-body2">
90
- <?php echo __('Yes I want to ask my customers in the WooCommerce Checkout for consent to send marketing emails.', 'ce4wp'); ?>
91
- </span>
92
- </label>
93
- </td>
94
- </tr>
95
- <tr>
96
- <td class="forminp forminp-text ce4wp-px-0">
97
- <label for="ce4wp_checkbox_text">
98
- <span class="ce4wp-typography-root ce4wp-body2">
99
- <?php echo __('Consent Text', 'ce4wp'); ?>
100
- <span>
101
- </label>
102
- <br />
103
- <input type="text" name="ce4wp_checkbox_text" value="<?php echo esc_attr(stripslashes(OptionsHelper::get_checkout_checkbox_text())); ?>" />
104
- </td>
105
- </tr>
106
- </tbody>
107
- </table>
 
 
 
 
 
108
 
109
- <div class="ce-kvp">
110
- <input name="save_button" type="submit" class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-button-contained-primary ce4wp-mt-2" id="save_customer_information" value="Save" />
111
- </div>
112
- </form>
113
- </div>
114
- </div>
115
- </div>
116
- </div>
117
- </div>
118
- </div>
 
 
 
 
119
  </div>
4
  use CreativeMail\Helpers\EnvironmentHelper;
5
  use CreativeMail\Helpers\OptionsHelper;
6
 
7
+ if ( isset ( $_SERVER['REQUEST_METHOD'] ) && 'POST' === $_SERVER['REQUEST_METHOD'] && isset ( $_POST['action'] ) ) {
8
+ if ( 'disconnect' === $_POST['action']
9
+ && isset( $_POST['disconnect_nonce'] )
10
+ && wp_verify_nonce( sanitize_text_field ( wp_unslash ( $_POST['disconnect_nonce'] ) ), 'disconnect' ) ) {
11
+ OptionsHelper::clear_options(true);
12
+ // @phpstan-ignore-next-line
13
+ $this->instance_id = null;
14
+ }
15
 
16
+ if ( 'change_activated_plugins' === $_POST['action']
17
+ && isset ( $_POST['activated_plugins_nonce'] )
18
+ && wp_verify_nonce(
19
+ sanitize_text_field ( wp_unslash ( $_POST['activated_plugins_nonce'] ) ), 'activated_plugins' )
20
+ ) {
21
+ $activated_plugins = array();
22
+ if ( isset($_POST['activated_plugins']) ) {
23
+ $activated_plugins = array_map( 'sanitize_text_field', wp_unslash( $_POST['activated_plugins'] ) );
24
+ }
25
+ CreativeMail::get_instance()->get_integration_manager()->set_activated_plugins($activated_plugins);
26
+ }
27
 
28
+ if ( 'change_marketing_information' === $_POST['action']
29
+ && isset ( $_POST['marketing_consent_nonce'] )
30
+ && wp_verify_nonce(
31
+ sanitize_text_field( wp_unslash($_POST['marketing_consent_nonce']) ), 'marketing_consent' )
32
+ ) {
33
+ if ( array_key_exists( 'ce4wp_show_marketing_checkbox', $_POST )
34
+ && sanitize_key( $_POST['ce4wp_show_marketing_checkbox'] ) === 'on' ) {
35
+ OptionsHelper::set_checkout_checkbox_enabled('1');
36
+ } else {
37
+ OptionsHelper::set_checkout_checkbox_enabled('0');
38
+ }
39
+ OptionsHelper::set_checkout_checkbox_text(
40
+ sanitize_text_field(
41
+ wp_unslash(
42
+ $_POST['ce4wp_checkbox_text'] ?? ''
43
+ ) ) );
44
+ }
45
  }
46
 
47
+ $contact_sync_available = ! empty(CreativeMail::get_instance()->get_integration_manager()->get_active_plugins());
48
+ $supported_plugin_available = ! empty(CreativeMail::get_instance()->get_integration_manager()->get_supported_integrations(true))
49
  ?>
50
 
51
  <div class="ce4wp-admin-wrapper">
52
+ <header class="ce4wp-swoosh-header"></header>
53
 
54
+ <div class="ce4wp-swoosh-container">
55
+ <div style="margin-top: 0;">
56
+ <div class="ce4wp-backdrop">
57
+ <div class="ce4wp-backdrop-container">
58
+ <div class="ce4wp-backdrop-header">
59
+ <div class="ce4wp-logo-poppins"></div>
60
+ <div>
61
+ <img src="<?php echo esc_url( CE4WP_PLUGIN_URL . 'assets/images/airplane.svg' ); ?>" class="ce4wp-airplane" alt="Paper airplane decoration">
62
+ </div>
63
+ </div>
64
 
65
+ <div class="ce4wp-card">
66
+ <div class="ce4wp-px-4 ce4wp-py-4">
67
+ <h2 class="ce4wp-typography-root ce4wp-typography-h2 ce4wp-mb-2">
68
+ <?php esc_html_e( 'Creative Mail by Constant Contact', 'creative-mail-by-constant-contact' ); ?>
69
+ </h2>
70
 
71
+ <?php
72
+ if ( OptionsHelper::get_instance_id() ) {
73
+ include 'unlink.php';
74
+ } else {
75
+ include 'pending-setup.php';
76
+ }
77
+ ?>
78
+ </div>
79
+ </div>
80
+ <?php
81
+ if ( OptionsHelper::get_instance_id() ) {
82
+ include 'contact-sync.php';
83
+ }
84
+ if ( EnvironmentHelper::is_test_environment() ) {
85
+ include 'settings-internal.php';
86
+ }
87
+ ?>
 
88
 
89
+ <div class="ce4wp-card">
90
+ <div class="ce4wp-px-4 ce4wp-py-4">
91
+ <h2 class="ce4wp-typography-root ce4wp-typography-h2 ce4wp-mb-2">
92
+ <?php esc_html_e( 'Customer Email Marketing', 'creative-mail-by-constant-contact' ); ?>
93
+ </h2>
94
 
95
+ <form name="plugins" action="" method="post">
96
+ <input name="marketing_consent_nonce"
97
+ type="hidden"
98
+ value="<?php echo esc_html(wp_create_nonce('marketing_consent')); ?>"
99
+ />
100
+ <input type="hidden" name="action" value="change_marketing_information" />
101
+ <table class="form-table">
102
+ <tbody>
103
+ <tr>
104
+ <td class="forminp forminp-text ce4wp-px-0">
105
+ <label class="ce4wp-checkbox">
106
+ <input type="checkbox" name="ce4wp_show_marketing_checkbox" <?php echo esc_attr ( OptionsHelper::get_checkout_checkbox_enabled() == '1' ? 'checked' : '' ); ?> />
107
+ <span class="ce4wp-typography-root ce4wp-body2">
108
+ <?php esc_html_e('Yes I want to ask my customers in the WooCommerce Checkout for consent to send marketing emails.', 'creative-mail-by-constant-contact'); ?>
109
+ </span>
110
+ </label>
111
+ </td>
112
+ </tr>
113
+ <tr>
114
+ <td class="forminp forminp-text ce4wp-px-0">
115
+ <label for="ce4wp_checkbox_text">
116
+ <span class="ce4wp-typography-root ce4wp-body2">
117
+ <?php esc_html_e('Consent Text', 'creative-mail-by-constant-contact'); ?>
118
+ <span>
119
+ </label>
120
+ <br />
121
+ <input type="text"
122
+ name="ce4wp_checkbox_text"
123
+ value="<?php echo esc_attr(stripslashes(OptionsHelper::get_checkout_checkbox_text())); ?>" />
124
+ </td>
125
+ </tr>
126
+ </tbody>
127
+ </table>
128
 
129
+ <div class="ce-kvp">
130
+ <input id="save_customer_information"
131
+ name="save_button"
132
+ type="submit"
133
+ class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-button-contained-primary ce4wp-mt-2"
134
+ value="Save" />
135
+ </div>
136
+ </form>
137
+ </div>
138
+ </div>
139
+ </div>
140
+ </div>
141
+ </div>
142
+ </div>
143
  </div>
src/views/unlink.php CHANGED
@@ -1,15 +1,30 @@
1
  <div class="ce4wp-kvp">
2
  <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);">
3
- <?= __( 'Your WordPress instance is connected to your Creative Mail account. If you would like to
4
- unlink your WordPress instance from your account, please click the "Unlink" button below.', 'ce4wp' ); ?>
5
- <strong><?= __('Unlinking your account is permanent and cannot be undone.', 'ce4wp' ); ?></strong>
 
 
6
  </p>
7
  </div>
8
 
9
  <div class="ce4wp-kvp">
10
  <form name="disconnect" action="" method="post">
11
- <input name="disconnect_nonce" type="hidden" value="<?=wp_create_nonce('disconnect')?>" />
12
  <input name="action" type="hidden" value="disconnect" />
13
- <input name="disconnect_button" type="submit" class="ce4wp-button-text-primary destructive ce4wp-right" id="disconnect-instance" value="Unlink" onclick="return confirm('Are you sure you want to unlink your CreativeMail account from your WordPress site? This action is permanent and cannot be undone.')" />
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  </form>
15
  </div>
1
  <div class="ce4wp-kvp">
2
  <p class="ce4wp-typography-root ce4wp-body2" style="color: rgba(0, 0, 0, 0.6);">
3
+ <?php esc_html_e( 'Your WordPress instance is connected to your Creative Mail account. If you would like to
4
+ unlink your WordPress instance from your account, please click the "Unlink" button below.', 'creative-mail-by-constant-contact' ); ?>
5
+ <strong>
6
+ <?php esc_html_e('Unlinking your account is permanent and cannot be undone.', 'creative-mail-by-constant-contact' ); ?>
7
+ </strong>
8
  </p>
9
  </div>
10
 
11
  <div class="ce4wp-kvp">
12
  <form name="disconnect" action="" method="post">
13
+ <input name="disconnect_nonce" type="hidden" value="<?php echo esc_attr(wp_create_nonce('disconnect')); ?>" />
14
  <input name="action" type="hidden" value="disconnect" />
15
+ <input id="disconnect-instance"
16
+ name="disconnect_button"
17
+ type="submit"
18
+ class="ce4wp-button-text-primary destructive ce4wp-right"
19
+ value="Unlink"
20
+ onclick="return confirm(
21
+ <?php
22
+ esc_html_e(
23
+ 'Are you sure you want to unlink your CreativeMail account from your WordPress site? This action is permanent and cannot be undone.',
24
+ 'creative-mail-by-constant-contact'
25
+ );
26
+ ?>
27
+ "
28
+ />
29
  </form>
30
  </div>
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit280162df9749c3147507d248f2c68d82::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit315811124a911e9493d5fdf73305051b::getLoader();
vendor/bin/phpstan ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env php
2
+ <?php
3
+
4
+ declare (strict_types=1);
5
+
6
+ Phar::loadPhar(__DIR__ . '/phpstan.phar', 'phpstan.phar');
7
+
8
+ require 'phar://phpstan.phar/bin/phpstan';
vendor/bin/phpstan.phar CHANGED
Binary file
vendor/composer/autoload_classmap.php CHANGED
@@ -16,7 +16,6 @@ return array(
16
  'CreativeMail\\Helpers\\GuidHelper' => $baseDir . '/src/Helpers/GuidHelper.php',
17
  'CreativeMail\\Helpers\\OptionsHelper' => $baseDir . '/src/Helpers/OptionsHelper.php',
18
  'CreativeMail\\Helpers\\SsoHelper' => $baseDir . '/src/Helpers/SsoHelper.php',
19
- 'CreativeMail\\Helpers\\ValidationHelper' => $baseDir . '/src/Helpers/ValidationHelper.php',
20
  'CreativeMail\\Integrations\\Integration' => $baseDir . '/src/Integrations/Integration.php',
21
  'CreativeMail\\Managers\\AdminManager' => $baseDir . '/src/Managers/AdminManager.php',
22
  'CreativeMail\\Managers\\ApiManager' => $baseDir . '/src/Managers/ApiManager.php',
@@ -32,6 +31,7 @@ return array(
32
  'CreativeMail\\Models\\CartData' => $baseDir . '/src/Models/CartData.php',
33
  'CreativeMail\\Models\\Checkout' => $baseDir . '/src/Models/Checkout.php',
34
  'CreativeMail\\Models\\CheckoutSave' => $baseDir . '/src/Models/CheckoutSave.php',
 
35
  'CreativeMail\\Models\\CustomerNewAccount' => $baseDir . '/src/Models/CustomerNewAccount.php',
36
  'CreativeMail\\Models\\CustomerNote' => $baseDir . '/src/Models/CustomerNote.php',
37
  'CreativeMail\\Models\\CustomerResetPassword' => $baseDir . '/src/Models/CustomerResetPassword.php',
@@ -40,6 +40,9 @@ return array(
40
  'CreativeMail\\Models\\OptionsSchema' => $baseDir . '/src/Models/OptionsSchema.php',
41
  'CreativeMail\\Models\\Order' => $baseDir . '/src/Models/Order.php',
42
  'CreativeMail\\Models\\OrderBilling' => $baseDir . '/src/Models/OrderBilling.php',
 
 
 
43
  'CreativeMail\\Models\\RequestItem' => $baseDir . '/src/Models/RequestItem.php',
44
  'CreativeMail\\Models\\Response' => $baseDir . '/src/Models/Response.php',
45
  'CreativeMail\\Models\\TriggerExecution' => $baseDir . '/src/Models/TriggerExecution.php',
@@ -68,6 +71,7 @@ return array(
68
  'CreativeMail\\Modules\\Contacts\\Models\\ContactAddressModel' => $baseDir . '/src/Modules/Contacts/Models/ContactAddressModel.php',
69
  'CreativeMail\\Modules\\Contacts\\Models\\ContactFormSevenSubmission' => $baseDir . '/src/Modules/Contacts/Models/ContactFormSevenSubmission.php',
70
  'CreativeMail\\Modules\\Contacts\\Models\\ContactModel' => $baseDir . '/src/Modules/Contacts/Models/ContactModel.php',
 
71
  'CreativeMail\\Modules\\Contacts\\Models\\OptActionBy' => $baseDir . '/src/Modules/Contacts/Models/OptActionBy.php',
72
  'CreativeMail\\Modules\\Contacts\\Processors\\ContactsSyncBackgroundProcessor' => $baseDir . '/src/Modules/Contacts/Processors/ContactsSyncBackgroundProcessor.php',
73
  'CreativeMail\\Modules\\Contacts\\Services\\ContactsSyncService' => $baseDir . '/src/Modules/Contacts/Services/ContactsSyncService.php',
16
  'CreativeMail\\Helpers\\GuidHelper' => $baseDir . '/src/Helpers/GuidHelper.php',
17
  'CreativeMail\\Helpers\\OptionsHelper' => $baseDir . '/src/Helpers/OptionsHelper.php',
18
  'CreativeMail\\Helpers\\SsoHelper' => $baseDir . '/src/Helpers/SsoHelper.php',
 
19
  'CreativeMail\\Integrations\\Integration' => $baseDir . '/src/Integrations/Integration.php',
20
  'CreativeMail\\Managers\\AdminManager' => $baseDir . '/src/Managers/AdminManager.php',
21
  'CreativeMail\\Managers\\ApiManager' => $baseDir . '/src/Managers/ApiManager.php',
31
  'CreativeMail\\Models\\CartData' => $baseDir . '/src/Models/CartData.php',
32
  'CreativeMail\\Models\\Checkout' => $baseDir . '/src/Models/Checkout.php',
33
  'CreativeMail\\Models\\CheckoutSave' => $baseDir . '/src/Models/CheckoutSave.php',
34
+ 'CreativeMail\\Models\\Coupon' => $baseDir . '/src/Models/Coupon.php',
35
  'CreativeMail\\Models\\CustomerNewAccount' => $baseDir . '/src/Models/CustomerNewAccount.php',
36
  'CreativeMail\\Models\\CustomerNote' => $baseDir . '/src/Models/CustomerNote.php',
37
  'CreativeMail\\Models\\CustomerResetPassword' => $baseDir . '/src/Models/CustomerResetPassword.php',
40
  'CreativeMail\\Models\\OptionsSchema' => $baseDir . '/src/Models/OptionsSchema.php',
41
  'CreativeMail\\Models\\Order' => $baseDir . '/src/Models/Order.php',
42
  'CreativeMail\\Models\\OrderBilling' => $baseDir . '/src/Models/OrderBilling.php',
43
+ 'CreativeMail\\Models\\OrderBillingPaymentDetails' => $baseDir . '/src/Models/OrderBillingPaymentDetails.php',
44
+ 'CreativeMail\\Models\\OrderBillingShipping' => $baseDir . '/src/Models/OrderBillingShipping.php',
45
+ 'CreativeMail\\Models\\OrderLineItem' => $baseDir . '/src/Models/OrderLineItem.php',
46
  'CreativeMail\\Models\\RequestItem' => $baseDir . '/src/Models/RequestItem.php',
47
  'CreativeMail\\Models\\Response' => $baseDir . '/src/Models/Response.php',
48
  'CreativeMail\\Models\\TriggerExecution' => $baseDir . '/src/Models/TriggerExecution.php',
71
  'CreativeMail\\Modules\\Contacts\\Models\\ContactAddressModel' => $baseDir . '/src/Modules/Contacts/Models/ContactAddressModel.php',
72
  'CreativeMail\\Modules\\Contacts\\Models\\ContactFormSevenSubmission' => $baseDir . '/src/Modules/Contacts/Models/ContactFormSevenSubmission.php',
73
  'CreativeMail\\Modules\\Contacts\\Models\\ContactModel' => $baseDir . '/src/Modules/Contacts/Models/ContactModel.php',
74
+ 'CreativeMail\\Modules\\Contacts\\Models\\FormidableContactForm' => $baseDir . '/src/Modules/Contacts/Models/FormidableContactForm.php',
75
  'CreativeMail\\Modules\\Contacts\\Models\\OptActionBy' => $baseDir . '/src/Modules/Contacts/Models/OptActionBy.php',
76
  'CreativeMail\\Modules\\Contacts\\Processors\\ContactsSyncBackgroundProcessor' => $baseDir . '/src/Modules/Contacts/Processors/ContactsSyncBackgroundProcessor.php',
77
  'CreativeMail\\Modules\\Contacts\\Services\\ContactsSyncService' => $baseDir . '/src/Modules/Contacts/Services/ContactsSyncService.php',
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit280162df9749c3147507d248f2c68d82
6
  {
7
  private static $loader;
8
 
@@ -22,15 +22,15 @@ class ComposerAutoloaderInit280162df9749c3147507d248f2c68d82
22
  return self::$loader;
23
  }
24
 
25
- spl_autoload_register(array('ComposerAutoloaderInit280162df9749c3147507d248f2c68d82', 'loadClassLoader'), true, true);
26
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
27
- spl_autoload_unregister(array('ComposerAutoloaderInit280162df9749c3147507d248f2c68d82', 'loadClassLoader'));
28
 
29
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
  if ($useStaticLoader) {
31
  require_once __DIR__ . '/autoload_static.php';
32
 
33
- call_user_func(\Composer\Autoload\ComposerStaticInit280162df9749c3147507d248f2c68d82::getInitializer($loader));
34
  } else {
35
  $map = require __DIR__ . '/autoload_namespaces.php';
36
  foreach ($map as $namespace => $path) {
@@ -51,19 +51,19 @@ class ComposerAutoloaderInit280162df9749c3147507d248f2c68d82
51
  $loader->register(true);
52
 
53
  if ($useStaticLoader) {
54
- $includeFiles = Composer\Autoload\ComposerStaticInit280162df9749c3147507d248f2c68d82::$files;
55
  } else {
56
  $includeFiles = require __DIR__ . '/autoload_files.php';
57
  }
58
  foreach ($includeFiles as $fileIdentifier => $file) {
59
- composerRequire280162df9749c3147507d248f2c68d82($fileIdentifier, $file);
60
  }
61
 
62
  return $loader;
63
  }
64
  }
65
 
66
- function composerRequire280162df9749c3147507d248f2c68d82($fileIdentifier, $file)
67
  {
68
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
69
  require $file;
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit315811124a911e9493d5fdf73305051b
6
  {
7
  private static $loader;
8
 
22
  return self::$loader;
23
  }
24
 
25
+ spl_autoload_register(array('ComposerAutoloaderInit315811124a911e9493d5fdf73305051b', 'loadClassLoader'), true, true);
26
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
27
+ spl_autoload_unregister(array('ComposerAutoloaderInit315811124a911e9493d5fdf73305051b', 'loadClassLoader'));
28
 
29
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
  if ($useStaticLoader) {
31
  require_once __DIR__ . '/autoload_static.php';
32
 
33
+ call_user_func(\Composer\Autoload\ComposerStaticInit315811124a911e9493d5fdf73305051b::getInitializer($loader));
34
  } else {
35
  $map = require __DIR__ . '/autoload_namespaces.php';
36
  foreach ($map as $namespace => $path) {
51
  $loader->register(true);
52
 
53
  if ($useStaticLoader) {
54
+ $includeFiles = Composer\Autoload\ComposerStaticInit315811124a911e9493d5fdf73305051b::$files;
55
  } else {
56
  $includeFiles = require __DIR__ . '/autoload_files.php';
57
  }
58
  foreach ($includeFiles as $fileIdentifier => $file) {
59
+ composerRequire315811124a911e9493d5fdf73305051b($fileIdentifier, $file);
60
  }
61
 
62
  return $loader;
63
  }
64
  }
65
 
66
+ function composerRequire315811124a911e9493d5fdf73305051b($fileIdentifier, $file)
67
  {
68
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
69
  require $file;
vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInit280162df9749c3147507d248f2c68d82
8
  {
9
  public static $files = array (
10
  '9b38cf48e83f5d8f60375221cd213eee' => __DIR__ . '/..' . '/phpstan/phpstan/bootstrap.php',
@@ -118,7 +118,6 @@ class ComposerStaticInit280162df9749c3147507d248f2c68d82
118
  'CreativeMail\\Helpers\\GuidHelper' => __DIR__ . '/../..' . '/src/Helpers/GuidHelper.php',
119
  'CreativeMail\\Helpers\\OptionsHelper' => __DIR__ . '/../..' . '/src/Helpers/OptionsHelper.php',
120
  'CreativeMail\\Helpers\\SsoHelper' => __DIR__ . '/../..' . '/src/Helpers/SsoHelper.php',
121
- 'CreativeMail\\Helpers\\ValidationHelper' => __DIR__ . '/../..' . '/src/Helpers/ValidationHelper.php',
122
  'CreativeMail\\Integrations\\Integration' => __DIR__ . '/../..' . '/src/Integrations/Integration.php',
123
  'CreativeMail\\Managers\\AdminManager' => __DIR__ . '/../..' . '/src/Managers/AdminManager.php',
124
  'CreativeMail\\Managers\\ApiManager' => __DIR__ . '/../..' . '/src/Managers/ApiManager.php',
@@ -134,6 +133,7 @@ class ComposerStaticInit280162df9749c3147507d248f2c68d82
134
  'CreativeMail\\Models\\CartData' => __DIR__ . '/../..' . '/src/Models/CartData.php',
135
  'CreativeMail\\Models\\Checkout' => __DIR__ . '/../..' . '/src/Models/Checkout.php',
136
  'CreativeMail\\Models\\CheckoutSave' => __DIR__ . '/../..' . '/src/Models/CheckoutSave.php',
 
137
  'CreativeMail\\Models\\CustomerNewAccount' => __DIR__ . '/../..' . '/src/Models/CustomerNewAccount.php',
138
  'CreativeMail\\Models\\CustomerNote' => __DIR__ . '/../..' . '/src/Models/CustomerNote.php',
139
  'CreativeMail\\Models\\CustomerResetPassword' => __DIR__ . '/../..' . '/src/Models/CustomerResetPassword.php',
@@ -142,6 +142,9 @@ class ComposerStaticInit280162df9749c3147507d248f2c68d82
142
  'CreativeMail\\Models\\OptionsSchema' => __DIR__ . '/../..' . '/src/Models/OptionsSchema.php',
143
  'CreativeMail\\Models\\Order' => __DIR__ . '/../..' . '/src/Models/Order.php',
144
  'CreativeMail\\Models\\OrderBilling' => __DIR__ . '/../..' . '/src/Models/OrderBilling.php',
 
 
 
145
  'CreativeMail\\Models\\RequestItem' => __DIR__ . '/../..' . '/src/Models/RequestItem.php',
146
  'CreativeMail\\Models\\Response' => __DIR__ . '/../..' . '/src/Models/Response.php',
147
  'CreativeMail\\Models\\TriggerExecution' => __DIR__ . '/../..' . '/src/Models/TriggerExecution.php',
@@ -170,6 +173,7 @@ class ComposerStaticInit280162df9749c3147507d248f2c68d82
170
  'CreativeMail\\Modules\\Contacts\\Models\\ContactAddressModel' => __DIR__ . '/../..' . '/src/Modules/Contacts/Models/ContactAddressModel.php',
171
  'CreativeMail\\Modules\\Contacts\\Models\\ContactFormSevenSubmission' => __DIR__ . '/../..' . '/src/Modules/Contacts/Models/ContactFormSevenSubmission.php',
172
  'CreativeMail\\Modules\\Contacts\\Models\\ContactModel' => __DIR__ . '/../..' . '/src/Modules/Contacts/Models/ContactModel.php',
 
173
  'CreativeMail\\Modules\\Contacts\\Models\\OptActionBy' => __DIR__ . '/../..' . '/src/Modules/Contacts/Models/OptActionBy.php',
174
  'CreativeMail\\Modules\\Contacts\\Processors\\ContactsSyncBackgroundProcessor' => __DIR__ . '/../..' . '/src/Modules/Contacts/Processors/ContactsSyncBackgroundProcessor.php',
175
  'CreativeMail\\Modules\\Contacts\\Services\\ContactsSyncService' => __DIR__ . '/../..' . '/src/Modules/Contacts/Services/ContactsSyncService.php',
@@ -247,10 +251,10 @@ class ComposerStaticInit280162df9749c3147507d248f2c68d82
247
  public static function getInitializer(ClassLoader $loader)
248
  {
249
  return \Closure::bind(function () use ($loader) {
250
- $loader->prefixLengthsPsr4 = ComposerStaticInit280162df9749c3147507d248f2c68d82::$prefixLengthsPsr4;
251
- $loader->prefixDirsPsr4 = ComposerStaticInit280162df9749c3147507d248f2c68d82::$prefixDirsPsr4;
252
- $loader->prefixesPsr0 = ComposerStaticInit280162df9749c3147507d248f2c68d82::$prefixesPsr0;
253
- $loader->classMap = ComposerStaticInit280162df9749c3147507d248f2c68d82::$classMap;
254
 
255
  }, null, ClassLoader::class);
256
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInit315811124a911e9493d5fdf73305051b
8
  {
9
  public static $files = array (
10
  '9b38cf48e83f5d8f60375221cd213eee' => __DIR__ . '/..' . '/phpstan/phpstan/bootstrap.php',
118
  'CreativeMail\\Helpers\\GuidHelper' => __DIR__ . '/../..' . '/src/Helpers/GuidHelper.php',
119
  'CreativeMail\\Helpers\\OptionsHelper' => __DIR__ . '/../..' . '/src/Helpers/OptionsHelper.php',
120
  'CreativeMail\\Helpers\\SsoHelper' => __DIR__ . '/../..' . '/src/Helpers/SsoHelper.php',
 
121
  'CreativeMail\\Integrations\\Integration' => __DIR__ . '/../..' . '/src/Integrations/Integration.php',
122
  'CreativeMail\\Managers\\AdminManager' => __DIR__ . '/../..' . '/src/Managers/AdminManager.php',
123
  'CreativeMail\\Managers\\ApiManager' => __DIR__ . '/../..' . '/src/Managers/ApiManager.php',
133
  'CreativeMail\\Models\\CartData' => __DIR__ . '/../..' . '/src/Models/CartData.php',
134
  'CreativeMail\\Models\\Checkout' => __DIR__ . '/../..' . '/src/Models/Checkout.php',
135
  'CreativeMail\\Models\\CheckoutSave' => __DIR__ . '/../..' . '/src/Models/CheckoutSave.php',
136
+ 'CreativeMail\\Models\\Coupon' => __DIR__ . '/../..' . '/src/Models/Coupon.php',
137
  'CreativeMail\\Models\\CustomerNewAccount' => __DIR__ . '/../..' . '/src/Models/CustomerNewAccount.php',
138
  'CreativeMail\\Models\\CustomerNote' => __DIR__ . '/../..' . '/src/Models/CustomerNote.php',
139
  'CreativeMail\\Models\\CustomerResetPassword' => __DIR__ . '/../..' . '/src/Models/CustomerResetPassword.php',
142
  'CreativeMail\\Models\\OptionsSchema' => __DIR__ . '/../..' . '/src/Models/OptionsSchema.php',
143
  'CreativeMail\\Models\\Order' => __DIR__ . '/../..' . '/src/Models/Order.php',
144
  'CreativeMail\\Models\\OrderBilling' => __DIR__ . '/../..' . '/src/Models/OrderBilling.php',
145
+ 'CreativeMail\\Models\\OrderBillingPaymentDetails' => __DIR__ . '/../..' . '/src/Models/OrderBillingPaymentDetails.php',
146
+ 'CreativeMail\\Models\\OrderBillingShipping' => __DIR__ . '/../..' . '/src/Models/OrderBillingShipping.php',
147
+ 'CreativeMail\\Models\\OrderLineItem' => __DIR__ . '/../..' . '/src/Models/OrderLineItem.php',
148
  'CreativeMail\\Models\\RequestItem' => __DIR__ . '/../..' . '/src/Models/RequestItem.php',
149
  'CreativeMail\\Models\\Response' => __DIR__ . '/../..' . '/src/Models/Response.php',
150
  'CreativeMail\\Models\\TriggerExecution' => __DIR__ . '/../..' . '/src/Models/TriggerExecution.php',
173
  'CreativeMail\\Modules\\Contacts\\Models\\ContactAddressModel' => __DIR__ . '/../..' . '/src/Modules/Contacts/Models/ContactAddressModel.php',
174
  'CreativeMail\\Modules\\Contacts\\Models\\ContactFormSevenSubmission' => __DIR__ . '/../..' . '/src/Modules/Contacts/Models/ContactFormSevenSubmission.php',
175
  'CreativeMail\\Modules\\Contacts\\Models\\ContactModel' => __DIR__ . '/../..' . '/src/Modules/Contacts/Models/ContactModel.php',
176
+ 'CreativeMail\\Modules\\Contacts\\Models\\FormidableContactForm' => __DIR__ . '/../..' . '/src/Modules/Contacts/Models/FormidableContactForm.php',
177
  'CreativeMail\\Modules\\Contacts\\Models\\OptActionBy' => __DIR__ . '/../..' . '/src/Modules/Contacts/Models/OptActionBy.php',
178
  'CreativeMail\\Modules\\Contacts\\Processors\\ContactsSyncBackgroundProcessor' => __DIR__ . '/../..' . '/src/Modules/Contacts/Processors/ContactsSyncBackgroundProcessor.php',
179
  'CreativeMail\\Modules\\Contacts\\Services\\ContactsSyncService' => __DIR__ . '/../..' . '/src/Modules/Contacts/Services/ContactsSyncService.php',
251
  public static function getInitializer(ClassLoader $loader)
252
  {
253
  return \Closure::bind(function () use ($loader) {
254
+ $loader->prefixLengthsPsr4 = ComposerStaticInit315811124a911e9493d5fdf73305051b::$prefixLengthsPsr4;
255
+ $loader->prefixDirsPsr4 = ComposerStaticInit315811124a911e9493d5fdf73305051b::$prefixDirsPsr4;
256
+ $loader->prefixesPsr0 = ComposerStaticInit315811124a911e9493d5fdf73305051b::$prefixesPsr0;
257
+ $loader->classMap = ComposerStaticInit315811124a911e9493d5fdf73305051b::$classMap;
258
 
259
  }, null, ClassLoader::class);
260
  }
vendor/composer/installed.json CHANGED
@@ -38,11 +38,7 @@
38
  "email": "nom@deliciousbrains.com"
39
  }
40
  ],
41
- "description": "WP Background Processing can be used to fire off non-blocking asynchronous requests or as a background processing tool, allowing you to queue tasks.",
42
- "support": {
43
- "issues": "https://github.com/deliciousbrains/wp-background-processing/issues",
44
- "source": "https://github.com/deliciousbrains/wp-background-processing/tree/1.0.2"
45
- }
46
  },
47
  {
48
  "name": "defuse/php-encryption",
@@ -106,11 +102,7 @@
106
  "openssl",
107
  "security",
108
  "symmetric key cryptography"
109
- ],
110
- "support": {
111
- "issues": "https://github.com/defuse/php-encryption/issues",
112
- "source": "https://github.com/defuse/php-encryption/tree/v2.3.1"
113
- }
114
  },
115
  {
116
  "name": "firebase/php-jwt",
@@ -165,25 +157,21 @@
165
  "keywords": [
166
  "jwt",
167
  "php"
168
- ],
169
- "support": {
170
- "issues": "https://github.com/firebase/php-jwt/issues",
171
- "source": "https://github.com/firebase/php-jwt/tree/v5.5.1"
172
- }
173
  },
174
  {
175
  "name": "mindscape/raygun4php",
176
- "version": "v1.8.4",
177
- "version_normalized": "1.8.4.0",
178
  "source": {
179
  "type": "git",
180
  "url": "https://github.com/MindscapeHQ/raygun4php.git",
181
- "reference": "7f841d251f5985817cec93e131bb334561c03338"
182
  },
183
  "dist": {
184
  "type": "zip",
185
- "url": "https://api.github.com/repos/MindscapeHQ/raygun4php/zipball/7f841d251f5985817cec93e131bb334561c03338",
186
- "reference": "7f841d251f5985817cec93e131bb334561c03338",
187
  "shasum": ""
188
  },
189
  "require": {
@@ -195,7 +183,7 @@
195
  "suggest": {
196
  "ext-curl": "*"
197
  },
198
- "time": "2019-03-07T01:23:01+00:00",
199
  "type": "library",
200
  "installation-source": "dist",
201
  "autoload": {
@@ -221,11 +209,7 @@
221
  "exceptions",
222
  "logging",
223
  "raygun"
224
- ],
225
- "support": {
226
- "issues": "https://github.com/MindscapeHQ/raygun4php/issues",
227
- "source": "https://github.com/MindscapeHQ/raygun4php/tree/v1.8.4"
228
- }
229
  },
230
  {
231
  "name": "paragonie/random_compat",
@@ -272,26 +256,21 @@
272
  "polyfill",
273
  "pseudorandom",
274
  "random"
275
- ],
276
- "support": {
277
- "email": "info@paragonie.com",
278
- "issues": "https://github.com/paragonie/random_compat/issues",
279
- "source": "https://github.com/paragonie/random_compat"
280
- }
281
  },
282
  {
283
  "name": "php-stubs/woocommerce-stubs",
284
- "version": "v6.9.3",
285
- "version_normalized": "6.9.3.0",
286
  "source": {
287
  "type": "git",
288
  "url": "https://github.com/php-stubs/woocommerce-stubs.git",
289
- "reference": "870c0c0abcd5ae9a8be58fc797123a4d882e604e"
290
  },
291
  "dist": {
292
  "type": "zip",
293
- "url": "https://api.github.com/repos/php-stubs/woocommerce-stubs/zipball/870c0c0abcd5ae9a8be58fc797123a4d882e604e",
294
- "reference": "870c0c0abcd5ae9a8be58fc797123a4d882e604e",
295
  "shasum": ""
296
  },
297
  "require": {
@@ -305,7 +284,7 @@
305
  "symfony/polyfill-php73": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
306
  "szepeviktor/phpstan-wordpress": "WordPress extensions for PHPStan"
307
  },
308
- "time": "2022-09-20T23:28:43+00:00",
309
  "type": "library",
310
  "installation-source": "dist",
311
  "notification-url": "https://packagist.org/downloads/",
@@ -319,25 +298,21 @@
319
  "static analysis",
320
  "woocommerce",
321
  "wordpress"
322
- ],
323
- "support": {
324
- "issues": "https://github.com/php-stubs/woocommerce-stubs/issues",
325
- "source": "https://github.com/php-stubs/woocommerce-stubs/tree/v6.9.3"
326
- }
327
  },
328
  {
329
  "name": "php-stubs/wordpress-stubs",
330
- "version": "v6.0.1",
331
- "version_normalized": "6.0.1.0",
332
  "source": {
333
  "type": "git",
334
  "url": "https://github.com/php-stubs/wordpress-stubs.git",
335
- "reference": "e04781a84e364615a7b5f70fdc345c8253ca5b8f"
336
  },
337
  "dist": {
338
  "type": "zip",
339
- "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/e04781a84e364615a7b5f70fdc345c8253ca5b8f",
340
- "reference": "e04781a84e364615a7b5f70fdc345c8253ca5b8f",
341
  "shasum": ""
342
  },
343
  "replace": {
@@ -355,7 +330,7 @@
355
  "symfony/polyfill-php73": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
356
  "szepeviktor/phpstan-wordpress": "WordPress extensions for PHPStan"
357
  },
358
- "time": "2022-07-15T11:10:45+00:00",
359
  "type": "library",
360
  "installation-source": "dist",
361
  "notification-url": "https://packagist.org/downloads/",
@@ -368,11 +343,7 @@
368
  "PHPStan",
369
  "static analysis",
370
  "wordpress"
371
- ],
372
- "support": {
373
- "issues": "https://github.com/php-stubs/wordpress-stubs/issues",
374
- "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.0.1"
375
- }
376
  },
377
  {
378
  "name": "phpcompatibility/php-compatibility",
@@ -432,11 +403,7 @@
432
  "compatibility",
433
  "phpcs",
434
  "standards"
435
- ],
436
- "support": {
437
- "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues",
438
- "source": "https://github.com/PHPCompatibility/PHPCompatibility"
439
- }
440
  },
441
  {
442
  "name": "phpstan/extension-installer",
@@ -479,25 +446,21 @@
479
  "license": [
480
  "MIT"
481
  ],
482
- "description": "Composer plugin for automatic installation of PHPStan extensions",
483
- "support": {
484
- "issues": "https://github.com/phpstan/extension-installer/issues",
485
- "source": "https://github.com/phpstan/extension-installer/tree/1.1.0"
486
- }
487
  },
488
  {
489
  "name": "phpstan/phpstan",
490
- "version": "1.8.2",
491
- "version_normalized": "1.8.2.0",
492
  "source": {
493
  "type": "git",
494
  "url": "https://github.com/phpstan/phpstan.git",
495
- "reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c"
496
  },
497
  "dist": {
498
  "type": "zip",
499
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c53312ecc575caf07b0e90dee43883fdf90ca67c",
500
- "reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c",
501
  "shasum": ""
502
  },
503
  "require": {
@@ -506,7 +469,7 @@
506
  "conflict": {
507
  "phpstan/phpstan-shim": "*"
508
  },
509
- "time": "2022-07-20T09:57:31+00:00",
510
  "bin": [
511
  "phpstan",
512
  "phpstan.phar"
@@ -523,10 +486,10 @@
523
  "MIT"
524
  ],
525
  "description": "PHPStan - PHP Static Analysis Tool",
526
- "support": {
527
- "issues": "https://github.com/phpstan/phpstan/issues",
528
- "source": "https://github.com/phpstan/phpstan/tree/1.8.2"
529
- },
530
  "funding": [
531
  {
532
  "url": "https://github.com/ondrejmirtes",
@@ -536,10 +499,6 @@
536
  "url": "https://github.com/phpstan",
537
  "type": "github"
538
  },
539
- {
540
- "url": "https://www.patreon.com/phpstan",
541
- "type": "patreon"
542
- },
543
  {
544
  "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan",
545
  "type": "tidelift"
@@ -548,17 +507,17 @@
548
  },
549
  {
550
  "name": "squizlabs/php_codesniffer",
551
- "version": "3.6.2",
552
- "version_normalized": "3.6.2.0",
553
  "source": {
554
  "type": "git",
555
  "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
556
- "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a"
557
  },
558
  "dist": {
559
  "type": "zip",
560
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a",
561
- "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a",
562
  "shasum": ""
563
  },
564
  "require": {
@@ -570,7 +529,7 @@
570
  "require-dev": {
571
  "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
572
  },
573
- "time": "2021-12-12T21:44:58+00:00",
574
  "bin": [
575
  "bin/phpcs",
576
  "bin/phpcbf"
@@ -597,12 +556,7 @@
597
  "keywords": [
598
  "phpcs",
599
  "standards"
600
- ],
601
- "support": {
602
- "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
603
- "source": "https://github.com/squizlabs/PHP_CodeSniffer",
604
- "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
605
- }
606
  },
607
  {
608
  "name": "symfony/polyfill-php73",
@@ -667,9 +621,6 @@
667
  "portable",
668
  "shim"
669
  ],
670
- "support": {
671
- "source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0"
672
- },
673
  "funding": [
674
  {
675
  "url": "https://symfony.com/sponsor",
@@ -741,10 +692,6 @@
741
  "static analysis",
742
  "wordpress"
743
  ],
744
- "support": {
745
- "issues": "https://github.com/szepeviktor/phpstan-wordpress/issues",
746
- "source": "https://github.com/szepeviktor/phpstan-wordpress/tree/v1.1.3"
747
- },
748
  "funding": [
749
  {
750
  "url": "https://www.paypal.me/szepeviktor",
38
  "email": "nom@deliciousbrains.com"
39
  }
40
  ],
41
+ "description": "WP Background Processing can be used to fire off non-blocking asynchronous requests or as a background processing tool, allowing you to queue tasks."
 
 
 
 
42
  },
43
  {
44
  "name": "defuse/php-encryption",
102
  "openssl",
103
  "security",
104
  "symmetric key cryptography"
105
+ ]
 
 
 
 
106
  },
107
  {
108
  "name": "firebase/php-jwt",
157
  "keywords": [
158
  "jwt",
159
  "php"
160
+ ]
 
 
 
 
161
  },
162
  {
163
  "name": "mindscape/raygun4php",
164
+ "version": "v1.8.5",
165
+ "version_normalized": "1.8.5.0",
166
  "source": {
167
  "type": "git",
168
  "url": "https://github.com/MindscapeHQ/raygun4php.git",
169
+ "reference": "ab5401d7bd042ce69810763274d250ac9c10068a"
170
  },
171
  "dist": {
172
  "type": "zip",
173
+ "url": "https://api.github.com/repos/MindscapeHQ/raygun4php/zipball/ab5401d7bd042ce69810763274d250ac9c10068a",
174
+ "reference": "ab5401d7bd042ce69810763274d250ac9c10068a",
175
  "shasum": ""
176
  },
177
  "require": {
183
  "suggest": {
184
  "ext-curl": "*"
185
  },
186
+ "time": "2022-07-11T22:19:37+00:00",
187
  "type": "library",
188
  "installation-source": "dist",
189
  "autoload": {
209
  "exceptions",
210
  "logging",
211
  "raygun"
212
+ ]
 
 
 
 
213
  },
214
  {
215
  "name": "paragonie/random_compat",
256
  "polyfill",
257
  "pseudorandom",
258
  "random"
259
+ ]
 
 
 
 
 
260
  },
261
  {
262
  "name": "php-stubs/woocommerce-stubs",
263
+ "version": "v6.9.4",
264
+ "version_normalized": "6.9.4.0",
265
  "source": {
266
  "type": "git",
267
  "url": "https://github.com/php-stubs/woocommerce-stubs.git",
268
+ "reference": "823aa38297d9013b96c5eab2846c260bbe12b975"
269
  },
270
  "dist": {
271
  "type": "zip",
272
+ "url": "https://api.github.com/repos/php-stubs/woocommerce-stubs/zipball/823aa38297d9013b96c5eab2846c260bbe12b975",
273
+ "reference": "823aa38297d9013b96c5eab2846c260bbe12b975",
274
  "shasum": ""
275
  },
276
  "require": {
284
  "symfony/polyfill-php73": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
285
  "szepeviktor/phpstan-wordpress": "WordPress extensions for PHPStan"
286
  },
287
+ "time": "2022-10-12T08:01:21+00:00",
288
  "type": "library",
289
  "installation-source": "dist",
290
  "notification-url": "https://packagist.org/downloads/",
298
  "static analysis",
299
  "woocommerce",
300
  "wordpress"
301
+ ]
 
 
 
 
302
  },
303
  {
304
  "name": "php-stubs/wordpress-stubs",
305
+ "version": "v6.0.2",
306
+ "version_normalized": "6.0.2.0",
307
  "source": {
308
  "type": "git",
309
  "url": "https://github.com/php-stubs/wordpress-stubs.git",
310
+ "reference": "165b84f082db851e76ec51bebcde550d03976893"
311
  },
312
  "dist": {
313
  "type": "zip",
314
+ "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/165b84f082db851e76ec51bebcde550d03976893",
315
+ "reference": "165b84f082db851e76ec51bebcde550d03976893",
316
  "shasum": ""
317
  },
318
  "replace": {
330
  "symfony/polyfill-php73": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
331
  "szepeviktor/phpstan-wordpress": "WordPress extensions for PHPStan"
332
  },
333
+ "time": "2022-09-30T17:46:11+00:00",
334
  "type": "library",
335
  "installation-source": "dist",
336
  "notification-url": "https://packagist.org/downloads/",
343
  "PHPStan",
344
  "static analysis",
345
  "wordpress"
346
+ ]
 
 
 
 
347
  },
348
  {
349
  "name": "phpcompatibility/php-compatibility",
403
  "compatibility",
404
  "phpcs",
405
  "standards"
406
+ ]
 
 
 
 
407
  },
408
  {
409
  "name": "phpstan/extension-installer",
446
  "license": [
447
  "MIT"
448
  ],
449
+ "description": "Composer plugin for automatic installation of PHPStan extensions"
 
 
 
 
450
  },
451
  {
452
  "name": "phpstan/phpstan",
453
+ "version": "1.8.11",
454
+ "version_normalized": "1.8.11.0",
455
  "source": {
456
  "type": "git",
457
  "url": "https://github.com/phpstan/phpstan.git",
458
+ "reference": "46e223dd68a620da18855c23046ddb00940b4014"
459
  },
460
  "dist": {
461
  "type": "zip",
462
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/46e223dd68a620da18855c23046ddb00940b4014",
463
+ "reference": "46e223dd68a620da18855c23046ddb00940b4014",
464
  "shasum": ""
465
  },
466
  "require": {
469
  "conflict": {
470
  "phpstan/phpstan-shim": "*"
471
  },
472
+ "time": "2022-10-24T15:45:13+00:00",
473
  "bin": [
474
  "phpstan",
475
  "phpstan.phar"
486
  "MIT"
487
  ],
488
  "description": "PHPStan - PHP Static Analysis Tool",
489
+ "keywords": [
490
+ "dev",
491
+ "static analysis"
492
+ ],
493
  "funding": [
494
  {
495
  "url": "https://github.com/ondrejmirtes",
499
  "url": "https://github.com/phpstan",
500
  "type": "github"
501
  },
 
 
 
 
502
  {
503
  "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan",
504
  "type": "tidelift"
507
  },
508
  {
509
  "name": "squizlabs/php_codesniffer",
510
+ "version": "3.7.1",
511
+ "version_normalized": "3.7.1.0",
512
  "source": {
513
  "type": "git",
514
  "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
515
+ "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619"
516
  },
517
  "dist": {
518
  "type": "zip",
519
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619",
520
+ "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619",
521
  "shasum": ""
522
  },
523
  "require": {
529
  "require-dev": {
530
  "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
531
  },
532
+ "time": "2022-06-18T07:21:10+00:00",
533
  "bin": [
534
  "bin/phpcs",
535
  "bin/phpcbf"
556
  "keywords": [
557
  "phpcs",
558
  "standards"
559
+ ]
 
 
 
 
 
560
  },
561
  {
562
  "name": "symfony/polyfill-php73",
621
  "portable",
622
  "shim"
623
  ],
 
 
 
624
  "funding": [
625
  {
626
  "url": "https://symfony.com/sponsor",
692
  "static analysis",
693
  "wordpress"
694
  ],
 
 
 
 
695
  "funding": [
696
  {
697
  "url": "https://www.paypal.me/szepeviktor",
vendor/mindscape/raygun4php/.travis.yml CHANGED
@@ -1,9 +1,12 @@
1
  language: php
2
 
3
- php: [5.4, 5.5, 7.0]
 
 
4
 
5
  before_script:
6
  - composer self-update
 
7
  - composer install --prefer-source --no-interaction --no-progress
8
 
9
  script: 'vendor/bin/phpunit tests'
1
  language: php
2
 
3
+ dist: trusty
4
+
5
+ php: [5.4, 5.5, 5.6, 7.0, 7.1, 7.2, 7.3, 7.4]
6
 
7
  before_script:
8
  - composer self-update
9
+ - if [[ ${TRAVIS_PHP_VERSION:0:3} =~ ^7\.[234]$ ]] ; then composer require --dev phpunit/phpunit:"^5.7.27" ; fi
10
  - composer install --prefer-source --no-interaction --no-progress
11
 
12
  script: 'vendor/bin/phpunit tests'
vendor/mindscape/raygun4php/sample-apps/.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
1
+ debug.log
2
+ config.php
vendor/mindscape/raygun4php/sample-apps/async-example/README.md ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ ## Setup instructions
2
+
3
+ 1. Install composer dependencies
4
+ 2. Copy `config-sample.php` and rename to `config.php`
5
+ 3. Insert your API key from Raygun into the `API_KEY` field
6
+ 4. Submit the form with empty/zero values to trigger errors
vendor/mindscape/raygun4php/sample-apps/async-example/composer.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ {
2
+ "require": {
3
+ "mindscape/raygun4php": "^1.0",
4
+ "monolog/monolog": "2.0.2"
5
+ }
6
+ }
vendor/mindscape/raygun4php/sample-apps/async-example/config-sample.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ const API_KEY = 'INSERT_YOUR_API_KEY_HERE';
vendor/mindscape/raygun4php/sample-apps/async-example/index.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once 'raygunSetup.php';
3
+ require_once 'viewData.php';
4
+
5
+ $viewData = new ViewData();
6
+ ?>
7
+
8
+ <!DOCTYPE html>
9
+ <html lang="en">
10
+ <head>
11
+ <?php include 'partials/head.php' ?>
12
+ </head>
13
+ <body>
14
+
15
+ <div class="grid-container">
16
+ <div class="grid-x">
17
+ <h2>Runner's pace calculator</h2>
18
+ <div class="cell">
19
+ <form method="post" action="index.php">
20
+ <div class="grid-x grid-margin-x">
21
+ <div class="cell medium-6">
22
+ <label for="time">Time (minutes)</label>
23
+ <input id="time" name="time" type="number" value="<?php echo $viewData->getTime(); ?>"/>
24
+ </div>
25
+ <div class="cell medium-6 grid-margin-x">
26
+ <label for="distance">Distance (km) <strong>DANGER: DO NOT SET TO ZERO!!!</strong></label>
27
+ <input id="distance" name="distance" type="number" step="0.1" value="<?php echo $viewData->getDistance(); ?>"/>
28
+ </div>
29
+ </div>
30
+
31
+ <button type="submit" class="primary button">Calculate</button>
32
+ </form>
33
+
34
+ <?php if ($viewData->hasSentData()) : ?>
35
+ <div class="callout success">
36
+ <p><strong>Average pace:</strong> <?php echo $viewData->getAveragePace(); ?>mins/km</p>
37
+ <p><strong>Average speed:</strong> <?php echo $viewData->getAverageSpeed(); ?>km/hr</p>
38
+ </div>
39
+ <?php endif; ?>
40
+ </div>
41
+ </div>
42
+ </div>
43
+
44
+ </body>
45
+ </html>
46
+
vendor/mindscape/raygun4php/sample-apps/async-example/partials/head.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <meta charset="UTF-8">
2
+ <title>Runner's pace calculator</title>
3
+
4
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/foundation-sites@6.4.3/dist/css/foundation.min.css"
5
+ integrity="sha256-GSio8qamaXapM8Fq9JYdGNTvk/dgs+cMLgPeevOYEx0= sha384-wAweiGTn38CY2DSwAaEffed6iMeflc0FMiuptanbN4J+ib+342gKGpvYRWubPd/+ sha512-QHEb6jOC8SaGTmYmGU19u2FhIfeG+t/hSacIWPpDzOp5yygnthL3JwnilM7LM1dOAbJv62R+/FICfsrKUqv4Gg=="
6
+ crossorigin="anonymous">
7
+
8
+ <script
9
+ src="https://code.jquery.com/jquery-3.4.1.min.js"
10
+ integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
11
+ crossorigin="anonymous"></script>
12
+
13
+ <script src="https://cdn.jsdelivr.net/npm/foundation-sites@6.4.3/dist/js/foundation.min.js"
14
+ integrity="sha256-mRYlCu5EG+ouD07WxLF8v4ZAZYCA6WrmdIXyn1Bv9Vk= sha384-KzKofw4qqetd3kvuQ5AdapWPqV1ZI+CnfyfEwZQgPk8poOLWaabfgJOfmW7uI+AV sha512-0gHfaMkY+Do568TgjJC2iMAV0dQlY4NqbeZ4pr9lVUTXQzKu8qceyd6wg/3Uql9qA2+3X5NHv3IMb05wb387rA=="
15
+ crossorigin="anonymous"></script>
vendor/mindscape/raygun4php/sample-apps/async-example/raygunSetup.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace
4
+ {
5
+ require_once 'vendor/autoload.php';
6
+
7
+ $client = new \Raygun4php\RaygunClient(API_KEY, true, false, false);
8
+
9
+ function error_handler($errno, $errstr, $errfile, $errline ) {
10
+ global $client;
11
+ $client->SendError($errno, $errstr, $errfile, $errline);
12
+ }
13
+
14
+ function exception_handler($exception)
15
+ {
16
+ global $client;
17
+ $client->SendException($exception);
18
+ }
19
+
20
+ function fatal_error()
21
+ {
22
+ global $client;
23
+ $last_error = error_get_last();
24
+
25
+ if (!is_null($last_error)) {
26
+ $errno = $last_error['type'];
27
+ $errstr = $last_error['message'];
28
+ $errfile = $last_error['file'];
29
+ $errline = $last_error['line'];
30
+ $client->SendError($errno, $errstr, $errfile, $errline);
31
+ }
32
+ }
33
+
34
+ set_exception_handler('exception_handler');
35
+ set_error_handler("error_handler");
36
+ register_shutdown_function("fatal_error");
37
+ }
vendor/mindscape/raygun4php/sample-apps/async-example/viewData.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class ViewData
4
+ {
5
+ /**
6
+ * @var int $time
7
+ */
8
+ private $time;
9
+
10
+ /**
11
+ * @var float $distance
12
+ */
13
+ private $distance;
14
+
15
+ const SPEED_PRECISION = 2;
16
+
17
+ public function __construct()
18
+ {
19
+ $this->time = $_POST['time'];
20
+ $this->distance = $_POST['distance'];
21
+ }
22
+
23
+ /**
24
+ * @return int
25
+ */
26
+ public function getTime()
27
+ {
28
+ return $this->time;
29
+ }
30
+
31
+ /**
32
+ * @return float
33
+ */
34
+ public function getDistance()
35
+ {
36
+ return $this->distance;
37
+ }
38
+
39
+ /**
40
+ * @return bool
41
+ */
42
+ public function hasSentData()
43
+ {
44
+ return isset($this->time) && isset($this->distance);
45
+ }
46
+
47
+ /**
48
+ * @return string
49
+ */
50
+ public function getAveragePace()
51
+ {
52
+ return $this->decimalToMinuteString($this->time / $this->distance);
53
+ }
54
+
55
+ /**
56
+ * @return string
57
+ */
58
+ public function getAverageSpeed()
59
+ {
60
+ return round($this->distance / ($this->time / 60), self::SPEED_PRECISION);
61
+ }
62
+
63
+ /**
64
+ * @param float $timeAsDecimal
65
+ * @return string
66
+ */
67
+ private function decimalToMinuteString($timeAsDecimal)
68
+ {
69
+ $whole = floor($timeAsDecimal);
70
+ $decimal = $timeAsDecimal - $whole;
71
+ $roundedMinutes = round($decimal * 60, 0);
72
+ $minutes = str_pad($roundedMinutes, 2, "0", STR_PAD_LEFT);
73
+
74
+ return "{$whole}:{$minutes}";
75
+ }
76
+ }
vendor/mindscape/raygun4php/src/Raygun4php/RaygunClient.php CHANGED
@@ -361,7 +361,7 @@ namespace Raygun4php {
361
  if ($this->proxy) {
362
  $curlOpts[] = "--proxy '" . $this->proxy . "'";
363
  }
364
- $cmd = "curl " . implode(' ', $curlOpts) . " 'https://api.raygun.io:443/entries' > /dev/null 2>&1 &";
365
  $output = array();
366
  $exit;
367
  exec($cmd, $output, $exit);
@@ -435,7 +435,7 @@ namespace Raygun4php {
435
  }
436
 
437
  function toJsonRemoveUnicodeSequences($struct) {
438
- return preg_replace_callback("/\\\\u([a-f0-9]{4})/", function($matches){ return iconv('UCS-4LE','UTF-8',pack('V', hexdec("U$matches[1]"))); }, json_encode($struct));
439
  }
440
 
441
  function removeNullBytes($string) {
361
  if ($this->proxy) {
362
  $curlOpts[] = "--proxy '" . $this->proxy . "'";
363
  }
364
+ $cmd = "curl " . implode(' ', $curlOpts) . " 'https://{$this->host}:{$this->port}{$this->path}' > /dev/null 2>&1 &";
365
  $output = array();
366
  $exit;
367
  exec($cmd, $output, $exit);
435
  }
436
 
437
  function toJsonRemoveUnicodeSequences($struct) {
438
+ return preg_replace_callback("/\\\\u([a-f0-9]{4})/", function($matches){ return iconv('UCS-4LE','UTF-8',pack('V', hexdec($matches[1]))); }, json_encode($struct));
439
  }
440
 
441
  function removeNullBytes($string) {
vendor/phpstan/phpstan/README.md CHANGED
@@ -18,9 +18,9 @@ PHPStan focuses on finding errors in your code without actually running it. It c
18
  even before you write tests for the code. It moves PHP closer to compiled languages in the sense that the correctness of each line of the code
19
  can be checked before you run the actual line.
20
 
21
- **[Read more about PHPStan in an introductory article »](https://phpstan.org/blog/find-bugs-in-your-code-without-writing-tests)**
22
 
23
- **[Try out PHPStan on the on-line playground! »](https://phpstan.org/)**
24
 
25
  ## Sponsors
26
 
@@ -46,7 +46,7 @@ can be checked before you run the actual line.
46
  <br>
47
  <a href="https://zol.fr?utm_source=phpstan"><img src="https://i.imgur.com/dzDgd4s.png" alt="ZOL" width="283" height="64"></a>
48
  &nbsp;&nbsp;&nbsp;
49
- <a href="https://kocourek.uk/"><img src="https://i.imgur.com/EX29z98.png" alt="Stepan Kocourek" width="294" height="64"></a>
50
  <br>
51
  <a href="https://www.shopware.com/en/"><img src="https://i.imgur.com/L4X5w9s.png" alt="Shopware" width="284" height="64"></a>
52
  &nbsp;&nbsp;&nbsp;
@@ -59,8 +59,7 @@ can be checked before you run the actual line.
59
  <a href="https://www.crisp.nl/"><img src="https://i.imgur.com/jRJyPve.png" alt="Crisp.nl" width="283" height="64"></a>
60
  &nbsp;&nbsp;&nbsp;
61
  <a href="https://inviqa.com/"><img src="https://i.imgur.com/G99rj45.png" alt="Inviqa" width="254" height="65"></a>
62
- <br>
63
- <a href="https://www.psyonix.com/"><img src="https://i.imgur.com/p8svxQZ.png" alt="Psyonix" width="254" height="65"></a>
64
 
65
  [**You can now sponsor my open-source work on PHPStan through GitHub Sponsors.**](https://github.com/sponsors/ondrejmirtes)
66
 
18
  even before you write tests for the code. It moves PHP closer to compiled languages in the sense that the correctness of each line of the code
19
  can be checked before you run the actual line.
20
 
21
+ **[Read more about PHPStan »](https://phpstan.org/)**
22
 
23
+ **[Try out PHPStan on the on-line playground! »](https://phpstan.org/try)**
24
 
25
  ## Sponsors
26
 
46
  <br>
47
  <a href="https://zol.fr?utm_source=phpstan"><img src="https://i.imgur.com/dzDgd4s.png" alt="ZOL" width="283" height="64"></a>
48
  &nbsp;&nbsp;&nbsp;
49
+ <a href="https://www.psyonix.com/"><img src="https://i.imgur.com/p8svxQZ.png" alt="Psyonix" width="254" height="65"></a>
50
  <br>
51
  <a href="https://www.shopware.com/en/"><img src="https://i.imgur.com/L4X5w9s.png" alt="Shopware" width="284" height="64"></a>
52
  &nbsp;&nbsp;&nbsp;
59
  <a href="https://www.crisp.nl/"><img src="https://i.imgur.com/jRJyPve.png" alt="Crisp.nl" width="283" height="64"></a>
60
  &nbsp;&nbsp;&nbsp;
61
  <a href="https://inviqa.com/"><img src="https://i.imgur.com/G99rj45.png" alt="Inviqa" width="254" height="65"></a>
62
+
 
63
 
64
  [**You can now sponsor my open-source work on PHPStan through GitHub Sponsors.**](https://github.com/sponsors/ondrejmirtes)
65
 
vendor/phpstan/phpstan/bootstrap.php CHANGED
@@ -21,8 +21,8 @@ final class PharAutoloader
21
 
22
  if (self::$composerAutoloader === null) {
23
  self::$composerAutoloader = require 'phar://' . __DIR__ . '/phpstan.phar/vendor/autoload.php';
24
- require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/clue/block-react/src/functions_include.php';
25
  require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/jetbrains/phpstorm-stubs/PhpStormStubsMap.php';
 
26
  require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/promise-stream/src/functions_include.php';
27
  require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/promise-timer/src/functions_include.php';
28
  require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/promise/src/functions_include.php';
21
 
22
  if (self::$composerAutoloader === null) {
23
  self::$composerAutoloader = require 'phar://' . __DIR__ . '/phpstan.phar/vendor/autoload.php';
 
24
  require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/jetbrains/phpstorm-stubs/PhpStormStubsMap.php';
25
+ require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/async/src/functions_include.php';
26
  require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/promise-stream/src/functions_include.php';
27
  require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/promise-timer/src/functions_include.php';
28
  require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/promise/src/functions_include.php';
vendor/phpstan/phpstan/composer.json CHANGED
@@ -2,6 +2,7 @@
2
  "name": "phpstan/phpstan",
3
  "description": "PHPStan - PHP Static Analysis Tool",
4
  "license": ["MIT"],
 
5
  "require": {
6
  "php": "^7.2|^8.0"
7
  },
2
  "name": "phpstan/phpstan",
3
  "description": "PHPStan - PHP Static Analysis Tool",
4
  "license": ["MIT"],
5
+ "keywords": ["dev", "static analysis"],
6
  "require": {
7
  "php": "^7.2|^8.0"
8
  },
vendor/phpstan/phpstan/phpstan.phar CHANGED
Binary file
vendor/phpstan/phpstan/phpstan.phar.asc CHANGED
@@ -1,16 +1,16 @@
1
  -----BEGIN PGP SIGNATURE-----
2
 
3
- iQIzBAABCgAdFiEE0yaA1ZV9xxFr4pwUzxoQjQ565yAFAmLX0XwACgkQzxoQjQ56
4
- 5yAmDw/+KPoaY+vsYXrYjbNcYmXyH+9ca8Yl1WkgqMOAAiojQBAdN+PIeXqdM4P1
5
- ODJq7SGPqhR5j9dK3k4wxvTkmAVlFHWCbOQS0eCueoV2s0w0Sg9xkut7zTMwwBTp
6
- I+0TbU9W7DdnDk6k6xoNCNhT8OYpMElmwhS9nChoY2+cwdWJNZ0Lr5JeXwvb5R7W
7
- YnHUqO/zTIAjwJNdKwb27J9szwL3GQ4nB9gSoKXCFQTIONszfMYNwboy3VlD8m/F
8
- irh9ZZeZsMlCpEO9Rsqx4QyOvbLy0D2jEOKNYzXPQea9dx9gQvDiWJrVETsQBwkc
9
- iWJ/HJVhs3ng7iyUfMr8VAPn7rf+3fSqYeQUs5Z5/ubqABF2ZI9/4DIPGsXtqH7q
10
- b5OTOvSucvRpsxudnJElKWhkCjZUyjYzBqGdZ6erCh+GTiM4uFNB/en/QObfHmP2
11
- z4D41Dk9peLxstqlrwoLL0sJCHR4fQZFvPKrQ6sKlTKliu1zBc0HcEqq3BFalKF+
12
- XO2PT1QVNXx/9IqOruKm+M5siY63VKDwE/DXJZZTUPz7GN/Cr9j5Jz3pjq8jL0CR
13
- e4D+sEu7xXzlJa7MFqg2odZhLTRYuM/DHZCj3cOyQGlYUQ+tZMGsAiix9JyO7XhB
14
- 1jzEMugtAglPAsmHr0HR/+oz+YDgwQEmQA4VO4l0swCNmjzLITA=
15
- =LM6h
16
  -----END PGP SIGNATURE-----
1
  -----BEGIN PGP SIGNATURE-----
2
 
3
+ iQIzBAABCgAdFiEE0yaA1ZV9xxFr4pwUzxoQjQ565yAFAmNWsvsACgkQzxoQjQ56
4
+ 5yDRxBAAjWCLhtqGMBf/5UB8lDTa8+jKeeeXw7tdRQtsEIL5KdRVCFGrpPDWA0pi
5
+ /F9akCBG1gYCPxAX5gD6khEWgSxQ6PItxupskpQWRYlYqHC0EA3CyYGecpBb6F9l
6
+ jRHQIlSzrAiuVI3hTX5EAUHxbPxhTC0zO+wKcvM0jLsOCtUQrWWSp12Nr7GZTxWw
7
+ 6IM3IKRdPnAMHwuoVWOcocR01NAkvpoWK1GtTfhu4E0c2XLsUpbW1rtiZQvf3W/H
8
+ yT47rran+dYOy9scE4sxNRtB4NZ6Bk5GKwR8XzUu1N7X5dL+/NPax4p0CKthyG+n
9
+ /VZdsIv8LnWCqXOOg1cjfYy/zlT8NUB/wmXpWDyxsw/T7Tc81QzJ1oqXcHq1oBXQ
10
+ OqbYAuZzk+nXSt6KhybYgKx1VyG6L4Xchu30ly5hlEHexoZCzWm8BZM2Ii3mT5gT
11
+ dSBDVghNs0dmgP7hRI5uBNtyE+Mnip23Nj3d4/Hg4AFSkmUOkugbWr7Gl8H6rKwi
12
+ w5p2i/RCQ6F+UwmSCd+/ZeL88heHO/loR6O2Cj/lCbEXP1djZuIiyv+gZ3FnB4Mr
13
+ s6sB1lQ2ocOyD20B8DLOg5IVdoIAsCtZ3PViZp4NG7oh9N117HQ/+H83GHjmZZn6
14
+ eVW3iw6stdGR6FpIZKdMsaKKPHCfNmuogVDpd8nabmbxl+GlH2g=
15
+ =TOxZ
16
  -----END PGP SIGNATURE-----