Version Description
Download this release
Release Info
Developer | constantcontact |
Plugin | Creative Mail – Easier WordPress & WooCommerce Email Marketing |
Version | 1.3.0 |
Comparing to | |
See all releases |
Code changes from version 1.2.4 to 1.3.0
- CHANGELOG.md +3 -0
- README.md +2 -1
- assets/js/checkout/ConsentCheckoutCapture.js +73 -0
- assets/js/checkout/GuestCheckoutCapture.js +69 -0
- assets/js/checkout/guest.js +11 -0
- assets/js/checkout/index.js +11 -0
- assets/js/consent_checkout.js +1 -0
- assets/js/dashboard.js +6 -4
- assets/js/guest_checkout.js +1 -0
- creative-mail-plugin.php +3 -3
- readme.txt +2 -1
- src/CreativeMail.php +21 -2
- src/managers/AdminManager.php +35 -29
- src/managers/ApiManager.php +21 -0
- src/managers/CheckoutManager.php +681 -0
- src/managers/DatabaseManager.php +275 -0
- src/managers/EmailManager.php +14 -14
- src/modules/DashboardWidgetModule.php +19 -8
- src/modules/contacts/Handlers/NinjaFormsPluginHandler.php +53 -28
- src/modules/contacts/Handlers/WooCommercePluginHandler.php +64 -26
- src/views/admin-dashboard-widget/campaigns.php +2 -2
- src/views/admin-dashboard-widget/exception.php +1 -1
- src/views/admin-dashboard-widget/most-recent-campaigns.php +4 -4
- src/views/admin-dashboard-widget/no-campaign.php +1 -1
- src/views/admin-dashboard-widget/no-ce-account.php +1 -1
- src/views/admin-dashboard-widget/no-woocommerce.php +1 -1
- src/views/admin-feedback-notice/few-contacts.php +1 -1
- src/views/admin-feedback-notice/many-contacts.php +1 -1
- src/views/dashboard.php +4 -4
- src/views/onboarding.php +2 -26
- src/views/settings.php +3 -3
- vendor/autoload.php +1 -1
- vendor/composer/ClassLoader.php +1 -1
- vendor/composer/autoload_classmap.php +2 -0
- vendor/composer/autoload_real.php +4 -4
- vendor/composer/autoload_static.php +6 -4
CHANGELOG.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1 |
Changelog
|
2 |
=========
|
3 |
|
|
|
|
|
|
|
4 |
#### 1.2.4 - December 16 2020
|
5 |
- Introduces a 'Reset' button on the settings page for accounts that are stuck.
|
6 |
|
1 |
Changelog
|
2 |
=========
|
3 |
|
4 |
+
#### 1.3.0 - January 12 2021
|
5 |
+
- Support for abandoned cart emails
|
6 |
+
|
7 |
#### 1.2.4 - December 16 2020
|
8 |
- Introduces a 'Reset' button on the settings page for accounts that are stuck.
|
9 |
|
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.6
|
5 |
Tested up to: 5.6
|
6 |
-
Stable tag: 1.
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
Requires PHP: 5.6
|
@@ -88,6 +88,7 @@ Creative Mail by Constant Contact [Privacy Notice](https://www.endurance.com/pri
|
|
88 |
6. Enhance your brand with logomaker
|
89 |
|
90 |
== Changelog ==
|
|
|
91 |
* 1.2.4 - Introduces a 'Reset' button on the settings page for accounts that are stuck.
|
92 |
* 1.2.3 - Fixes an issue where the banner would show up again after being dismissed.
|
93 |
* 1.2.2 - Introduction of multi step automations and fixes a couple of small issues in the CreativeMail widgets
|
3 |
Tags: email, marketing, newsletter, subscribe, contact form, constant contact, crm, automations, ecommerce, promotion, offers, retargeting
|
4 |
Requires at least: 4.6
|
5 |
Tested up to: 5.6
|
6 |
+
Stable tag: 1.3.0
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
Requires PHP: 5.6
|
88 |
6. Enhance your brand with logomaker
|
89 |
|
90 |
== Changelog ==
|
91 |
+
* 1.3.0 - Support for abandoned cart emails.
|
92 |
* 1.2.4 - Introduces a 'Reset' button on the settings page for accounts that are stuck.
|
93 |
* 1.2.3 - Fixes an issue where the banner would show up again after being dismissed.
|
94 |
* 1.2.2 - Introduction of multi step automations and fixes a couple of small issues in the CreativeMail widgets
|
assets/js/checkout/ConsentCheckoutCapture.js
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// phpcs:disable
|
2 |
+
/**
|
3 |
+
* ConsentCheckoutCapture.
|
4 |
+
*
|
5 |
+
* @package CreativeMail
|
6 |
+
*/
|
7 |
+
export default class ConsentCheckoutCapture {
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @constructor
|
11 |
+
*
|
12 |
+
* @since 1.3.0
|
13 |
+
*/
|
14 |
+
constructor() {
|
15 |
+
this.els = {};
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Init public JS.
|
20 |
+
*
|
21 |
+
* @since 1.3.0
|
22 |
+
*/
|
23 |
+
init() {
|
24 |
+
this.cacheEls();
|
25 |
+
this.bindEvents();
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Cache some DOM elements.
|
30 |
+
*
|
31 |
+
* @since 1.3.0
|
32 |
+
*/
|
33 |
+
cacheEls() {
|
34 |
+
this.els.ce4wpConsent = document.getElementById('ce4wp_no_consent');
|
35 |
+
this.els.wcCheckoutNonce = document.getElementById('woocommerce-process-checkout-nonce');
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Bind callbacks to events.
|
40 |
+
*
|
41 |
+
* @since 1.3.0
|
42 |
+
*/
|
43 |
+
bindEvents() {
|
44 |
+
var self = this;
|
45 |
+
if (this.els.ce4wpConsent && typeof this.els.ce4wpConsent.addEventListener === "function")
|
46 |
+
{
|
47 |
+
this.els.ce4wpConsent.addEventListener('click', e => {
|
48 |
+
e.preventDefault();
|
49 |
+
window.setTimeout(function () {
|
50 |
+
self.noConsentCaptureGuestCheckout();
|
51 |
+
}, 1500);
|
52 |
+
});
|
53 |
+
}
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Changes the consent of the checkout.
|
58 |
+
*
|
59 |
+
* @since 1.3.0
|
60 |
+
*
|
61 |
+
*/
|
62 |
+
noConsentCaptureGuestCheckout() {
|
63 |
+
var self = this;
|
64 |
+
wp.ajax.send('ce4wp_abandoned_checkouts_no_consent_checkout', {
|
65 |
+
data: {
|
66 |
+
nonce: this.els.wcCheckoutNonce.value
|
67 |
+
},
|
68 |
+
success: function() {
|
69 |
+
self.els.ce4wpConsent.parentElement.style.display = 'none';
|
70 |
+
}
|
71 |
+
});
|
72 |
+
}
|
73 |
+
}
|
assets/js/checkout/GuestCheckoutCapture.js
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// phpcs:disable
|
2 |
+
/**
|
3 |
+
* GuestCheckoutCapture.
|
4 |
+
*
|
5 |
+
* @package CreativeMail
|
6 |
+
*/
|
7 |
+
|
8 |
+
import validateEmail from 'filter-validate-email';
|
9 |
+
|
10 |
+
export default class GuestCheckoutCapture {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @constructor
|
14 |
+
*
|
15 |
+
* @since 1.3.0
|
16 |
+
*/
|
17 |
+
constructor() {
|
18 |
+
this.els = {};
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Init public JS.
|
23 |
+
*
|
24 |
+
* @since 1.3.0
|
25 |
+
*/
|
26 |
+
init() {
|
27 |
+
this.cacheEls();
|
28 |
+
this.bindEvents();
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Cache some DOM elements.
|
33 |
+
*
|
34 |
+
* @since 1.3.0
|
35 |
+
*/
|
36 |
+
cacheEls() {
|
37 |
+
this.els.billingEmail = document.getElementById( 'billing_email' );
|
38 |
+
this.els.wcCheckoutNonce = document.getElementById( 'woocommerce-process-checkout-nonce' );
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Bind callbacks to events.
|
43 |
+
*
|
44 |
+
* @since 1.3.0
|
45 |
+
*/
|
46 |
+
bindEvents() {
|
47 |
+
this.els.billingEmail.addEventListener( 'focusout', e => {
|
48 |
+
if ( validateEmail( e.target.value ) ) {
|
49 |
+
this.maybeCaptureGuestCheckout(e.target.value);
|
50 |
+
}
|
51 |
+
} );
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Captures guest checkout if billing email is valid.
|
56 |
+
*
|
57 |
+
* @since 1.3.0
|
58 |
+
*
|
59 |
+
* @param {string} emailAddr Billing email address entered by user.
|
60 |
+
*/
|
61 |
+
maybeCaptureGuestCheckout( emailAddr ) {
|
62 |
+
wp.ajax.send( 'ce4wp_abandoned_checkouts_capture_guest_checkout', {
|
63 |
+
data: {
|
64 |
+
nonce: this.els.wcCheckoutNonce.value,
|
65 |
+
email: emailAddr
|
66 |
+
}
|
67 |
+
} );
|
68 |
+
}
|
69 |
+
}
|
assets/js/checkout/guest.js
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* Javascript.
|
3 |
+
*
|
4 |
+
* @package CreativeMail
|
5 |
+
*/
|
6 |
+
|
7 |
+
import GuestCheckoutCapture from './GuestCheckoutCapture';
|
8 |
+
|
9 |
+
// Capture abandoned carts from non-logged-in users.
|
10 |
+
const MyGuestCheckoutCapture = new GuestCheckoutCapture();
|
11 |
+
MyGuestCheckoutCapture.init();
|
assets/js/checkout/index.js
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* Javascript.
|
3 |
+
*
|
4 |
+
* @package CreativeMail
|
5 |
+
*/
|
6 |
+
|
7 |
+
import ConsentCheckoutCapture from './ConsentCheckoutCapture';
|
8 |
+
|
9 |
+
// Capture consent
|
10 |
+
const MyConsentCheckoutCapture = new ConsentCheckoutCapture();
|
11 |
+
MyConsentCheckoutCapture.init();
|
assets/js/consent_checkout.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
!function(e){var n={};function t(o){if(n[o])return n[o].exports;var c=n[o]={i:o,l:!1,exports:{}};return e[o].call(c.exports,c,c.exports,t),c.l=!0,c.exports}t.m=e,t.c=n,t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:o})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(t.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var c in e)t.d(o,c,function(n){return e[n]}.bind(null,c));return o},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=0)}([function(e,n,t){"use strict";function o(e,n){for(var t=0;t<n.length;t++){var o=n[t];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}t.r(n),(new(function(){function e(){!function(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this,e),this.els={}}var n,t,c;return n=e,(t=[{key:"init",value:function(){this.cacheEls(),this.bindEvents()}},{key:"cacheEls",value:function(){this.els.ce4wpConsent=document.getElementById("ce4wp_no_consent"),this.els.wcCheckoutNonce=document.getElementById("woocommerce-process-checkout-nonce")}},{key:"bindEvents",value:function(){var e=this;this.els.ce4wpConsent&&"function"==typeof this.els.ce4wpConsent.addEventListener&&this.els.ce4wpConsent.addEventListener("click",(function(n){n.preventDefault(),window.setTimeout((function(){e.noConsentCaptureGuestCheckout()}),1500)}))}},{key:"noConsentCaptureGuestCheckout",value:function(){var e=this;wp.ajax.send("ce4wp_abandoned_checkouts_no_consent_checkout",{data:{nonce:this.els.wcCheckoutNonce.value},success:function(){e.els.ce4wpConsent.parentElement.style.display="none"}})}}])&&o(n.prototype,t),c&&o(n,c),e}())).init()}]);
|
assets/js/dashboard.js
CHANGED
@@ -19,10 +19,12 @@ function ce4wpNavigateToDashboard(element, linkReference, linkParameters, startC
|
|
19 |
link_parameters: linkParameters || undefined,
|
20 |
action: 'ce4wp_request_sso'
|
21 |
},
|
22 |
-
success: function(
|
23 |
-
|
24 |
-
|
25 |
-
finishCallback
|
|
|
|
|
26 |
}
|
27 |
},
|
28 |
error: function(){
|
19 |
link_parameters: linkParameters || undefined,
|
20 |
action: 'ce4wp_request_sso'
|
21 |
},
|
22 |
+
success: function(response) {
|
23 |
+
if (response.success) {
|
24 |
+
ce4wpWindow.location = response.data.url;
|
25 |
+
if (typeof finishCallback === 'function') {
|
26 |
+
finishCallback(element)
|
27 |
+
}
|
28 |
}
|
29 |
},
|
30 |
error: function(){
|
assets/js/guest_checkout.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
!function(u){var D={};function F(C){if(D[C])return D[C].exports;var A=D[C]={i:C,l:!1,exports:{}};return u[C].call(A.exports,A,A.exports,F),A.l=!0,A.exports}F.m=u,F.c=D,F.d=function(u,D,C){F.o(u,D)||Object.defineProperty(u,D,{enumerable:!0,get:C})},F.r=function(u){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(u,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(u,"__esModule",{value:!0})},F.t=function(u,D){if(1&D&&(u=F(u)),8&D)return u;if(4&D&&"object"==typeof u&&u&&u.__esModule)return u;var C=Object.create(null);if(F.r(C),Object.defineProperty(C,"default",{enumerable:!0,value:u}),2&D&&"string"!=typeof u)for(var A in u)F.d(C,A,function(D){return u[D]}.bind(null,A));return C},F.n=function(u){var D=u&&u.__esModule?function(){return u.default}:function(){return u};return F.d(D,"a",D),D},F.o=function(u,D){return Object.prototype.hasOwnProperty.call(u,D)},F.p="",F(F.s=0)}([function(u,D,F){"use strict";F.r(D);var C=/^(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){255,})(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){65,}@)(?:(?:[\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E]+)|(?:\x22(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F]))*\x22))(?:\.(?:(?:[\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E]+)|(?:\x22(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F]))*\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\.){1,126})+(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))]))$/i,A=/^(?!(?:(?:"?\\[\0-~\u017F\u212A]"?)|(?:"?(?:[\0-!#-\[\]-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])"?)){255,})(?!(?:(?:"?\\[\0-~\u017F\u212A]"?)|(?:"?(?:[\0-!#-\[\]-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])"?)){65,}@)(?:(?:(?:[!#-'\*\+\x2D\/-9=\?A-Z\^-~\xAA\xB2\xB3\xB5\xB9\xBA\xBC-\xBE\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0345\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u0660-\u0669\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07C0-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0966-\u096F\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09E6-\u09F1\u09F4-\u09F9\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AE6-\u0AEF\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71-\u0B77\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0BE6-\u0BF2\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C66-\u0C6F\u0C78-\u0C7E\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CE6-\u0CEF\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D58-\u0D61\u0D66-\u0D78\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DE6-\u0DEF\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F20-\u0F33\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F-\u1049\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1369-\u137C\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A16\u1A20-\u1A54\u1A80-\u1A89\u1A90-\u1A99\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B50-\u1B59\u1B83-\u1BA0\u1BAE-\u1BE5\u1C00-\u1C23\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2070\u2071\u2074-\u2079\u207F-\u2089\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2150-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2CFD\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u3192-\u3195\u31A0-\u31BA\u31F0-\u31FF\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\u3400-\u4DB5\u4E00-\u9FEF\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7B9\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA830-\uA835\uA840-\uA873\uA882-\uA8B3\uA8D0-\uA8D9\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA900-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF-\uA9D9\uA9E0-\uA9E4\uA9E6-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD07-\uDD33\uDD40-\uDD78\uDD8A\uDD8B\uDE80-\uDE9C\uDEA0-\uDED0\uDEE1-\uDEFB\uDF00-\uDF23\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC58-\uDC76\uDC79-\uDC9E\uDCA7-\uDCAF\uDCE0-\uDCF2\uDCF4\uDCF5\uDCFB-\uDD1B\uDD20-\uDD39\uDD80-\uDDB7\uDDBC-\uDDCF\uDDD2-\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE40-\uDE48\uDE60-\uDE7E\uDE80-\uDE9F\uDEC0-\uDEC7\uDEC9-\uDEE4\uDEEB-\uDEEF\uDF00-\uDF35\uDF40-\uDF55\uDF58-\uDF72\uDF78-\uDF91\uDFA9-\uDFAF]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDCFA-\uDD23\uDD30-\uDD39\uDE60-\uDE7E\uDF00-\uDF27\uDF30-\uDF45\uDF51-\uDF54]|\uD804[\uDC03-\uDC37\uDC52-\uDC6F\uDC83-\uDCAF\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD03-\uDD26\uDD36-\uDD3F\uDD44\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDD0-\uDDDA\uDDDC\uDDE1-\uDDF4\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDEF0-\uDEF9\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC50-\uDC59\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE50-\uDE59\uDE80-\uDEAA\uDEC0-\uDEC9\uDF00-\uDF1A\uDF30-\uDF3B]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCF2\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC50-\uDC6C\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDDA0-\uDDA9\uDEE0-\uDEF2]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF50-\uDF59\uDF5B-\uDF61\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE96\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFF1]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD834[\uDEE0-\uDEF3\uDF60-\uDF78]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD83A[\uDC00-\uDCC4\uDCC7-\uDCCF\uDD00-\uDD43\uDD50-\uDD59]|\uD83B[\uDC71-\uDCAB\uDCAD-\uDCAF\uDCB1-\uDCB4\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83C[\uDD00-\uDD0C]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D])+)|(?:"(?:(?:[\x01-\x08\x0B\f\x0E-\x1F!#-\[\]-\x7F\xAA\xB2\xB3\xB5\xB9\xBA\xBC-\xBE\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0345\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u0660-\u0669\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07C0-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0966-\u096F\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09E6-\u09F1\u09F4-\u09F9\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AE6-\u0AEF\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71-\u0B77\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0BE6-\u0BF2\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C66-\u0C6F\u0C78-\u0C7E\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CE6-\u0CEF\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D58-\u0D61\u0D66-\u0D78\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DE6-\u0DEF\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F20-\u0F33\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F-\u1049\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1369-\u137C\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A16\u1A20-\u1A54\u1A80-\u1A89\u1A90-\u1A99\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B50-\u1B59\u1B83-\u1BA0\u1BAE-\u1BE5\u1C00-\u1C23\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2070\u2071\u2074-\u2079\u207F-\u2089\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2150-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2CFD\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u3192-\u3195\u31A0-\u31BA\u31F0-\u31FF\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\u3400-\u4DB5\u4E00-\u9FEF\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7B9\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA830-\uA835\uA840-\uA873\uA882-\uA8B3\uA8D0-\uA8D9\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA900-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF-\uA9D9\uA9E0-\uA9E4\uA9E6-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD07-\uDD33\uDD40-\uDD78\uDD8A\uDD8B\uDE80-\uDE9C\uDEA0-\uDED0\uDEE1-\uDEFB\uDF00-\uDF23\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC58-\uDC76\uDC79-\uDC9E\uDCA7-\uDCAF\uDCE0-\uDCF2\uDCF4\uDCF5\uDCFB-\uDD1B\uDD20-\uDD39\uDD80-\uDDB7\uDDBC-\uDDCF\uDDD2-\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE40-\uDE48\uDE60-\uDE7E\uDE80-\uDE9F\uDEC0-\uDEC7\uDEC9-\uDEE4\uDEEB-\uDEEF\uDF00-\uDF35\uDF40-\uDF55\uDF58-\uDF72\uDF78-\uDF91\uDFA9-\uDFAF]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDCFA-\uDD23\uDD30-\uDD39\uDE60-\uDE7E\uDF00-\uDF27\uDF30-\uDF45\uDF51-\uDF54]|\uD804[\uDC03-\uDC37\uDC52-\uDC6F\uDC83-\uDCAF\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD03-\uDD26\uDD36-\uDD3F\uDD44\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDD0-\uDDDA\uDDDC\uDDE1-\uDDF4\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDEF0-\uDEF9\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC50-\uDC59\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE50-\uDE59\uDE80-\uDEAA\uDEC0-\uDEC9\uDF00-\uDF1A\uDF30-\uDF3B]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCF2\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC50-\uDC6C\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDDA0-\uDDA9\uDEE0-\uDEF2]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF50-\uDF59\uDF5B-\uDF61\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE96\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFF1]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD834[\uDEE0-\uDEF3\uDF60-\uDF78]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD83A[\uDC00-\uDCC4\uDCC7-\uDCCF\uDD00-\uDD43\uDD50-\uDD59]|\uD83B[\uDC71-\uDCAB\uDCAD-\uDCAF\uDCB1-\uDCB4\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83C[\uDD00-\uDD0C]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D])|(?:\\[\0-\x7F\u017F\u212A]))*"))(?:\.(?:(?:(?:[!#-'\*\+\x2D\/-9=\?A-Z\^-~\xAA\xB2\xB3\xB5\xB9\xBA\xBC-\xBE\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0345\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u0660-\u0669\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07C0-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0966-\u096F\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09E6-\u09F1\u09F4-\u09F9\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AE6-\u0AEF\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71-\u0B77\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0BE6-\u0BF2\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C66-\u0C6F\u0C78-\u0C7E\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CE6-\u0CEF\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D58-\u0D61\u0D66-\u0D78\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DE6-\u0DEF\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F20-\u0F33\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F-\u1049\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1369-\u137C\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A16\u1A20-\u1A54\u1A80-\u1A89\u1A90-\u1A99\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B50-\u1B59\u1B83-\u1BA0\u1BAE-\u1BE5\u1C00-\u1C23\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2070\u2071\u2074-\u2079\u207F-\u2089\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2150-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2CFD\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u3192-\u3195\u31A0-\u31BA\u31F0-\u31FF\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\u3400-\u4DB5\u4E00-\u9FEF\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7B9\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA830-\uA835\uA840-\uA873\uA882-\uA8B3\uA8D0-\uA8D9\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA900-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF-\uA9D9\uA9E0-\uA9E4\uA9E6-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD07-\uDD33\uDD40-\uDD78\uDD8A\uDD8B\uDE80-\uDE9C\uDEA0-\uDED0\uDEE1-\uDEFB\uDF00-\uDF23\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC58-\uDC76\uDC79-\uDC9E\uDCA7-\uDCAF\uDCE0-\uDCF2\uDCF4\uDCF5\uDCFB-\uDD1B\uDD20-\uDD39\uDD80-\uDDB7\uDDBC-\uDDCF\uDDD2-\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE40-\uDE48\uDE60-\uDE7E\uDE80-\uDE9F\uDEC0-\uDEC7\uDEC9-\uDEE4\uDEEB-\uDEEF\uDF00-\uDF35\uDF40-\uDF55\uDF58-\uDF72\uDF78-\uDF91\uDFA9-\uDFAF]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDCFA-\uDD23\uDD30-\uDD39\uDE60-\uDE7E\uDF00-\uDF27\uDF30-\uDF45\uDF51-\uDF54]|\uD804[\uDC03-\uDC37\uDC52-\uDC6F\uDC83-\uDCAF\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD03-\uDD26\uDD36-\uDD3F\uDD44\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDD0-\uDDDA\uDDDC\uDDE1-\uDDF4\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDEF0-\uDEF9\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC50-\uDC59\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE50-\uDE59\uDE80-\uDEAA\uDEC0-\uDEC9\uDF00-\uDF1A\uDF30-\uDF3B]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCF2\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC50-\uDC6C\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDDA0-\uDDA9\uDEE0-\uDEF2]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF50-\uDF59\uDF5B-\uDF61\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE96\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFF1]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD834[\uDEE0-\uDEF3\uDF60-\uDF78]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD83A[\uDC00-\uDCC4\uDCC7-\uDCCF\uDD00-\uDD43\uDD50-\uDD59]|\uD83B[\uDC71-\uDCAB\uDCAD-\uDCAF\uDCB1-\uDCB4\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83C[\uDD00-\uDD0C]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D])+)|(?:"(?:(?:[\x01-\x08\x0B\f\x0E-\x1F!#-\[\]-\x7F\xAA\xB2\xB3\xB5\xB9\xBA\xBC-\xBE\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0345\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u0660-\u0669\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07C0-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0966-\u096F\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09E6-\u09F1\u09F4-\u09F9\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AE6-\u0AEF\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71-\u0B77\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0BE6-\u0BF2\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C66-\u0C6F\u0C78-\u0C7E\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CE6-\u0CEF\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D58-\u0D61\u0D66-\u0D78\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DE6-\u0DEF\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F20-\u0F33\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F-\u1049\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1369-\u137C\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A16\u1A20-\u1A54\u1A80-\u1A89\u1A90-\u1A99\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B50-\u1B59\u1B83-\u1BA0\u1BAE-\u1BE5\u1C00-\u1C23\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2070\u2071\u2074-\u2079\u207F-\u2089\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2150-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2CFD\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u3192-\u3195\u31A0-\u31BA\u31F0-\u31FF\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\u3400-\u4DB5\u4E00-\u9FEF\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7B9\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA830-\uA835\uA840-\uA873\uA882-\uA8B3\uA8D0-\uA8D9\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA900-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF-\uA9D9\uA9E0-\uA9E4\uA9E6-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD07-\uDD33\uDD40-\uDD78\uDD8A\uDD8B\uDE80-\uDE9C\uDEA0-\uDED0\uDEE1-\uDEFB\uDF00-\uDF23\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC58-\uDC76\uDC79-\uDC9E\uDCA7-\uDCAF\uDCE0-\uDCF2\uDCF4\uDCF5\uDCFB-\uDD1B\uDD20-\uDD39\uDD80-\uDDB7\uDDBC-\uDDCF\uDDD2-\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE40-\uDE48\uDE60-\uDE7E\uDE80-\uDE9F\uDEC0-\uDEC7\uDEC9-\uDEE4\uDEEB-\uDEEF\uDF00-\uDF35\uDF40-\uDF55\uDF58-\uDF72\uDF78-\uDF91\uDFA9-\uDFAF]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDCFA-\uDD23\uDD30-\uDD39\uDE60-\uDE7E\uDF00-\uDF27\uDF30-\uDF45\uDF51-\uDF54]|\uD804[\uDC03-\uDC37\uDC52-\uDC6F\uDC83-\uDCAF\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD03-\uDD26\uDD36-\uDD3F\uDD44\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDD0-\uDDDA\uDDDC\uDDE1-\uDDF4\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDEF0-\uDEF9\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC50-\uDC59\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE50-\uDE59\uDE80-\uDEAA\uDEC0-\uDEC9\uDF00-\uDF1A\uDF30-\uDF3B]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCF2\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC50-\uDC6C\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDDA0-\uDDA9\uDEE0-\uDEF2]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF50-\uDF59\uDF5B-\uDF61\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE96\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFF1]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD834[\uDEE0-\uDEF3\uDF60-\uDF78]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD83A[\uDC00-\uDCC4\uDCC7-\uDCCF\uDD00-\uDD43\uDD50-\uDD59]|\uD83B[\uDC71-\uDCAB\uDCAD-\uDCAF\uDCB1-\uDCB4\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83C[\uDD00-\uDD0C]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D])|(?:\\[\0-\x7F\u017F\u212A]))*")))*@(?:(?:(?!(?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*(?:[\0-\x2D\/-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){64,})(?:(?:(?:xn\x2D\x2D)?[0-9a-z\u017F\u212A]+(?:\x2D+[0-9a-z\u017F\u212A]+)*\.){1,126})+(?:(?:[a-z\u017F\u212A][0-9a-z\u017F\u212A]*)|(?:(?:xn\x2D\x2D)[0-9a-z\u017F\u212A]+))(?:\x2D+[0-9a-z\u017F\u212A]+)*)|(?:\[(?:(?:IPv6:(?:(?:[0-9a-f]{1,4}(?::[0-9a-f]{1,4}){7})|(?:(?!(?:(?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*[0-9a-f][:\]]){7,})(?:[0-9a-f]{1,4}(?::[0-9a-f]{1,4}){0,5})?::(?:[0-9a-f]{1,4}(?::[0-9a-f]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[0-9a-f]{1,4}(?::[0-9a-f]{1,4}){5}:)|(?:(?!(?:(?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*[0-9a-f]:){5,})(?:[0-9a-f]{1,4}(?::[0-9a-f]{1,4}){0,3})?::(?:[0-9a-f]{1,4}(?::[0-9a-f]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\]))$/i;function E(u){return e(C,u)}function B(u){return e(A,u)}var x=function(u){var D=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return(D?B:E)(u)},e=function(u,D){return"string"==typeof D&&D.length<=320&&u.test(D)&&"\n"!==D.slice(-1)&&encodeURIComponent(D).replace(/%../g,"x").length<=320};function t(u,D){for(var F=0;F<D.length;F++){var C=D[F];C.enumerable=C.enumerable||!1,C.configurable=!0,"value"in C&&(C.writable=!0),Object.defineProperty(u,C.key,C)}}(new(function(){function u(){!function(u,D){if(!(u instanceof D))throw new TypeError("Cannot call a class as a function")}(this,u),this.els={}}var D,F,C;return D=u,(F=[{key:"init",value:function(){this.cacheEls(),this.bindEvents()}},{key:"cacheEls",value:function(){this.els.billingEmail=document.getElementById("billing_email"),this.els.wcCheckoutNonce=document.getElementById("woocommerce-process-checkout-nonce")}},{key:"bindEvents",value:function(){var u=this;this.els.billingEmail.addEventListener("focusout",(function(D){x(D.target.value)&&u.maybeCaptureGuestCheckout(D.target.value)}))}},{key:"maybeCaptureGuestCheckout",value:function(u){wp.ajax.send("ce4wp_abandoned_checkouts_capture_guest_checkout",{data:{nonce:this.els.wcCheckoutNonce.value,email:u}})}}])&&t(D.prototype,F),C&&t(D,C),u}())).init()}]);
|
creative-mail-plugin.php
CHANGED
@@ -9,7 +9,7 @@
|
|
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.
|
13 |
* Author URI: https://www.constantcontact.com
|
14 |
*/
|
15 |
use CreativeMail\CreativeMail;
|
@@ -24,7 +24,7 @@ function _load_ce4wp_plugin()
|
|
24 |
define('CE4WP_PLUGIN_DIR', __DIR__ . '/');
|
25 |
define('CE4WP_PLUGIN_URL', plugin_dir_url(__FILE__) . '/');
|
26 |
define('CE4WP_PLUGIN_FILE', __FILE__);
|
27 |
-
define('CE4WP_PLUGIN_VERSION', '1.
|
28 |
define('CE4WP_INSTANCE_UUID_KEY', 'ce4wp_instance_uuid');
|
29 |
define('CE4WP_INSTANCE_HANDSHAKE_TOKEN', 'ce4wp_handshake_token');
|
30 |
define('CE4WP_INSTANCE_HANDSHAKE_EXPIRATION', 'ce4wp_handshake_expiration');
|
@@ -41,7 +41,7 @@ function _load_ce4wp_plugin()
|
|
41 |
define('CE4WP_APP_GATEWAY_URL', 'https://app-gateway.creativemail.com/');
|
42 |
define('CE4WP_APP_URL', 'https://app.creativemail.com/');
|
43 |
define('CE4WP_ENVIRONMENT', 'PRODUCTION');
|
44 |
-
define('CE4WP_BUILD_NUMBER', '
|
45 |
define('CE4WP_BATCH_SIZE', 500);
|
46 |
define('CE4WP_WC_API_KEY_ID', 'ce4wp_woocommerce_api_key_id');
|
47 |
define('CE4WP_WC_API_CONSUMER_KEY', 'ce4wp_woocommerce_consumer_key');
|
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.3.0
|
13 |
* Author URI: https://www.constantcontact.com
|
14 |
*/
|
15 |
use CreativeMail\CreativeMail;
|
24 |
define('CE4WP_PLUGIN_DIR', __DIR__ . '/');
|
25 |
define('CE4WP_PLUGIN_URL', plugin_dir_url(__FILE__) . '/');
|
26 |
define('CE4WP_PLUGIN_FILE', __FILE__);
|
27 |
+
define('CE4WP_PLUGIN_VERSION', '1.3.0');
|
28 |
define('CE4WP_INSTANCE_UUID_KEY', 'ce4wp_instance_uuid');
|
29 |
define('CE4WP_INSTANCE_HANDSHAKE_TOKEN', 'ce4wp_handshake_token');
|
30 |
define('CE4WP_INSTANCE_HANDSHAKE_EXPIRATION', 'ce4wp_handshake_expiration');
|
41 |
define('CE4WP_APP_GATEWAY_URL', 'https://app-gateway.creativemail.com/');
|
42 |
define('CE4WP_APP_URL', 'https://app.creativemail.com/');
|
43 |
define('CE4WP_ENVIRONMENT', 'PRODUCTION');
|
44 |
+
define('CE4WP_BUILD_NUMBER', '961');
|
45 |
define('CE4WP_BATCH_SIZE', 500);
|
46 |
define('CE4WP_WC_API_KEY_ID', 'ce4wp_woocommerce_api_key_id');
|
47 |
define('CE4WP_WC_API_CONSUMER_KEY', 'ce4wp_woocommerce_consumer_key');
|
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.6
|
5 |
Tested up to: 5.6
|
6 |
-
Stable tag: 1.
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
Requires PHP: 5.6
|
@@ -93,6 +93,7 @@ Creative Mail by Constant Contact [Privacy Notice](https://www.endurance.com/pri
|
|
93 |
6. Enhance your brand with logomaker
|
94 |
|
95 |
== Changelog ==
|
|
|
96 |
* 1.2.4 - Introduces a 'Reset' button on the settings page for accounts that are stuck.
|
97 |
* 1.2.3 - Fixes an issue where the banner would show up again after being dismissed.
|
98 |
* 1.2.2 - Introduction of multi step automations and fixes a couple of small issues in the CreativeMail widgets
|
3 |
Tags: email, marketing, newsletter, subscribe, contact form, constant contact, crm, automations, ecommerce, promotion, offers, retargeting
|
4 |
Requires at least: 4.6
|
5 |
Tested up to: 5.6
|
6 |
+
Stable tag: 1.3.0
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
Requires PHP: 5.6
|
93 |
6. Enhance your brand with logomaker
|
94 |
|
95 |
== Changelog ==
|
96 |
+
* 1.3.0 - Support for abandoned cart emails
|
97 |
* 1.2.4 - Introduces a 'Reset' button on the settings page for accounts that are stuck.
|
98 |
* 1.2.3 - Fixes an issue where the banner would show up again after being dismissed.
|
99 |
* 1.2.2 - Introduction of multi step automations and fixes a couple of small issues in the CreativeMail widgets
|
src/CreativeMail.php
CHANGED
@@ -5,6 +5,8 @@ namespace CreativeMail;
|
|
5 |
|
6 |
use CreativeMail\Managers\AdminManager;
|
7 |
use CreativeMail\Managers\ApiManager;
|
|
|
|
|
8 |
use CreativeMail\Managers\EmailManager;
|
9 |
use CreativeMail\Managers\InstanceManager;
|
10 |
use CreativeMail\Managers\IntegrationManager;
|
@@ -18,23 +20,25 @@ class CreativeMail
|
|
18 |
private $instance_manager;
|
19 |
private $integration_manager;
|
20 |
private $email_manager;
|
|
|
|
|
21 |
|
22 |
public function __construct()
|
23 |
{
|
24 |
-
|
25 |
if (current_user_can('administrator')) {
|
26 |
$this->admin_manager = new AdminManager();
|
27 |
}
|
28 |
|
|
|
29 |
$this->instance_manager = new InstanceManager();
|
30 |
$this->api_manager = new ApiManager();
|
31 |
$this->integration_manager = new IntegrationManager();
|
32 |
$this->email_manager = new EmailManager();
|
|
|
33 |
}
|
34 |
|
35 |
public function add_hooks()
|
36 |
{
|
37 |
-
|
38 |
if (!$this->is_active()) {
|
39 |
return;
|
40 |
}
|
@@ -42,11 +46,26 @@ class CreativeMail
|
|
42 |
if ($this->admin_manager !== null) {
|
43 |
$this->admin_manager->add_hooks();
|
44 |
}
|
|
|
|
|
|
|
45 |
|
46 |
$this->api_manager->add_hooks();
|
47 |
$this->integration_manager->add_hooks();
|
48 |
$this->instance_manager->add_hooks();
|
49 |
$this->email_manager->add_hooks();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
}
|
51 |
|
52 |
public function get_integration_manager()
|
5 |
|
6 |
use CreativeMail\Managers\AdminManager;
|
7 |
use CreativeMail\Managers\ApiManager;
|
8 |
+
use CreativeMail\Managers\CheckoutManager;
|
9 |
+
use CreativeMail\Managers\DatabaseManager;
|
10 |
use CreativeMail\Managers\EmailManager;
|
11 |
use CreativeMail\Managers\InstanceManager;
|
12 |
use CreativeMail\Managers\IntegrationManager;
|
20 |
private $instance_manager;
|
21 |
private $integration_manager;
|
22 |
private $email_manager;
|
23 |
+
private $database_manager;
|
24 |
+
private $checkout_manager;
|
25 |
|
26 |
public function __construct()
|
27 |
{
|
|
|
28 |
if (current_user_can('administrator')) {
|
29 |
$this->admin_manager = new AdminManager();
|
30 |
}
|
31 |
|
32 |
+
$this->database_manager = new DatabaseManager();
|
33 |
$this->instance_manager = new InstanceManager();
|
34 |
$this->api_manager = new ApiManager();
|
35 |
$this->integration_manager = new IntegrationManager();
|
36 |
$this->email_manager = new EmailManager();
|
37 |
+
$this->checkout_manager = new CheckoutManager();
|
38 |
}
|
39 |
|
40 |
public function add_hooks()
|
41 |
{
|
|
|
42 |
if (!$this->is_active()) {
|
43 |
return;
|
44 |
}
|
46 |
if ($this->admin_manager !== null) {
|
47 |
$this->admin_manager->add_hooks();
|
48 |
}
|
49 |
+
if ($this->database_manager !== null) {
|
50 |
+
$this->database_manager->add_hooks();
|
51 |
+
}
|
52 |
|
53 |
$this->api_manager->add_hooks();
|
54 |
$this->integration_manager->add_hooks();
|
55 |
$this->instance_manager->add_hooks();
|
56 |
$this->email_manager->add_hooks();
|
57 |
+
|
58 |
+
// check if abandoned cart email is managed by creative mail
|
59 |
+
$enabled = $this->email_manager->is_email_managed('cart_abandoned_ce4wp');
|
60 |
+
if ($enabled)
|
61 |
+
{
|
62 |
+
$this->checkout_manager->add_hooks();
|
63 |
+
}
|
64 |
+
}
|
65 |
+
|
66 |
+
public function get_database_manager()
|
67 |
+
{
|
68 |
+
return $this->database_manager;
|
69 |
}
|
70 |
|
71 |
public function get_integration_manager()
|
src/managers/AdminManager.php
CHANGED
@@ -9,6 +9,7 @@ use CreativeMail\Helpers\SsoHelper;
|
|
9 |
use CreativeMail\Modules\DashboardWidgetModule;
|
10 |
use CreativeMail\Modules\FeedbackNoticeModule;
|
11 |
use Exception;
|
|
|
12 |
|
13 |
/**
|
14 |
* The AdminManager will manage the admin section of the plugin.
|
@@ -76,10 +77,10 @@ class AdminManager
|
|
76 |
add_action('wp_ajax_ce4wp_request_sso', [$this, 'request_single_sign_on_url'] );
|
77 |
|
78 |
// deactivation footer
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
}
|
84 |
|
85 |
private function check_nonce()
|
@@ -88,7 +89,9 @@ class AdminManager
|
|
88 |
|
89 |
if (!wp_verify_nonce($nonce,self::ADMIN_AJAX_NONCE))
|
90 |
{
|
91 |
-
|
|
|
|
|
92 |
}
|
93 |
}
|
94 |
|
@@ -107,6 +110,9 @@ class AdminManager
|
|
107 |
|
108 |
$sso = $this->get_sso_link($linkReference, $linkParameters);
|
109 |
|
|
|
|
|
|
|
110 |
if (is_null($sso)) {
|
111 |
$redirectUrl = EnvironmentHelper::get_app_gateway_url('wordpress/v1.0/instances/open?clearSession=true&redirectUrl=');
|
112 |
$onboardingUrl = EnvironmentHelper::get_app_url() . 'marketing/onboarding/signup?wp_site_name=' . $this->instance_name
|
@@ -126,11 +132,9 @@ class AdminManager
|
|
126 |
}
|
127 |
$onboardingUrl .= '&utm_source=wordpress&utm_medium=plugin&utm_campaign=' . $utm_campaign;
|
128 |
}
|
129 |
-
|
130 |
-
die();
|
131 |
}
|
132 |
-
|
133 |
-
die();
|
134 |
}
|
135 |
|
136 |
function deactivate_survey_post()
|
@@ -211,7 +215,8 @@ class AdminManager
|
|
211 |
<span><input type="radio" name="ce4wp_deactivation_option" value="3"> %s</span>
|
212 |
<span><input type="radio" name="ce4wp_deactivation_option" value="4"> %s</span>
|
213 |
<span><input type="radio" name="ce4wp_deactivation_option" value="5"> %s</span>
|
214 |
-
<span><input type="radio" name="ce4wp_deactivation_option" value="6"> %s
|
|
|
215 |
<br>
|
216 |
<span><input type="submit" class="button button-primary" value="Submit"></span>
|
217 |
</fieldset>
|
@@ -221,13 +226,14 @@ class AdminManager
|
|
221 |
</div>
|
222 |
</div>
|
223 |
</div>',
|
224 |
-
__('
|
225 |
-
__('I
|
226 |
-
__('
|
227 |
-
__('I
|
228 |
-
__('
|
229 |
-
__('
|
230 |
-
__('
|
|
|
231 |
__('Other', self::DOMAIN_CE4WP),
|
232 |
__('Thank you', self::DOMAIN_CE4WP),
|
233 |
__('Close this window and deactivate Creative Mail', self::DOMAIN_CE4WP)
|
@@ -276,7 +282,7 @@ class AdminManager
|
|
276 |
|
277 |
update_option('ce4wp_admin_footer_text_rated', 1);
|
278 |
|
279 |
-
|
280 |
}
|
281 |
|
282 |
/**
|
@@ -374,7 +380,9 @@ class AdminManager
|
|
374 |
|
375 |
// Create the root menu item
|
376 |
$icon = file_get_contents(CE4WP_PLUGIN_DIR . 'assets/images/icon.svg');
|
377 |
-
|
|
|
|
|
378 |
|
379 |
$sub_actions = array(
|
380 |
array(
|
@@ -452,15 +460,9 @@ class AdminManager
|
|
452 |
*/
|
453 |
public function show_setup()
|
454 |
{
|
455 |
-
|
456 |
-
}
|
457 |
|
458 |
-
|
459 |
-
* Renders the consent screen.
|
460 |
-
*/
|
461 |
-
public function show_consent()
|
462 |
-
{
|
463 |
-
include CE4WP_PLUGIN_DIR . 'src/views/consent.php';
|
464 |
}
|
465 |
|
466 |
/**
|
@@ -468,13 +470,17 @@ class AdminManager
|
|
468 |
*/
|
469 |
public function show_dashboard()
|
470 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
471 |
wp_enqueue_script('ce4wp_dashboard', CE4WP_PLUGIN_URL.'assets/js/dashboard.js', null,CE4WP_PLUGIN_VERSION);
|
472 |
wp_localize_script('ce4wp_dashboard', 'ce4wp_data', array(
|
473 |
'url' => admin_url('admin-ajax.php'),
|
474 |
'nonce' => $this->create_nonce()
|
475 |
));
|
476 |
-
|
477 |
-
include CE4WP_PLUGIN_DIR . 'src/views/dashboard.php';
|
478 |
}
|
479 |
|
480 |
/**
|
9 |
use CreativeMail\Modules\DashboardWidgetModule;
|
10 |
use CreativeMail\Modules\FeedbackNoticeModule;
|
11 |
use Exception;
|
12 |
+
use stdClass;
|
13 |
|
14 |
/**
|
15 |
* The AdminManager will manage the admin section of the plugin.
|
77 |
add_action('wp_ajax_ce4wp_request_sso', [$this, 'request_single_sign_on_url'] );
|
78 |
|
79 |
// deactivation footer
|
80 |
+
add_action(self::ADMIN_ENQUEUE_SCRIPTS_HOOK, [$this, 'deactivation_modal_js'], 20);
|
81 |
+
add_action(self::ADMIN_ENQUEUE_SCRIPTS_HOOK, [$this, 'deactivation_modal_css']);
|
82 |
+
add_action('admin_footer', [$this, 'show_deactivation_modal']);
|
83 |
+
add_action('wp_ajax_ce4wp_deactivate_survey', [$this, 'deactivate_survey_post'] );
|
84 |
}
|
85 |
|
86 |
private function check_nonce()
|
89 |
|
90 |
if (!wp_verify_nonce($nonce,self::ADMIN_AJAX_NONCE))
|
91 |
{
|
92 |
+
$response = new stdClass();
|
93 |
+
$response->url = admin_url('admin.php?page=creativemail');
|
94 |
+
wp_send_json_success($response);
|
95 |
}
|
96 |
}
|
97 |
|
110 |
|
111 |
$sso = $this->get_sso_link($linkReference, $linkParameters);
|
112 |
|
113 |
+
$response = new stdClass();
|
114 |
+
$response->url = $sso;
|
115 |
+
|
116 |
if (is_null($sso)) {
|
117 |
$redirectUrl = EnvironmentHelper::get_app_gateway_url('wordpress/v1.0/instances/open?clearSession=true&redirectUrl=');
|
118 |
$onboardingUrl = EnvironmentHelper::get_app_url() . 'marketing/onboarding/signup?wp_site_name=' . $this->instance_name
|
132 |
}
|
133 |
$onboardingUrl .= '&utm_source=wordpress&utm_medium=plugin&utm_campaign=' . $utm_campaign;
|
134 |
}
|
135 |
+
$response->url = $redirectUrl . rawurlencode($onboardingUrl);
|
|
|
136 |
}
|
137 |
+
wp_send_json_success($response);
|
|
|
138 |
}
|
139 |
|
140 |
function deactivate_survey_post()
|
215 |
<span><input type="radio" name="ce4wp_deactivation_option" value="3"> %s</span>
|
216 |
<span><input type="radio" name="ce4wp_deactivation_option" value="4"> %s</span>
|
217 |
<span><input type="radio" name="ce4wp_deactivation_option" value="5"> %s</span>
|
218 |
+
<span><input type="radio" name="ce4wp_deactivation_option" value="6"> %s</span>
|
219 |
+
<span><input type="radio" name="ce4wp_deactivation_option" value="7"> %s: <input type="text" name="other" /></span>
|
220 |
<br>
|
221 |
<span><input type="submit" class="button button-primary" value="Submit"></span>
|
222 |
</fieldset>
|
226 |
</div>
|
227 |
</div>
|
228 |
</div>',
|
229 |
+
__('Sadness... why leave so soon?', self::DOMAIN_CE4WP),
|
230 |
+
__('I’m not sending email campaigns right now', self::DOMAIN_CE4WP),
|
231 |
+
__('It didn’t have the features I want', self::DOMAIN_CE4WP),
|
232 |
+
__('I didn’t like the email editor', self::DOMAIN_CE4WP),
|
233 |
+
__('It was too confusing', self::DOMAIN_CE4WP),
|
234 |
+
__('There were technical issues', self::DOMAIN_CE4WP),
|
235 |
+
__('I don’t have enough email contacts', self::DOMAIN_CE4WP),
|
236 |
+
__('It’s a temporary deactivation', self::DOMAIN_CE4WP),
|
237 |
__('Other', self::DOMAIN_CE4WP),
|
238 |
__('Thank you', self::DOMAIN_CE4WP),
|
239 |
__('Close this window and deactivate Creative Mail', self::DOMAIN_CE4WP)
|
282 |
|
283 |
update_option('ce4wp_admin_footer_text_rated', 1);
|
284 |
|
285 |
+
wp_send_json_success();
|
286 |
}
|
287 |
|
288 |
/**
|
380 |
|
381 |
// Create the root menu item
|
382 |
$icon = file_get_contents(CE4WP_PLUGIN_DIR . 'assets/images/icon.svg');
|
383 |
+
// Filter to change the menu position if there is any conflict.
|
384 |
+
$position = apply_filters( 'ce4wp_menu_position', '35.5' );
|
385 |
+
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);
|
386 |
|
387 |
$sub_actions = array(
|
388 |
array(
|
460 |
*/
|
461 |
public function show_setup()
|
462 |
{
|
463 |
+
$this->enqueue_dashboard_js();
|
|
|
464 |
|
465 |
+
include CE4WP_PLUGIN_DIR . 'src/views/onboarding.php';
|
|
|
|
|
|
|
|
|
|
|
466 |
}
|
467 |
|
468 |
/**
|
470 |
*/
|
471 |
public function show_dashboard()
|
472 |
{
|
473 |
+
$this->enqueue_dashboard_js();
|
474 |
+
|
475 |
+
include CE4WP_PLUGIN_DIR . 'src/views/dashboard.php';
|
476 |
+
}
|
477 |
+
|
478 |
+
private function enqueue_dashboard_js() {
|
479 |
wp_enqueue_script('ce4wp_dashboard', CE4WP_PLUGIN_URL.'assets/js/dashboard.js', null,CE4WP_PLUGIN_VERSION);
|
480 |
wp_localize_script('ce4wp_dashboard', 'ce4wp_data', array(
|
481 |
'url' => admin_url('admin-ajax.php'),
|
482 |
'nonce' => $this->create_nonce()
|
483 |
));
|
|
|
|
|
484 |
}
|
485 |
|
486 |
/**
|
src/managers/ApiManager.php
CHANGED
@@ -156,6 +156,13 @@ class ApiManager
|
|
156 |
return $this->modify_response(new WP_REST_Response($result, 200));
|
157 |
}
|
158 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
159 |
array (
|
160 |
self::ROUTE_PATH => '/wc_key',
|
161 |
self::ROUTE_METHODS => 'GET',
|
@@ -336,6 +343,20 @@ class ApiManager
|
|
336 |
return $response;
|
337 |
}
|
338 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
339 |
private function get_wc_keys()
|
340 |
{
|
341 |
$wcKey = CreativeMail::get_instance()->get_api_manager()->get_or_generate_key();
|
156 |
return $this->modify_response(new WP_REST_Response($result, 200));
|
157 |
}
|
158 |
),
|
159 |
+
array (
|
160 |
+
self::ROUTE_PATH => '/abandoned_checkout',
|
161 |
+
self::ROUTE_METHODS => 'GET',
|
162 |
+
self::ROUTE_CALLBACK => function ($request) {
|
163 |
+
return $this->modify_response($this->get_ce_checkout($request->get_param('uuid')));
|
164 |
+
}
|
165 |
+
),
|
166 |
array (
|
167 |
self::ROUTE_PATH => '/wc_key',
|
168 |
self::ROUTE_METHODS => 'GET',
|
343 |
return $response;
|
344 |
}
|
345 |
|
346 |
+
private function get_ce_checkout($checkout_uuid) {
|
347 |
+
if (empty($checkout_uuid)) {
|
348 |
+
return new WP_REST_Response("No uuid provided", 400);
|
349 |
+
}
|
350 |
+
|
351 |
+
$checkout = CreativeMail::get_instance()->get_database_manager()->get_checkout_data( 'user_id,user_email,checkout_contents,checkout_updated,checkout_created,checkout_recovered,checkout_uuid',
|
352 |
+
'checkout_uuid = %s', [ $checkout_uuid ] );
|
353 |
+
if (empty($checkout)) {
|
354 |
+
return new WP_REST_Response($checkout, 404);
|
355 |
+
}
|
356 |
+
|
357 |
+
return new WP_REST_Response($checkout, 200);
|
358 |
+
}
|
359 |
+
|
360 |
private function get_wc_keys()
|
361 |
{
|
362 |
$wcKey = CreativeMail::get_instance()->get_api_manager()->get_or_generate_key();
|
src/managers/CheckoutManager.php
ADDED
@@ -0,0 +1,681 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
|
4 |
+
namespace CreativeMail\Managers;
|
5 |
+
|
6 |
+
use CreativeMail\CreativeMail;
|
7 |
+
use CreativeMail\Helpers\EnvironmentHelper;
|
8 |
+
use CreativeMail\Helpers\OptionsHelper;
|
9 |
+
use stdClass;
|
10 |
+
use WC_Coupon;
|
11 |
+
use WC_Order;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Class CheckoutManager
|
15 |
+
*
|
16 |
+
* @package CreativeMail\Managers
|
17 |
+
*/
|
18 |
+
class CheckoutManager
|
19 |
+
{
|
20 |
+
/**
|
21 |
+
* Current checkout UUID.
|
22 |
+
*
|
23 |
+
* @var string
|
24 |
+
* @since 1.3.0
|
25 |
+
*/
|
26 |
+
protected $checkout_uuid = '';
|
27 |
+
|
28 |
+
const UPDATE_CHECKOUT_DATA = 'update_checkout_data';
|
29 |
+
const META_CHECKOUT_UUID = 'ce4wp_checkout_uuid';
|
30 |
+
const CHECKOUT_UUID = 'checkout_uuid';
|
31 |
+
const NONCE = 'nonce';
|
32 |
+
const EMAIL = 'email';
|
33 |
+
const CHECKED = 'checked';
|
34 |
+
const DOMAIN = 'ce4wp';
|
35 |
+
const BILLING_EMAIL = 'billing_email';
|
36 |
+
const BILLING_EMAIL_NOTICE = 'billing_email_notice';
|
37 |
+
const BILLING_EMAIL_NO_CONSENT = 'billing_email_no_consent';
|
38 |
+
const CHECKOUT_UUID_PARAM = 'checkout_uuid = %s';
|
39 |
+
const COUPONS = 'coupons';
|
40 |
+
const PRODUCT_ID = 'product_id';
|
41 |
+
const VARIATION_ID = 'variation_id';
|
42 |
+
const QUANTITY = 'quantity';
|
43 |
+
const VARIATION = 'variation';
|
44 |
+
const USER_EMAIL = 'user_email';
|
45 |
+
const PRODUCTS = 'products';
|
46 |
+
const CUSTOMER = 'customer';
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Add hooks
|
50 |
+
*
|
51 |
+
* @since 1.3.0
|
52 |
+
*/
|
53 |
+
public function add_hooks()
|
54 |
+
{
|
55 |
+
// check if woocommerce is active
|
56 |
+
if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
|
57 |
+
add_action('woocommerce_before_checkout_form', array($this, 'enqueue_scripts'));
|
58 |
+
// add checkout notice field
|
59 |
+
add_filter('woocommerce_form_field_ce4wp_notice', array($this, 'add_email_usage_notice_field'), 10, 4);
|
60 |
+
add_filter('woocommerce_checkout_fields', array($this, 'ce4wp_filter_checkout_fields'));
|
61 |
+
|
62 |
+
add_action('woocommerce_after_template_part', array($this, 'save_or_clear_checkout_data'), 10, 1);
|
63 |
+
add_action('woocommerce_add_to_cart', array($this, self::UPDATE_CHECKOUT_DATA));
|
64 |
+
add_action('woocommerce_cart_item_removed', array($this, self::UPDATE_CHECKOUT_DATA), 30, 0);
|
65 |
+
add_action('woocommerce_cart_item_restored', array($this, self::UPDATE_CHECKOUT_DATA), 30, 0);
|
66 |
+
add_action('woocommerce_cart_item_set_quantity', array($this, self::UPDATE_CHECKOUT_DATA), 20, 0);
|
67 |
+
|
68 |
+
add_action('wp_ajax_ce4wp_abandoned_checkouts_capture_guest_checkout', array($this, 'maybe_capture_guest_checkout'));
|
69 |
+
add_action('wp_ajax_nopriv_ce4wp_abandoned_checkouts_capture_guest_checkout', array($this, 'maybe_capture_guest_checkout'));
|
70 |
+
|
71 |
+
add_action('wp_ajax_ce4wp_abandoned_checkouts_no_consent_checkout', array($this, 'no_consent_checkout'));
|
72 |
+
add_action('wp_ajax_nopriv_ce4wp_abandoned_checkouts_no_consent_checkout', array($this, 'no_consent_checkout'));
|
73 |
+
|
74 |
+
add_action('woocommerce_checkout_create_order', array($this, 'clear_purchased_data'), 10, 1);
|
75 |
+
add_action('woocommerce_checkout_order_processed', array($this, 'order_processed'), 10, 1);
|
76 |
+
add_action('woocommerce_order_status_completed', array($this, 'order_completed'), 10, 1);
|
77 |
+
|
78 |
+
// Sanitize checkout UUID.
|
79 |
+
$this->checkout_uuid = filter_input(INPUT_GET, 'ce4wp-recover', FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
|
80 |
+
|
81 |
+
if (empty($this->checkout_uuid)) {
|
82 |
+
return;
|
83 |
+
}
|
84 |
+
|
85 |
+
add_action('wp_loaded', array($this, 'recover_checkout'));
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Add custom field under billing_email
|
91 |
+
*
|
92 |
+
* @since 1.3.0
|
93 |
+
*/
|
94 |
+
public function ce4wp_filter_checkout_fields($fields) {
|
95 |
+
$fields['billing'][self::BILLING_EMAIL_NOTICE] = array(
|
96 |
+
'type' => 'ce4wp_notice',
|
97 |
+
'required' => false,
|
98 |
+
'class' => array( 'form-row-wide' ),
|
99 |
+
'clear' => true,
|
100 |
+
'priority' => $fields['billing']['billing_email']['priority'] + 0.5
|
101 |
+
);
|
102 |
+
return $fields;
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Add logic for ce4wp_notice field type
|
107 |
+
*
|
108 |
+
* @since 1.3.0
|
109 |
+
*/
|
110 |
+
public function add_email_usage_notice_field( $field, $key, $args, $value )
|
111 |
+
{
|
112 |
+
$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>';
|
113 |
+
|
114 |
+
$container_class = esc_attr( implode( ' ', $args['class'] ) );
|
115 |
+
$container_id = esc_attr( $args['id'] ) . '_field';
|
116 |
+
|
117 |
+
$after = ! empty( $args['clear'] ) ? '<div class="clear"></div>' : '';
|
118 |
+
|
119 |
+
$field_container = '<p class="form-row %1$s" id="%2$s">%3$s</p>';
|
120 |
+
|
121 |
+
return sprintf( $field_container, $container_class, $container_id, $field_html ) . $after;
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Order has been completed
|
126 |
+
*
|
127 |
+
* @param int $order_id The order id.
|
128 |
+
*
|
129 |
+
* @since 1.3.0
|
130 |
+
*
|
131 |
+
* @return void
|
132 |
+
*/
|
133 |
+
public function order_completed($order_id)
|
134 |
+
{
|
135 |
+
$this->update_checkout($order_id, '/v1.0/checkout/order_completed');
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Order has been created and is processed
|
140 |
+
*
|
141 |
+
* @param int $order_id Newly created order id.
|
142 |
+
*
|
143 |
+
* @since 1.3.0
|
144 |
+
*
|
145 |
+
* @return void
|
146 |
+
*/
|
147 |
+
public function order_processed( $order_id) {
|
148 |
+
$this->update_checkout($order_id, '/v1.0/checkout/order_created');
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Update of checkout data in the external service
|
153 |
+
*
|
154 |
+
* @param int $order_id Newly created order id.
|
155 |
+
* @param string $endpoint Endpoint to call
|
156 |
+
*
|
157 |
+
* @since 1.3.0
|
158 |
+
*/
|
159 |
+
private function update_checkout($order_id, $endpoint) {
|
160 |
+
$order = wc_get_order($order_id);
|
161 |
+
if ( empty( $order ) ) {
|
162 |
+
return;
|
163 |
+
}
|
164 |
+
// check if order had checkout uuid
|
165 |
+
$uuid = $order->get_meta( self::META_CHECKOUT_UUID);
|
166 |
+
// check if order is created with checkout meta
|
167 |
+
if (empty($uuid)) {
|
168 |
+
return;
|
169 |
+
}
|
170 |
+
// get the recovery date if recovered
|
171 |
+
$recovery_date = $this->get_checkout_recovery_date($uuid);
|
172 |
+
// Remote post to ce4wp marking checkout as completed
|
173 |
+
$requestItem = new stdClass();
|
174 |
+
$requestItem->uuid = $uuid;
|
175 |
+
$requestItem->order_id = $order->get_id();
|
176 |
+
$requestItem->order_total = $order->get_total();
|
177 |
+
$requestItem->order_currency = $order->get_currency();
|
178 |
+
$requestItem->recovery_date = $recovery_date;
|
179 |
+
$endpoint = EnvironmentHelper::get_app_gateway_url('wordpress') . $endpoint;
|
180 |
+
// call remote endpoint to update
|
181 |
+
$this->ce4wp_remote_post($requestItem, $endpoint);
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Enqueue abandoned cart javascript files
|
186 |
+
*
|
187 |
+
* @since 1.3.0
|
188 |
+
*/
|
189 |
+
public function enqueue_scripts() {
|
190 |
+
wp_enqueue_script( 'ce4wp-consent-checkout', CE4WP_PLUGIN_URL . 'assets/js/consent_checkout.js', [ 'wp-util' ], CE4WP_PLUGIN_VERSION, false );
|
191 |
+
|
192 |
+
if ( is_user_logged_in() ) {
|
193 |
+
return;
|
194 |
+
}
|
195 |
+
|
196 |
+
wp_enqueue_script( 'ce4wp-guest-checkout', CE4WP_PLUGIN_URL . 'assets/js/guest_checkout.js', [ 'wp-util' ], CE4WP_PLUGIN_VERSION, false );
|
197 |
+
}
|
198 |
+
|
199 |
+
/**
|
200 |
+
* AJAX handler for attempting to capture guest checkouts.
|
201 |
+
*
|
202 |
+
* @since 1.3.0
|
203 |
+
*/
|
204 |
+
public function maybe_capture_guest_checkout() {
|
205 |
+
$data = filter_input_array( INPUT_POST, [
|
206 |
+
self::NONCE => FILTER_SANITIZE_STRING,
|
207 |
+
self::EMAIL => FILTER_SANITIZE_EMAIL
|
208 |
+
] );
|
209 |
+
|
210 |
+
if ( empty( $data[self::NONCE] ) || ! wp_verify_nonce( $data[self::NONCE], 'woocommerce-process_checkout' ) ) {
|
211 |
+
wp_send_json_error( esc_html__( 'Invalid nonce.', self::DOMAIN ) );
|
212 |
+
}
|
213 |
+
|
214 |
+
$email = filter_var( $data[self::EMAIL], FILTER_VALIDATE_EMAIL );
|
215 |
+
|
216 |
+
if ( ! $email ) {
|
217 |
+
wp_send_json_error( esc_html__( 'Invalid email.', self::DOMAIN ) );
|
218 |
+
}
|
219 |
+
|
220 |
+
WC()->session->set( self::BILLING_EMAIL, $email );
|
221 |
+
$this->save_checkout_data( $email, true);
|
222 |
+
|
223 |
+
wp_send_json_success();
|
224 |
+
}
|
225 |
+
|
226 |
+
/**
|
227 |
+
* AJAX handler for opt out on abandoned cart.
|
228 |
+
*
|
229 |
+
* @since 1.3.0
|
230 |
+
*/
|
231 |
+
public function no_consent_checkout()
|
232 |
+
{
|
233 |
+
$data = filter_input_array(INPUT_POST, [
|
234 |
+
self::NONCE => FILTER_SANITIZE_STRING
|
235 |
+
]);
|
236 |
+
|
237 |
+
if (empty($data[self::NONCE]) || !wp_verify_nonce($data[self::NONCE], 'woocommerce-process_checkout')) {
|
238 |
+
wp_send_json_error(esc_html__('Invalid nonce.', self::DOMAIN));
|
239 |
+
}
|
240 |
+
// save no consent on session
|
241 |
+
WC()->session->set( self::BILLING_EMAIL_NO_CONSENT, true);
|
242 |
+
|
243 |
+
$checkout_id = WC()->session->get( self::CHECKOUT_UUID );
|
244 |
+
if (empty($checkout_id)) {
|
245 |
+
wp_send_json_success();
|
246 |
+
}
|
247 |
+
|
248 |
+
$endpoint = EnvironmentHelper::get_app_gateway_url('wordpress') . '/v1.0/checkout/'. $checkout_id;
|
249 |
+
$this->ce4wp_remote_delete($endpoint);
|
250 |
+
CreativeMail::get_instance()->get_database_manager()->change_checkout_consent($checkout_id, false);
|
251 |
+
|
252 |
+
wp_send_json_success();
|
253 |
+
}
|
254 |
+
|
255 |
+
/**
|
256 |
+
* Either call an update of checkout data which will be saved or remove checkout data based on what template we arrive at.
|
257 |
+
*
|
258 |
+
* @param string $template_name Current template file name.
|
259 |
+
*
|
260 |
+
* @since 1.3.0
|
261 |
+
*/
|
262 |
+
public function save_or_clear_checkout_data( $template_name) {
|
263 |
+
|
264 |
+
// If checkout page displayed, save checkout data.
|
265 |
+
if ( 'checkout/form-checkout.php' === $template_name ) {
|
266 |
+
$this->save_checkout_data();
|
267 |
+
}
|
268 |
+
}
|
269 |
+
|
270 |
+
/**
|
271 |
+
* Helper function to update current checkout session data in db.
|
272 |
+
*
|
273 |
+
* Used to strip unneeded params from callbacks.
|
274 |
+
*
|
275 |
+
* @since 1.3.0
|
276 |
+
*/
|
277 |
+
public function update_checkout_data() {
|
278 |
+
$this->save_checkout_data();
|
279 |
+
}
|
280 |
+
|
281 |
+
/**
|
282 |
+
* Helper function to retrieve checkout contents based on checkout UUID.
|
283 |
+
*
|
284 |
+
* @param string $uuid Checkout UUID.
|
285 |
+
*
|
286 |
+
* @since 1.3.0
|
287 |
+
*
|
288 |
+
* @return array Checkout contents.
|
289 |
+
*/
|
290 |
+
private function get_checkout_contents( $uuid ) {
|
291 |
+
$checkout = CreativeMail::get_instance()->get_database_manager()->get_checkout_data( 'checkout_contents', self::CHECKOUT_UUID_PARAM, [ $uuid ] );
|
292 |
+
|
293 |
+
if ( empty( $checkout ) ) {
|
294 |
+
return [];
|
295 |
+
}
|
296 |
+
|
297 |
+
return maybe_unserialize( array_shift( $checkout )->checkout_contents );
|
298 |
+
}
|
299 |
+
|
300 |
+
/**
|
301 |
+
* Helper function to retrieve checkout recovery date based on checkout UUID.
|
302 |
+
*
|
303 |
+
* @param string $uuid Checkout UUID.
|
304 |
+
*
|
305 |
+
* @since 1.3.0
|
306 |
+
*
|
307 |
+
* @return string|null Checkout recovery date if exists, else null.
|
308 |
+
*/
|
309 |
+
private function get_checkout_recovery_date( $uuid ) {
|
310 |
+
$checkout = CreativeMail::get_instance()->get_database_manager()->get_checkout_data( 'checkout_recovered', self::CHECKOUT_UUID_PARAM, [ $uuid ] );
|
311 |
+
|
312 |
+
return ( empty( $checkout ) ? null : array_shift( $checkout )->checkout_recovered );
|
313 |
+
}
|
314 |
+
|
315 |
+
/**
|
316 |
+
* Helper function to retrieve checkout UUID for current user.
|
317 |
+
*
|
318 |
+
* @since 1.3.0
|
319 |
+
*
|
320 |
+
* @return string Checkout UUID if exists, else empty string.
|
321 |
+
*/
|
322 |
+
private function get_checkout_uuid_by_user() {
|
323 |
+
$checkout = CreativeMail::get_instance()->get_database_manager()->get_checkout_data( self::CHECKOUT_UUID, 'user_id = %d', [ get_current_user_id() ] );
|
324 |
+
|
325 |
+
return ( empty( $checkout ) ? '' : array_shift( $checkout )->checkout_uuid );
|
326 |
+
}
|
327 |
+
|
328 |
+
/**
|
329 |
+
* Save current checkout data to db.
|
330 |
+
*
|
331 |
+
* @param string $billing_email Manually set customer billing email if provided.
|
332 |
+
* @param boolean $is_checkout Manually mark current page as checkout if necessary (e.g., coming from ajax callback).
|
333 |
+
* @param boolean|null $consent_checkout Manually mark consent value.
|
334 |
+
*
|
335 |
+
* @since 1.3.0
|
336 |
+
*
|
337 |
+
* @return void
|
338 |
+
*/
|
339 |
+
protected function save_checkout_data( string $billing_email = '', bool $is_checkout = false) {
|
340 |
+
// Get current user email.
|
341 |
+
$session_customer = WC()->session->get( self::CUSTOMER );
|
342 |
+
$session_billing_email = is_array( $session_customer ) && key_exists( self::EMAIL, $session_customer ) ? $session_customer[self::EMAIL] : '';
|
343 |
+
|
344 |
+
if (empty($billing_email)) {
|
345 |
+
$billing_email = $session_billing_email;
|
346 |
+
if (empty($billing_email)) {
|
347 |
+
$billing_email = WC()->checkout->get_value( self::BILLING_EMAIL );
|
348 |
+
if (empty($billing_email)) {
|
349 |
+
$billing_email = WC()->session->get( self::BILLING_EMAIL );
|
350 |
+
}
|
351 |
+
}
|
352 |
+
}
|
353 |
+
$is_checkout = $is_checkout ?: is_checkout();
|
354 |
+
$uuid = WC()->session->get( self::CHECKOUT_UUID );
|
355 |
+
|
356 |
+
if ( empty( $billing_email ) ) {
|
357 |
+
return;
|
358 |
+
}
|
359 |
+
|
360 |
+
$has_no_consent = WC()->session->get( self::BILLING_EMAIL_NO_CONSENT);
|
361 |
+
if($has_no_consent === true)
|
362 |
+
{
|
363 |
+
return;
|
364 |
+
}
|
365 |
+
|
366 |
+
// Check for existing checkout session.
|
367 |
+
if ( ! $uuid ) {
|
368 |
+
|
369 |
+
// Only create session if cart is not empty.
|
370 |
+
// This is to avoid re-creating checkout UUID during checkout process.
|
371 |
+
if ( $is_checkout && empty( WC()->cart->get_cart() ) ) {
|
372 |
+
return;
|
373 |
+
}
|
374 |
+
|
375 |
+
// Retrieve existing checkout UUID for registered users only.
|
376 |
+
if ( is_user_logged_in() ) {
|
377 |
+
$existing_uuid = $this->get_checkout_uuid_by_user();
|
378 |
+
}
|
379 |
+
|
380 |
+
// Only create session if currently on checkout page or if current user has an existing session saved.
|
381 |
+
if ( ! $is_checkout && empty( $existing_uuid ) ) {
|
382 |
+
return;
|
383 |
+
}
|
384 |
+
|
385 |
+
$uuid = isset( $existing_uuid ) && ! empty( $existing_uuid ) ? $existing_uuid : wp_generate_uuid4();
|
386 |
+
|
387 |
+
WC()->session->set( 'checkout_uuid', $uuid );
|
388 |
+
}
|
389 |
+
|
390 |
+
$current_time = current_time( 'mysql', 1 );
|
391 |
+
$user_id = get_current_user_id();
|
392 |
+
|
393 |
+
$cart_products = WC()->cart->get_cart();
|
394 |
+
$cart_coupons = WC()->cart->get_applied_coupons();
|
395 |
+
|
396 |
+
$checkout_content = [
|
397 |
+
self::PRODUCTS => array_values($cart_products),
|
398 |
+
self::COUPONS => $cart_coupons,
|
399 |
+
];
|
400 |
+
|
401 |
+
CreativeMail::get_instance()->get_database_manager()->upsert_checkout($uuid, $user_id, $billing_email, $checkout_content, $current_time);
|
402 |
+
|
403 |
+
// Remote post to ce4wp create or update cart if email is provided
|
404 |
+
$requestItem = new stdClass();
|
405 |
+
$requestItem->data = wp_json_encode($this->get_cart_data_for_endpoint($cart_products, $cart_coupons));
|
406 |
+
$requestItem->uuid = $uuid;
|
407 |
+
$requestItem->user_id = $user_id;
|
408 |
+
$requestItem->billing_email = $billing_email;
|
409 |
+
$requestItem->timestamp = strtotime($current_time);
|
410 |
+
$endpoint = EnvironmentHelper::get_app_gateway_url('wordpress') . '/v1.0/checkout/upsert';
|
411 |
+
|
412 |
+
$consent = CreativeMail::get_instance()->get_database_manager()->has_checkout_consent($uuid);
|
413 |
+
if ($consent) {
|
414 |
+
$this->ce4wp_remote_post($requestItem, $endpoint);
|
415 |
+
}
|
416 |
+
}
|
417 |
+
|
418 |
+
/**
|
419 |
+
* Get cart object with data for each product and coupon
|
420 |
+
*
|
421 |
+
* @since 1.3.0
|
422 |
+
*/
|
423 |
+
private function get_cart_data_for_endpoint($cart_products, $cart_coupons) {
|
424 |
+
$data = new stdClass();
|
425 |
+
$data->products = array();
|
426 |
+
$data->coupons = array();
|
427 |
+
$data->user = new stdClass();
|
428 |
+
|
429 |
+
try
|
430 |
+
{
|
431 |
+
// Get user first and last name of available
|
432 |
+
$current_user = wp_get_current_user();
|
433 |
+
if ($current_user->exists() ) {
|
434 |
+
$data->user->id = $current_user->ID;
|
435 |
+
$data->user->username = $current_user->user_login;
|
436 |
+
$data->user->display_name = $current_user->display_name;
|
437 |
+
$data->user->first_name = $current_user->user_firstname;
|
438 |
+
$data->user->last_name = $current_user->user_lastname;
|
439 |
+
$data->user->email = $current_user->user_email;
|
440 |
+
}
|
441 |
+
|
442 |
+
$dp = 2; // decimal point
|
443 |
+
|
444 |
+
foreach ($cart_products as $value)
|
445 |
+
{
|
446 |
+
$product = array_key_exists('data', $value) ? $value['data'] : wc_get_product($value[self::PRODUCT_ID]);
|
447 |
+
$product_id = $product->get_id();
|
448 |
+
$product_data = array(
|
449 |
+
'images' => array()
|
450 |
+
);
|
451 |
+
$attachment_ids = $product->get_gallery_image_ids();
|
452 |
+
foreach ($attachment_ids as $attachment_id) {
|
453 |
+
$product_data['images'][] = wp_get_attachment_url($attachment_id);
|
454 |
+
}
|
455 |
+
|
456 |
+
$product_data["on_sale"] = $product->is_on_sale();
|
457 |
+
$product_data["sale_price"] = $product->get_sale_price();
|
458 |
+
$product_data["regular_price"] = $product->get_regular_price();
|
459 |
+
$src = wc_placeholder_img_src();
|
460 |
+
if ($image_id = $product->get_image_id()) {
|
461 |
+
list($src) = wp_get_attachment_image_src($image_id, 'full');
|
462 |
+
}
|
463 |
+
|
464 |
+
$line_subtotal = empty($value['line_subtotal']) ? 0: $value['line_subtotal'];
|
465 |
+
$line_subtotal_tax =empty($value['line_subtotal_tax']) ? 0: $value['line_subtotal_tax'];
|
466 |
+
$line_total = empty($value['line_total']) ? 0: $value['line_total'];
|
467 |
+
$line_tax = empty($value['line_tax']) ? 0: $value['line_tax'];
|
468 |
+
|
469 |
+
$data->products[] = array(
|
470 |
+
'name' => $product->get_name(),
|
471 |
+
'product_id' => $product_id,
|
472 |
+
'product_image' => $src,
|
473 |
+
'product_data' => $product_data,
|
474 |
+
'sku' => is_object($product) ? $product->get_sku() : null,
|
475 |
+
'product_url' => get_the_permalink($product_id),
|
476 |
+
'variation_id' => $value[self::VARIATION_ID],
|
477 |
+
'subtotal' => wc_format_decimal($line_subtotal, $dp),
|
478 |
+
'subtotal_tax' => wc_format_decimal($line_subtotal_tax, $dp),
|
479 |
+
'total' => wc_format_decimal($line_total, $dp),
|
480 |
+
'total_tax' => wc_format_decimal($line_tax, $dp),
|
481 |
+
'price' => wc_format_decimal($line_subtotal, $dp),
|
482 |
+
'quantity' => $value[self::QUANTITY]
|
483 |
+
);
|
484 |
+
}
|
485 |
+
|
486 |
+
foreach ($cart_coupons as $coupon_code)
|
487 |
+
{
|
488 |
+
$coupon_id = wc_get_coupon_id_by_code($coupon_code);
|
489 |
+
if ($coupon_id)
|
490 |
+
{
|
491 |
+
$coupon = new WC_Coupon($coupon_id);
|
492 |
+
|
493 |
+
$data->coupons[] = array(
|
494 |
+
'code' => $coupon->get_code(),
|
495 |
+
'amount' => $coupon->get_amount(),
|
496 |
+
'discount_type' => $coupon->get_discount_type(),
|
497 |
+
'description' => $coupon->get_description(),
|
498 |
+
'free_shipping' => $coupon->get_free_shipping()
|
499 |
+
);
|
500 |
+
}
|
501 |
+
}
|
502 |
+
}
|
503 |
+
catch (\Exception $e)
|
504 |
+
{
|
505 |
+
// silent
|
506 |
+
}
|
507 |
+
|
508 |
+
return $data;
|
509 |
+
}
|
510 |
+
|
511 |
+
/**
|
512 |
+
* Remove current checkout session data from db upon successful order submission.
|
513 |
+
*
|
514 |
+
* @param WC_Order $order Newly created order object.
|
515 |
+
*
|
516 |
+
* @since 1.3.0
|
517 |
+
*
|
518 |
+
* @return void
|
519 |
+
*/
|
520 |
+
public function clear_purchased_data( $order) {
|
521 |
+
$checkout_id = WC()->session->get( self::CHECKOUT_UUID );
|
522 |
+
if (empty($checkout_id)) {
|
523 |
+
return;
|
524 |
+
}
|
525 |
+
|
526 |
+
$order->update_meta_data( self::META_CHECKOUT_UUID, $checkout_id );
|
527 |
+
CreativeMail::get_instance()->get_database_manager()->remove_checkout_data($checkout_id);
|
528 |
+
WC()->session->__unset( self::CHECKOUT_UUID );
|
529 |
+
}
|
530 |
+
|
531 |
+
/**
|
532 |
+
* Recovery saved checkout from UUID.
|
533 |
+
*
|
534 |
+
* @since 1.3.0
|
535 |
+
*
|
536 |
+
* @return void
|
537 |
+
*/
|
538 |
+
public function recover_checkout() {
|
539 |
+
|
540 |
+
// Set checkout session UUID.
|
541 |
+
WC()->session->set( self::CHECKOUT_UUID, $this->checkout_uuid );
|
542 |
+
|
543 |
+
// Clear current checkout contents.
|
544 |
+
WC()->cart->empty_cart();
|
545 |
+
|
546 |
+
// Get saved checkout contents.
|
547 |
+
$checkout_contents = $this->get_checkout_contents( $this->checkout_uuid );
|
548 |
+
|
549 |
+
if ( empty($checkout_contents) ) {
|
550 |
+
return;
|
551 |
+
}
|
552 |
+
|
553 |
+
// Mark checkout as recovered
|
554 |
+
CreativeMail::get_instance()->get_database_manager()->mark_checkout_recovered($this->checkout_uuid);
|
555 |
+
|
556 |
+
// Recover saved products.
|
557 |
+
$this->recover_products( $checkout_contents[self::PRODUCTS] );
|
558 |
+
|
559 |
+
// Apply coupons.
|
560 |
+
foreach ( $checkout_contents[self::COUPONS] as $coupon ) {
|
561 |
+
WC()->cart->apply_coupon( $coupon );
|
562 |
+
}
|
563 |
+
|
564 |
+
// Maybe recover checkout email.
|
565 |
+
$this->maybe_recover_checkout_email();
|
566 |
+
|
567 |
+
// Update totals.
|
568 |
+
WC()->cart->calculate_totals();
|
569 |
+
|
570 |
+
// Redirect to checkout page.
|
571 |
+
wp_safe_redirect( wc_get_page_permalink( 'cart' ) );
|
572 |
+
|
573 |
+
exit();
|
574 |
+
}
|
575 |
+
|
576 |
+
|
577 |
+
/**
|
578 |
+
* Recover checkout email address if guest user and no email is set.
|
579 |
+
*
|
580 |
+
* @since 1.3.0
|
581 |
+
*
|
582 |
+
* @return void
|
583 |
+
*/
|
584 |
+
protected function maybe_recover_checkout_email() : void {
|
585 |
+
$checkout_email = CreativeMail::get_instance()->get_database_manager()->get_checkout_data( self::USER_EMAIL, self::CHECKOUT_UUID_PARAM, [ $this->checkout_uuid ] );
|
586 |
+
$checkout_email = empty( $checkout_email ) ? '' : array_shift( $checkout_email )->user_email;
|
587 |
+
|
588 |
+
if ( is_user_logged_in() || ! empty( WC()->session->get( self::BILLING_EMAIL ) ) || empty( $checkout_email ) ) {
|
589 |
+
return;
|
590 |
+
}
|
591 |
+
|
592 |
+
WC()->session->set( self::BILLING_EMAIL, $checkout_email );
|
593 |
+
WC()->customer->set_billing_email( $checkout_email );
|
594 |
+
}
|
595 |
+
|
596 |
+
/**
|
597 |
+
* Recover products from saved checkout data.
|
598 |
+
*
|
599 |
+
* @param array $products Array of product data.
|
600 |
+
*
|
601 |
+
* @since 1.3.0
|
602 |
+
*/
|
603 |
+
protected function recover_products( $products ) {
|
604 |
+
if (empty($products)) {
|
605 |
+
return;
|
606 |
+
}
|
607 |
+
// Programmatically add each product to cart.
|
608 |
+
$products_added = [];
|
609 |
+
foreach ( $products as $product ) {
|
610 |
+
$added = WC()->cart->add_to_cart(
|
611 |
+
$product[self::PRODUCT_ID],
|
612 |
+
$product[self::QUANTITY],
|
613 |
+
empty( $product[self::VARIATION_ID] ) ? 0 : $product[self::VARIATION_ID],
|
614 |
+
empty( $product[self::VARIATION] ) ? array() : $product[self::VARIATION]
|
615 |
+
);
|
616 |
+
if ( false !== $added ) {
|
617 |
+
$products_added[ ( empty( $product[self::VARIATION_ID] ) ? $product[self::PRODUCT_ID] : $product[self::VARIATION_ID] ) ] = $product[self::QUANTITY];
|
618 |
+
}
|
619 |
+
}
|
620 |
+
|
621 |
+
// Add product notices.
|
622 |
+
if ( 0 < count( $products_added ) ) {
|
623 |
+
wc_add_to_cart_message( $products_added );
|
624 |
+
}
|
625 |
+
if ( count( $products ) > count( $products_added ) ) {
|
626 |
+
wc_add_notice(
|
627 |
+
sprintf(
|
628 |
+
/* translators: %d item count */
|
629 |
+
_n(
|
630 |
+
'%d item from your previous order is currently unavailable and could not be added to your cart.',
|
631 |
+
'%d items from your previous order are currently unavailable and could not be added to your cart.',
|
632 |
+
( count( $products ) - count( $products_added ) ),
|
633 |
+
self::DOMAIN
|
634 |
+
),
|
635 |
+
( count( $products ) - count( $products_added ) )
|
636 |
+
),
|
637 |
+
'error'
|
638 |
+
);
|
639 |
+
}
|
640 |
+
}
|
641 |
+
|
642 |
+
private function ce4wp_remote_post($requestItem, $endpoint) {
|
643 |
+
try
|
644 |
+
{
|
645 |
+
// check if abandoned cart email is managed by creative mail
|
646 |
+
$enabled = CreativeMail::get_instance()->get_email_manager()->is_email_managed('cart_abandoned_ce4wp');
|
647 |
+
if($enabled) {
|
648 |
+
wp_remote_post(
|
649 |
+
$endpoint, array(
|
650 |
+
'method' => 'POST',
|
651 |
+
'timeout' => 10,
|
652 |
+
'headers' => array(
|
653 |
+
'x-account-id' => OptionsHelper::get_connected_account_id(),
|
654 |
+
'x-api-key' => OptionsHelper::get_instance_api_key(),
|
655 |
+
'content-type' => 'application/json'
|
656 |
+
),
|
657 |
+
'body' => wp_json_encode($requestItem)
|
658 |
+
)
|
659 |
+
);
|
660 |
+
}
|
661 |
+
} catch (\Exception $e) {
|
662 |
+
// silent
|
663 |
+
}
|
664 |
+
}
|
665 |
+
|
666 |
+
private function ce4wp_remote_delete($endpoint) {
|
667 |
+
try {
|
668 |
+
wp_remote_request($endpoint,
|
669 |
+
array(
|
670 |
+
'method' => 'DELETE',
|
671 |
+
'headers' => array(
|
672 |
+
'x-account-id' => OptionsHelper::get_connected_account_id(),
|
673 |
+
'x-api-key' => OptionsHelper::get_instance_api_key()
|
674 |
+
)
|
675 |
+
)
|
676 |
+
);
|
677 |
+
} catch (\Exception $e) {
|
678 |
+
// silent
|
679 |
+
}
|
680 |
+
}
|
681 |
+
}
|
src/managers/DatabaseManager.php
ADDED
@@ -0,0 +1,275 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
|
4 |
+
namespace CreativeMail\Managers;
|
5 |
+
|
6 |
+
use DateInterval;
|
7 |
+
use DateTime;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Class DatabaseManager
|
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 DB_VERSION = '1.0';
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Option name for abandoned checkouts db version.
|
25 |
+
*
|
26 |
+
* @since 1.3.0
|
27 |
+
*/
|
28 |
+
const DB_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 TABLE_NAME = 'ce4wp_abandoned_checkout';
|
38 |
+
|
39 |
+
public function add_hooks()
|
40 |
+
{
|
41 |
+
// check if woocommerce is active
|
42 |
+
if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
|
43 |
+
add_action('admin_init', array($this, 'update_database_check'), 10, 2);
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Check if table exists and is up-to-date.
|
49 |
+
*
|
50 |
+
* @since 1.3.0
|
51 |
+
*/
|
52 |
+
public function update_database_check() {
|
53 |
+
if ( ! get_site_option( self::DB_VERSION_OPTION_NAME ) ) {
|
54 |
+
// Fresh install: create table.
|
55 |
+
$this->create_table();
|
56 |
+
} else if(current_user_can('administrator')){
|
57 |
+
// Cleanup old expired checkouts
|
58 |
+
$this->delete_expired_checkouts();
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Helper function to remove checkout session data from db.
|
64 |
+
*
|
65 |
+
* @since 1.3.0
|
66 |
+
*/
|
67 |
+
public function remove_checkout_data($checkout_uuid) {
|
68 |
+
global $wpdb;
|
69 |
+
|
70 |
+
// Delete current checkout data.
|
71 |
+
$wpdb->delete(
|
72 |
+
DatabaseManager::get_table_name(),
|
73 |
+
[
|
74 |
+
self::CHECKOUT_UUID => $checkout_uuid,
|
75 |
+
],
|
76 |
+
[
|
77 |
+
'%s',
|
78 |
+
]
|
79 |
+
);
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Create abandoned checkouts table.
|
84 |
+
*
|
85 |
+
* @since 1.3.0
|
86 |
+
*/
|
87 |
+
public function create_table() {
|
88 |
+
global $wpdb;
|
89 |
+
|
90 |
+
$table_name = self::get_table_name();
|
91 |
+
|
92 |
+
$sql = "CREATE TABLE {$table_name} (
|
93 |
+
checkout_id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
94 |
+
user_id bigint(20) unsigned NOT NULL DEFAULT 0,
|
95 |
+
user_email varchar(200) NOT NULL DEFAULT '',
|
96 |
+
checkout_contents longtext NOT NULL,
|
97 |
+
checkout_updated datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
98 |
+
checkout_updated_ts int(11) unsigned NOT NULL DEFAULT 0,
|
99 |
+
checkout_created datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
100 |
+
checkout_created_ts int(11) unsigned NOT NULL DEFAULT 0,
|
101 |
+
checkout_recovered datetime NULL DEFAULT '0000-00-00 00:00:00',
|
102 |
+
checkout_recovered_ts int(11) unsigned NULL DEFAULT 0,
|
103 |
+
checkout_consent int(11) unsigned NOT NULL DEFAULT 1,
|
104 |
+
checkout_uuid varchar(36) NOT NULL DEFAULT '',
|
105 |
+
PRIMARY KEY (checkout_id),
|
106 |
+
UNIQUE KEY checkout_uuid (checkout_uuid)
|
107 |
+
) {$wpdb->get_charset_collate()}";
|
108 |
+
|
109 |
+
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
110 |
+
dbDelta( $sql );
|
111 |
+
|
112 |
+
add_option( self::DB_VERSION_OPTION_NAME, self::DB_VERSION );
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Delete expired checkouts.
|
117 |
+
*
|
118 |
+
* @since 1.3.0
|
119 |
+
*/
|
120 |
+
public function delete_expired_checkouts() {
|
121 |
+
global $wpdb;
|
122 |
+
|
123 |
+
// Delete all checkouts at least 30 days old.
|
124 |
+
$table_name = $this->get_table_name();
|
125 |
+
|
126 |
+
$wpdb->query(
|
127 |
+
$wpdb->prepare(
|
128 |
+
// phpcs:disable WordPress.DB.PreparedSQL -- Okay use of unprepared variable for table name in SQL.
|
129 |
+
"DELETE FROM {$table_name}
|
130 |
+
WHERE `checkout_updated_ts` <= %s",
|
131 |
+
// phpcs:enable
|
132 |
+
( new DateTime() )->sub( new DateInterval( 'P30D' ) )->format( 'U' )
|
133 |
+
)
|
134 |
+
);
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Upsert the checkout content
|
139 |
+
*
|
140 |
+
* @since 1.3.0
|
141 |
+
*/
|
142 |
+
public function upsert_checkout($checkout_uuid, $user_id, $billing_email, $content, $current_time) {
|
143 |
+
global $wpdb;
|
144 |
+
|
145 |
+
$table_name = $this->get_table_name();
|
146 |
+
|
147 |
+
// phpcs:disable WordPress.DB.PreparedSQL -- Okay use of unprepared variable for table name in SQL.
|
148 |
+
$wpdb->query(
|
149 |
+
$wpdb->prepare(
|
150 |
+
"INSERT INTO {$table_name} (
|
151 |
+
`user_id`,
|
152 |
+
`user_email`,
|
153 |
+
`checkout_contents`,
|
154 |
+
`checkout_updated`,
|
155 |
+
`checkout_updated_ts`,
|
156 |
+
`checkout_created`,
|
157 |
+
`checkout_created_ts`,
|
158 |
+
`checkout_uuid`
|
159 |
+
) VALUES (
|
160 |
+
%d,
|
161 |
+
%s,
|
162 |
+
%s,
|
163 |
+
%s,
|
164 |
+
%d,
|
165 |
+
%s,
|
166 |
+
%d,
|
167 |
+
%s
|
168 |
+
) 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`)",
|
169 |
+
$user_id,
|
170 |
+
$billing_email,
|
171 |
+
maybe_serialize($content),
|
172 |
+
$current_time,
|
173 |
+
strtotime( $current_time ),
|
174 |
+
$current_time,
|
175 |
+
strtotime( $current_time ),
|
176 |
+
$checkout_uuid
|
177 |
+
)
|
178 |
+
);
|
179 |
+
// phpcs:enable
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Update the database record with current time for recovery
|
184 |
+
*
|
185 |
+
* @since 1.3.0
|
186 |
+
*/
|
187 |
+
public function mark_checkout_recovered($checkout_uuid) {
|
188 |
+
global $wpdb;
|
189 |
+
|
190 |
+
$table_name = $this->get_table_name();
|
191 |
+
|
192 |
+
$current_time = current_time( 'mysql', 1 );
|
193 |
+
|
194 |
+
$wpdb->update($table_name, array(
|
195 |
+
'checkout_recovered' => $current_time,
|
196 |
+
'checkout_recovered_ts' => strtotime( $current_time )
|
197 |
+
), array(self::CHECKOUT_UUID => $checkout_uuid));
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Update the database record with current consent
|
202 |
+
*
|
203 |
+
* @since 1.3.0
|
204 |
+
*/
|
205 |
+
public function change_checkout_consent($checkout_uuid, $consent) {
|
206 |
+
global $wpdb;
|
207 |
+
|
208 |
+
$table_name = $this->get_table_name();
|
209 |
+
|
210 |
+
$int_consent = $consent ? 1 : 0;
|
211 |
+
|
212 |
+
$wpdb->update($table_name, array(
|
213 |
+
'checkout_consent' => $int_consent
|
214 |
+
), array(self::CHECKOUT_UUID => $checkout_uuid));
|
215 |
+
}
|
216 |
+
|
217 |
+
public function has_checkout_consent($checkout_uuid) {
|
218 |
+
global $wpdb;
|
219 |
+
|
220 |
+
$table_name = $this->get_table_name();
|
221 |
+
|
222 |
+
$consent_value = $wpdb->get_var($wpdb->prepare("SELECT `checkout_consent` FROM $table_name WHERE `checkout_uuid` = %s", $checkout_uuid));
|
223 |
+
return $consent_value === "1";
|
224 |
+
}
|
225 |
+
|
226 |
+
/**
|
227 |
+
* Retrieve specific user's checkout data.
|
228 |
+
*
|
229 |
+
* @param string $select Field to return.
|
230 |
+
* @param mixed $where String or array of WHERE clause predicates, using placeholders for values.
|
231 |
+
* @param array $where_args Array of WHERE clause arguments.
|
232 |
+
* @param string $order_by Order by column.
|
233 |
+
* @param string $order Order (ASC/DESC).
|
234 |
+
* @param string $limit LIMIT clause.
|
235 |
+
* @param array $limit_args Array of LIMIT clause arguments.
|
236 |
+
*
|
237 |
+
* @since 1.3.0
|
238 |
+
*
|
239 |
+
* @return mixed Checkout data if exists, else null.
|
240 |
+
*/
|
241 |
+
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 = [] ) {
|
242 |
+
global $wpdb;
|
243 |
+
|
244 |
+
$table_name = $this->get_table_name();
|
245 |
+
$where = is_array( $where ) ? implode( ' AND ', $where ) : $where;
|
246 |
+
$where = empty( $where ) ? 1 : $where;
|
247 |
+
|
248 |
+
// Construct query to return checkout data.
|
249 |
+
// phpcs:disable -- Disabling a number of sniffs that erroneously flag following block of code.
|
250 |
+
// $where often includes placeholders for replacement via $wpdb->prepare(). $where_values provides those values.
|
251 |
+
return $wpdb->get_results(
|
252 |
+
$wpdb->prepare(
|
253 |
+
"SELECT {$select}
|
254 |
+
FROM {$table_name}
|
255 |
+
WHERE {$where}
|
256 |
+
ORDER BY {$order_by} {$order}
|
257 |
+
{$limit}",
|
258 |
+
array_merge( $where_args, $limit_args )
|
259 |
+
)
|
260 |
+
);
|
261 |
+
// phpcs:enable
|
262 |
+
}
|
263 |
+
|
264 |
+
/**
|
265 |
+
* A simple utility for grabbing the full table name, including the WPDB table prefix.
|
266 |
+
*
|
267 |
+
* @since 1.3.0
|
268 |
+
*
|
269 |
+
* @return string
|
270 |
+
*/
|
271 |
+
public static function get_table_name() : string {
|
272 |
+
global $wpdb;
|
273 |
+
return $wpdb->prefix . self::TABLE_NAME;
|
274 |
+
}
|
275 |
+
}
|
src/managers/EmailManager.php
CHANGED
@@ -31,12 +31,16 @@ class EmailManager
|
|
31 |
'customer_new_account',
|
32 |
'customer_reset_password',
|
33 |
'customer_invoice',
|
34 |
-
'customer_note'
|
|
|
35 |
];
|
36 |
|
|
|
|
|
|
|
37 |
public function __construct()
|
38 |
{
|
39 |
-
|
40 |
}
|
41 |
|
42 |
public function add_hooks()
|
@@ -79,19 +83,19 @@ class EmailManager
|
|
79 |
|
80 |
public function ce_checkout_order_meta( $order_id )
|
81 |
{
|
82 |
-
if ($_POST[
|
83 |
-
$checkbox_value = esc_attr($_POST[
|
84 |
-
update_post_meta($order_id,
|
85 |
}
|
86 |
}
|
87 |
|
88 |
public function add_checkout_field( $checkout)
|
89 |
{
|
90 |
-
$checked = $checkout->get_value(
|
91 |
$checkbox_text = stripslashes(OptionsHelper::get_checkout_checkbox_text());
|
92 |
|
93 |
woocommerce_form_field(
|
94 |
-
|
95 |
'type' => 'checkbox',
|
96 |
'class' => array('ce-field form-row-wide'),
|
97 |
'label' => $checkbox_text,
|
@@ -141,12 +145,12 @@ class EmailManager
|
|
141 |
public function print_ce_manage_button($options)
|
142 |
{
|
143 |
?><tr valign="top">
|
144 |
-
<th scope="row" class="titledesc"
|
145 |
<td class="forminp forminp-<?php echo sanitize_title($options['type']); ?>">
|
146 |
<a href="admin.php?page=creativemail">
|
147 |
-
<button type="button" class="button button-secondary" value="<?php _e('Manage', 'ce4wp'); ?>"
|
148 |
</a>
|
149 |
-
<p class="description"
|
150 |
</td>
|
151 |
</tr><?php
|
152 |
}
|
@@ -587,9 +591,6 @@ class EmailManager
|
|
587 |
*/
|
588 |
public function manage_emails()
|
589 |
{
|
590 |
-
|
591 |
-
$this->managed_email_notifications = $this->get_managed_email_notifications();
|
592 |
-
|
593 |
if (empty($this->managed_email_notifications) || ! is_array($this->managed_email_notifications) ) {
|
594 |
return;
|
595 |
}
|
@@ -692,7 +693,6 @@ class EmailManager
|
|
692 |
*/
|
693 |
public function get_managed_notification_param( $email_id, $param )
|
694 |
{
|
695 |
-
|
696 |
foreach($this->managed_email_notifications as $managed_email_notification) {
|
697 |
if ($email_id == $managed_email_notification->name && property_exists($managed_email_notification, $param)) {
|
698 |
return $managed_email_notification->$param;
|
31 |
'customer_new_account',
|
32 |
'customer_reset_password',
|
33 |
'customer_invoice',
|
34 |
+
'customer_note',
|
35 |
+
'cart_abandoned_ce4wp'
|
36 |
];
|
37 |
|
38 |
+
const CHECKOUT_CONSENT_CHECKBOX_ID = 'ce4wp_checkout_consent_checkbox';
|
39 |
+
const CHECKOUT_CONSENT_CHECKBOX_VALUE = 'ce4wp_checkout_consent';
|
40 |
+
|
41 |
public function __construct()
|
42 |
{
|
43 |
+
$this->managed_email_notifications = $this->get_managed_email_notifications();
|
44 |
}
|
45 |
|
46 |
public function add_hooks()
|
83 |
|
84 |
public function ce_checkout_order_meta( $order_id )
|
85 |
{
|
86 |
+
if ($_POST[self::CHECKOUT_CONSENT_CHECKBOX_ID]) {
|
87 |
+
$checkbox_value = esc_attr($_POST[self::CHECKOUT_CONSENT_CHECKBOX_ID]);
|
88 |
+
update_post_meta($order_id, self::CHECKOUT_CONSENT_CHECKBOX_VALUE, $checkbox_value);
|
89 |
}
|
90 |
}
|
91 |
|
92 |
public function add_checkout_field( $checkout)
|
93 |
{
|
94 |
+
$checked = $checkout->get_value(self::CHECKOUT_CONSENT_CHECKBOX_ID) ? $checkout->get_value(self::CHECKOUT_CONSENT_CHECKBOX_ID) : 0;
|
95 |
$checkbox_text = stripslashes(OptionsHelper::get_checkout_checkbox_text());
|
96 |
|
97 |
woocommerce_form_field(
|
98 |
+
self::CHECKOUT_CONSENT_CHECKBOX_ID, array(
|
99 |
'type' => 'checkbox',
|
100 |
'class' => array('ce-field form-row-wide'),
|
101 |
'label' => $checkbox_text,
|
145 |
public function print_ce_manage_button($options)
|
146 |
{
|
147 |
?><tr valign="top">
|
148 |
+
<th scope="row" class="titledesc"><?php _e('Customize Emails', 'ce4wp'); ?></th>
|
149 |
<td class="forminp forminp-<?php echo sanitize_title($options['type']); ?>">
|
150 |
<a href="admin.php?page=creativemail">
|
151 |
+
<button type="button" class="button button-secondary" value="<?php _e('Manage', 'ce4wp'); ?>"><?php _e('Manage', 'ce4wp'); ?></button>
|
152 |
</a>
|
153 |
+
<p class="description"><?php _e('Manage all your email settings and templates with Creative Mail', 'ce4wp'); ?></p>
|
154 |
</td>
|
155 |
</tr><?php
|
156 |
}
|
591 |
*/
|
592 |
public function manage_emails()
|
593 |
{
|
|
|
|
|
|
|
594 |
if (empty($this->managed_email_notifications) || ! is_array($this->managed_email_notifications) ) {
|
595 |
return;
|
596 |
}
|
693 |
*/
|
694 |
public function get_managed_notification_param( $email_id, $param )
|
695 |
{
|
|
|
696 |
foreach($this->managed_email_notifications as $managed_email_notification) {
|
697 |
if ($email_id == $managed_email_notification->name && property_exists($managed_email_notification, $param)) {
|
698 |
return $managed_email_notification->$param;
|
src/modules/DashboardWidgetModule.php
CHANGED
@@ -80,15 +80,26 @@ class DashboardWidgetModule
|
|
80 |
|
81 |
private function show_woo_commerce()
|
82 |
{
|
83 |
-
$
|
84 |
-
$number_of_active_notifications =
|
85 |
-
|
86 |
-
|
87 |
-
$
|
88 |
-
|
89 |
-
|
90 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
}
|
|
|
92 |
}
|
93 |
|
94 |
private function show_exception()
|
80 |
|
81 |
private function show_woo_commerce()
|
82 |
{
|
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 $email_notification->active === true;
|
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 |
}
|
102 |
+
catch(\Exception $ex) { }
|
103 |
}
|
104 |
|
105 |
private function show_exception()
|
src/modules/contacts/Handlers/NinjaFormsPluginHandler.php
CHANGED
@@ -48,9 +48,13 @@ class NinjaFormsPluginHandler extends BaseContactFormPluginHandler
|
|
48 |
|
49 |
$contactModel->setEventType(CE4WP_NF_EVENTTYPE);
|
50 |
|
51 |
-
$contactModel->setOptIn(
|
52 |
$contactModel->setOptOut(false);
|
53 |
-
$contactModel->setOptActionBy(OptActionBy::
|
|
|
|
|
|
|
|
|
54 |
|
55 |
$email = $contact->email;
|
56 |
if (!empty($email)) {
|
@@ -58,7 +62,7 @@ class NinjaFormsPluginHandler extends BaseContactFormPluginHandler
|
|
58 |
$contactModel->setEmail($email);
|
59 |
}
|
60 |
|
61 |
-
$name = $contact->name;
|
62 |
$firstName = null;
|
63 |
$lastName = null;
|
64 |
if (!empty($name)){
|
@@ -80,6 +84,23 @@ class NinjaFormsPluginHandler extends BaseContactFormPluginHandler
|
|
80 |
return $contactModel;
|
81 |
}
|
82 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
public function ceHandleNinjaFormSubmission($form_data)
|
84 |
{
|
85 |
try {
|
@@ -136,39 +157,43 @@ class NinjaFormsPluginHandler extends BaseContactFormPluginHandler
|
|
136 |
foreach ($fields as $field) {
|
137 |
// Get field settings so we can map the values with it's field type
|
138 |
$field_settings = $field->get_settings();
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
|
|
|
|
|
|
|
|
143 |
$contact->email = $email;
|
144 |
}
|
145 |
break;
|
146 |
-
case 'name'
|
147 |
-
|
|
|
148 |
break;
|
149 |
-
case 'firstname'
|
150 |
-
|
|
|
151 |
break;
|
152 |
-
case 'lastname'
|
153 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
break;
|
155 |
-
}
|
156 |
-
if ($this->isNullOrEmpty($contact->name) && $this->isNullOrEmpty($contact->firstName)){
|
157 |
-
//Attempt additional checking for name in an attempt to get custom form fields for names
|
158 |
-
$name = null;
|
159 |
-
|
160 |
-
if (strpos($field_settings["key"], "full_name") !== false) {
|
161 |
-
$contact->name = $field["value"];
|
162 |
-
}
|
163 |
-
if (strpos($field_settings["key"], "first_name") !== false) {
|
164 |
-
$contact->firstName = $field["value"];
|
165 |
-
}
|
166 |
-
if (strpos($field_settings["key"], "last_name") !== false) {
|
167 |
-
$contact->lastname = $field["value"];
|
168 |
-
}
|
169 |
}
|
170 |
}
|
171 |
-
|
|
|
|
|
|
|
172 |
//Convert to contactModel and push to the array
|
173 |
$contactModel = $this->convertToContactModel($contact);
|
174 |
array_push($contactsArray, $contactModel);
|
48 |
|
49 |
$contactModel->setEventType(CE4WP_NF_EVENTTYPE);
|
50 |
|
51 |
+
$contactModel->setOptIn(false);
|
52 |
$contactModel->setOptOut(false);
|
53 |
+
$contactModel->setOptActionBy(OptActionBy::Owner);
|
54 |
+
|
55 |
+
if(isset($contact->optinByOwner)){
|
56 |
+
$contactModel->setOptIn(boolval($contact->optinByOwner));
|
57 |
+
}
|
58 |
|
59 |
$email = $contact->email;
|
60 |
if (!empty($email)) {
|
62 |
$contactModel->setEmail($email);
|
63 |
}
|
64 |
|
65 |
+
$name = !empty($contact->name) ? $contact->name : null;
|
66 |
$firstName = null;
|
67 |
$lastName = null;
|
68 |
if (!empty($name)){
|
84 |
return $contactModel;
|
85 |
}
|
86 |
|
87 |
+
public function attemptAdditionalNameExtraction($contact, $field_key, $field_values){
|
88 |
+
//Attempt additional checking for name in an attempt to get custom form fields for names
|
89 |
+
$name = null;
|
90 |
+
if (strpos($field_key, "full_name") !== false || isset($field_values["name"])) {
|
91 |
+
$contact->name = $field_values[$field_key];
|
92 |
+
return;
|
93 |
+
}
|
94 |
+
if (strpos($field_key, "first_name") !== false || isset($field_values["firstname"])) {
|
95 |
+
$contact->firstName = $field_values[$field_key];
|
96 |
+
return;
|
97 |
+
}
|
98 |
+
if (strpos($field_key, "last_name") !== false || isset($field_values["lastname"])) {
|
99 |
+
$contact->lastname = $field_values[$field_key];
|
100 |
+
return;
|
101 |
+
}
|
102 |
+
}
|
103 |
+
|
104 |
public function ceHandleNinjaFormSubmission($form_data)
|
105 |
{
|
106 |
try {
|
157 |
foreach ($fields as $field) {
|
158 |
// Get field settings so we can map the values with it's field type
|
159 |
$field_settings = $field->get_settings();
|
160 |
+
$field_key = $field_settings["key"];
|
161 |
+
$field_type = $field_settings["type"];
|
162 |
+
|
163 |
+
switch($field_type)
|
164 |
+
{
|
165 |
+
case 'email';
|
166 |
+
$email = isset($field_values[$field_key]) ? $field_values[$field_key] : null;
|
167 |
+
if (filter_var($email, FILTER_VALIDATE_EMAIL)){
|
168 |
$contact->email = $email;
|
169 |
}
|
170 |
break;
|
171 |
+
case 'name';
|
172 |
+
case 'full_name';
|
173 |
+
$contact->name = $field_values[$field_key];
|
174 |
break;
|
175 |
+
case 'firstname';
|
176 |
+
case 'first_name';
|
177 |
+
$contact->firstName = $field_values[$field_key];
|
178 |
break;
|
179 |
+
case 'lastname';
|
180 |
+
case 'last_name';
|
181 |
+
$contact->lastname = $field_values[$field_key];
|
182 |
+
break;
|
183 |
+
case 'textbox';
|
184 |
+
case 'text';
|
185 |
+
if (empty($contact->name) && (empty($contact->firstName) || empty($contact->lastName))){
|
186 |
+
$this->attemptAdditionalNameExtraction($contact, $field_key, $field_values);
|
187 |
+
}
|
188 |
+
break;
|
189 |
+
default;
|
190 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
}
|
192 |
}
|
193 |
+
|
194 |
+
if (!empty($contact->email) && $contact->email != null) {
|
195 |
+
//set optin by owner on db sync
|
196 |
+
$contact->optinByOwner = true;
|
197 |
//Convert to contactModel and push to the array
|
198 |
$contactModel = $this->convertToContactModel($contact);
|
199 |
array_push($contactsArray, $contactModel);
|
src/modules/contacts/Handlers/WooCommercePluginHandler.php
CHANGED
@@ -10,10 +10,15 @@ namespace CreativeMail\Modules\Contacts\Handlers;
|
|
10 |
|
11 |
define('CE4WP_WC_EVENTTYPE', 'WordPress - WooCommerce');
|
12 |
|
|
|
13 |
use CreativeMail\Modules\Contacts\Models\ContactModel;
|
14 |
|
15 |
class WooCommercePluginHandler extends BaseContactFormPluginHandler
|
16 |
{
|
|
|
|
|
|
|
|
|
17 |
public function convertToContactModel($orderId)
|
18 |
{
|
19 |
$contactModel = new ContactModel();
|
@@ -31,6 +36,12 @@ class WooCommercePluginHandler extends BaseContactFormPluginHandler
|
|
31 |
$contactModel->setEmail($products_detail["_billing_email"][0]);
|
32 |
}
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
if (!empty($contactModel->getEmail())) {
|
35 |
$contactModel->setEventType(CE4WP_WC_EVENTTYPE);
|
36 |
$contactModel->setOptActionBy(2);
|
@@ -40,15 +51,16 @@ class WooCommercePluginHandler extends BaseContactFormPluginHandler
|
|
40 |
|
41 |
$checkbox_value = null;
|
42 |
|
43 |
-
if (
|
44 |
-
|
45 |
-
} else if (!empty($products_detail[
|
46 |
-
|
47 |
-
} else if (
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
|
|
52 |
}
|
53 |
|
54 |
if (!is_null($checkbox_value)) {
|
@@ -60,32 +72,58 @@ class WooCommercePluginHandler extends BaseContactFormPluginHandler
|
|
60 |
return $contactModel;
|
61 |
}
|
62 |
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
// }
|
67 |
-
// catch (\Exception $exception) {
|
68 |
-
// // silent exception
|
69 |
-
// }
|
70 |
-
// }
|
71 |
|
72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
{
|
74 |
try {
|
75 |
$order = wc_get_order($order_id);
|
76 |
$this->upsertContact($this->convertToContactModel($order->ID));
|
77 |
-
}
|
78 |
-
catch (\Exception $exception) {
|
79 |
// silent exception
|
80 |
}
|
81 |
}
|
82 |
|
83 |
public function registerHooks()
|
84 |
{
|
85 |
-
add_action('woocommerce_new_order', array($this, 'ceHandlerWooCommerceNewOrder'));
|
86 |
// hook function to synchronize
|
87 |
add_action(CE4WP_SYNCHRONIZE_ACTION, array($this, 'syncAction'));
|
88 |
-
|
89 |
}
|
90 |
|
91 |
public function unregisterHooks()
|
@@ -98,7 +136,7 @@ class WooCommercePluginHandler extends BaseContactFormPluginHandler
|
|
98 |
|
99 |
public function syncAction($limit = null)
|
100 |
{
|
101 |
-
if(!is_int($limit) || $limit <= 0) {
|
102 |
$limit = null;
|
103 |
}
|
104 |
|
@@ -107,7 +145,7 @@ class WooCommercePluginHandler extends BaseContactFormPluginHandler
|
|
107 |
$args = array(
|
108 |
'posts_per_page' => -1,
|
109 |
'post_type' => 'shop_order',
|
110 |
-
'post_status'=> array_keys(wc_get_order_statuses())
|
111 |
);
|
112 |
|
113 |
if ($limit != null) {
|
@@ -116,7 +154,7 @@ class WooCommercePluginHandler extends BaseContactFormPluginHandler
|
|
116 |
|
117 |
$products_orders = get_posts($args);
|
118 |
|
119 |
-
foreach (
|
120 |
|
121 |
$contactModel = $this->convertToContactModel($products_order->ID);
|
122 |
|
@@ -129,7 +167,7 @@ class WooCommercePluginHandler extends BaseContactFormPluginHandler
|
|
129 |
if (!empty($backfillArray)) {
|
130 |
|
131 |
$batches = array_chunk($backfillArray, CE4WP_BATCH_SIZE);
|
132 |
-
foreach($batches as $batch){
|
133 |
$this->batchUpsertContacts($batch);
|
134 |
}
|
135 |
}
|
10 |
|
11 |
define('CE4WP_WC_EVENTTYPE', 'WordPress - WooCommerce');
|
12 |
|
13 |
+
use CreativeMail\Modules\Contacts\Models\ContactAddressModel;
|
14 |
use CreativeMail\Modules\Contacts\Models\ContactModel;
|
15 |
|
16 |
class WooCommercePluginHandler extends BaseContactFormPluginHandler
|
17 |
{
|
18 |
+
const CHECKOUT_CONSENT_CHECKBOX_ID = 'ce4wp_checkout_consent_checkbox';
|
19 |
+
const CHECKOUT_CONSENT_CHECKBOX_VALUE = 'ce4wp_checkout_consent';
|
20 |
+
const CHECKOUT_CONSENT_CHECKBOX_VALUE_OLD = 'ce_checkout_consent';
|
21 |
+
|
22 |
public function convertToContactModel($orderId)
|
23 |
{
|
24 |
$contactModel = new ContactModel();
|
36 |
$contactModel->setEmail($products_detail["_billing_email"][0]);
|
37 |
}
|
38 |
|
39 |
+
$contactAddress = $this->getContactAddressFromOrder($products_detail);
|
40 |
+
|
41 |
+
if (!empty($contactAddress)) {
|
42 |
+
$contactModel->setContactAddress($contactAddress);
|
43 |
+
}
|
44 |
+
|
45 |
if (!empty($contactModel->getEmail())) {
|
46 |
$contactModel->setEventType(CE4WP_WC_EVENTTYPE);
|
47 |
$contactModel->setOptActionBy(2);
|
51 |
|
52 |
$checkbox_value = null;
|
53 |
|
54 |
+
if (!empty($_POST[self::CHECKOUT_CONSENT_CHECKBOX_ID])) {
|
55 |
+
$checkbox_value = esc_attr($_POST[self::CHECKOUT_CONSENT_CHECKBOX_ID]);
|
56 |
+
} else if (!empty($products_detail[self::CHECKOUT_CONSENT_CHECKBOX_ID])) {
|
57 |
+
$checkbox_value = $products_detail[self::CHECKOUT_CONSENT_CHECKBOX_ID];
|
58 |
+
} else if (!empty($_POST[self::CHECKOUT_CONSENT_CHECKBOX_VALUE])) {
|
59 |
+
$checkbox_value = esc_attr($_POST[self::CHECKOUT_CONSENT_CHECKBOX_VALUE]);
|
60 |
+
} else if (!empty($products_detail[self::CHECKOUT_CONSENT_CHECKBOX_VALUE])) {
|
61 |
+
$checkbox_value = $products_detail[self::CHECKOUT_CONSENT_CHECKBOX_VALUE];
|
62 |
+
} else if (!empty($products_detail[self::CHECKOUT_CONSENT_CHECKBOX_VALUE_OLD])) {
|
63 |
+
$checkbox_value = $products_detail[self::CHECKOUT_CONSENT_CHECKBOX_VALUE_OLD];
|
64 |
}
|
65 |
|
66 |
if (!is_null($checkbox_value)) {
|
72 |
return $contactModel;
|
73 |
}
|
74 |
|
75 |
+
function getContactAddressFromOrder($products_detail)
|
76 |
+
{
|
77 |
+
$contactAddress = new ContactAddressModel();
|
|
|
|
|
|
|
|
|
|
|
78 |
|
79 |
+
if (isset($products_detail)) {
|
80 |
+
if (!empty($products_detail["_billing_address_1"])) {
|
81 |
+
$contactAddress->setAddress($products_detail["_billing_address_1"][0]);
|
82 |
+
}
|
83 |
+
if (!empty($products_detail["_billing_address_2"])) {
|
84 |
+
$contactAddress->setAddress2($products_detail["_billing_address_2"][0]);
|
85 |
+
}
|
86 |
+
if (!empty($products_detail["_billing_city"])) {
|
87 |
+
$contactAddress->setCity($products_detail["_billing_city"][0]);
|
88 |
+
}
|
89 |
+
if (!empty($products_detail["_billing_country"])) {
|
90 |
+
$contactAddress->setCountryCode($products_detail["_billing_country"][0]);
|
91 |
+
}
|
92 |
+
if (!empty($products_detail["_billing_postcode"])) {
|
93 |
+
$contactAddress->setPostalCode($products_detail["_billing_postcode"][0]);
|
94 |
+
}
|
95 |
+
if (!empty($products_detail["_billing_state"])) {
|
96 |
+
$contactAddress->setStateCode($products_detail["_billing_state"][0]);
|
97 |
+
}
|
98 |
+
}
|
99 |
+
return $contactAddress;
|
100 |
+
}
|
101 |
+
|
102 |
+
// public function ceHandlerWooCommerceNewCustomer($customer_id, $new_customer_data, $password)
|
103 |
+
// {
|
104 |
+
// try {
|
105 |
+
// $this->upsertContact($this->convertToContactModel($new_customer_data));
|
106 |
+
// } catch (\Exception $exception) {
|
107 |
+
// // silent exception
|
108 |
+
// }
|
109 |
+
// }
|
110 |
+
|
111 |
+
public function ceHandlerWooCommerceNewOrder($order_id)
|
112 |
{
|
113 |
try {
|
114 |
$order = wc_get_order($order_id);
|
115 |
$this->upsertContact($this->convertToContactModel($order->ID));
|
116 |
+
} catch (\Exception $exception) {
|
|
|
117 |
// silent exception
|
118 |
}
|
119 |
}
|
120 |
|
121 |
public function registerHooks()
|
122 |
{
|
123 |
+
add_action('woocommerce_new_order', array($this, 'ceHandlerWooCommerceNewOrder'), 10, 1);
|
124 |
// hook function to synchronize
|
125 |
add_action(CE4WP_SYNCHRONIZE_ACTION, array($this, 'syncAction'));
|
126 |
+
// add_action('woocommerce_created_customer', array($this, 'ceHandlerWooCommerceNewCustomer'), 10, 3);
|
127 |
}
|
128 |
|
129 |
public function unregisterHooks()
|
136 |
|
137 |
public function syncAction($limit = null)
|
138 |
{
|
139 |
+
if (!is_int($limit) || $limit <= 0) {
|
140 |
$limit = null;
|
141 |
}
|
142 |
|
145 |
$args = array(
|
146 |
'posts_per_page' => -1,
|
147 |
'post_type' => 'shop_order',
|
148 |
+
'post_status' => array_keys(wc_get_order_statuses())
|
149 |
);
|
150 |
|
151 |
if ($limit != null) {
|
154 |
|
155 |
$products_orders = get_posts($args);
|
156 |
|
157 |
+
foreach ($products_orders as $products_order) {
|
158 |
|
159 |
$contactModel = $this->convertToContactModel($products_order->ID);
|
160 |
|
167 |
if (!empty($backfillArray)) {
|
168 |
|
169 |
$batches = array_chunk($backfillArray, CE4WP_BATCH_SIZE);
|
170 |
+
foreach ($batches as $batch) {
|
171 |
$this->batchUpsertContacts($batch);
|
172 |
}
|
173 |
}
|
src/views/admin-dashboard-widget/campaigns.php
CHANGED
@@ -40,6 +40,6 @@
|
|
40 |
</div>
|
41 |
</section>
|
42 |
<section class="ce4wp-campaign-actions">
|
43 |
-
<button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, '93b1417d-2efb-406d-a9a6-aa8af8f813a3',
|
44 |
-
<button class="button" onclick="ce4wpNavigateToDashboard(this, '5166faec-1dbb-4434-bad0-bb2f75898f92',
|
45 |
</section>
|
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>
|
src/views/admin-dashboard-widget/exception.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<div style="display: flex;">
|
2 |
<section style="flex: 1;">
|
3 |
-
<p style="margin-top: 0;"><?= __( 'Well... this is
|
4 |
<p><?= __( 'Creative Mail ran into an error.', 'ce4wp' ); ?></p>
|
5 |
<p><?= __( 'Please try again at a later time.', 'ce4wp') ?></p>
|
6 |
</section>
|
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>
|
src/views/admin-dashboard-widget/most-recent-campaigns.php
CHANGED
@@ -71,11 +71,11 @@ p.ce4wp-campaigns__item__subtitle {
|
|
71 |
</section>
|
72 |
<section class="ce4wp-campaigns__item__section ce4wp-campaigns__item__section--grow">
|
73 |
<?php if ( $campaign->is_draft ) { ?>
|
74 |
-
<a class="ce4wp-campaigns__item__title" onclick="ce4wpNavigateToDashboard(this, 'c182bb37-9cef-4962-a706-7fa14ffef01e', { campaignId: '<?= esc_attr( $campaign->id ); ?>' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
|
75 |
<strong><?= esc_html( $campaign->name ); ?></strong>
|
76 |
</a>
|
77 |
<?php } else { ?>
|
78 |
-
<a class="ce4wp-campaigns__item__title" onclick="ce4wpNavigateToDashboard(this, 'bd38068c-329b-4c9f-9b2d-fb03a9278bbb', { campaignId: '<?= esc_attr( $campaign->id ); ?>' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
|
79 |
<strong><?= esc_html( $campaign->name ); ?></strong>
|
80 |
</a>
|
81 |
<?php } ?>
|
@@ -92,10 +92,10 @@ p.ce4wp-campaigns__item__subtitle {
|
|
92 |
<?php } ?>
|
93 |
</section>
|
94 |
<section class="ce4wp-campaign-actions">
|
95 |
-
<button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, '93b1417d-2efb-406d-a9a6-aa8af8f813a3',
|
96 |
<?= __( 'Create a new campaign', 'ce4wp' ); ?>
|
97 |
</button>
|
98 |
-
<button class="button" onclick="ce4wpNavigateToDashboard(this, '5166faec-1dbb-4434-bad0-bb2f75898f92',
|
99 |
<?= __( 'View all campaigns', 'ce4wp' ); ?>
|
100 |
</button>
|
101 |
</section>
|
71 |
</section>
|
72 |
<section class="ce4wp-campaigns__item__section ce4wp-campaigns__item__section--grow">
|
73 |
<?php if ( $campaign->is_draft ) { ?>
|
74 |
+
<a class="ce4wp-campaigns__item__title" onclick="ce4wpNavigateToDashboard(this, 'c182bb37-9cef-4962-a706-7fa14ffef01e', { campaignId: '<?= esc_attr( $campaign->id ); ?>', source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
|
75 |
<strong><?= esc_html( $campaign->name ); ?></strong>
|
76 |
</a>
|
77 |
<?php } else { ?>
|
78 |
+
<a class="ce4wp-campaigns__item__title" onclick="ce4wpNavigateToDashboard(this, 'bd38068c-329b-4c9f-9b2d-fb03a9278bbb', { campaignId: '<?= esc_attr( $campaign->id ); ?>', source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
|
79 |
<strong><?= esc_html( $campaign->name ); ?></strong>
|
80 |
</a>
|
81 |
<?php } ?>
|
92 |
<?php } ?>
|
93 |
</section>
|
94 |
<section class="ce4wp-campaign-actions">
|
95 |
+
<button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, '93b1417d-2efb-406d-a9a6-aa8af8f813a3', { source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
|
96 |
<?= __( 'Create a new campaign', 'ce4wp' ); ?>
|
97 |
</button>
|
98 |
+
<button class="button" onclick="ce4wpNavigateToDashboard(this, '5166faec-1dbb-4434-bad0-bb2f75898f92', { source: 'dashboard_widget' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
|
99 |
<?= __( 'View all campaigns', 'ce4wp' ); ?>
|
100 |
</button>
|
101 |
</section>
|
src/views/admin-dashboard-widget/no-campaign.php
CHANGED
@@ -3,7 +3,7 @@
|
|
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',
|
7 |
</section>
|
8 |
<img
|
9 |
src="<?= CE4WP_PLUGIN_URL . 'assets/images/admin-dashboard-widget/airplane.svg'; ?>"
|
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'; ?>"
|
src/views/admin-dashboard-widget/no-ce-account.php
CHANGED
@@ -3,7 +3,7 @@
|
|
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,
|
7 |
<?= __("Let's go!", 'ce4wp'); ?>
|
8 |
</button>
|
9 |
</section>
|
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>
|
src/views/admin-dashboard-widget/no-woocommerce.php
CHANGED
@@ -3,7 +3,7 @@
|
|
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',
|
7 |
<?= __( "Let's go!", 'ce4wp' ); ?>
|
8 |
</button>
|
9 |
</section>
|
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>
|
src/views/admin-feedback-notice/few-contacts.php
CHANGED
@@ -6,6 +6,6 @@
|
|
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',
|
10 |
<span id="close" onclick="hideAdminFeedbackNotice('feedback_notice_few_contacts')"></span>
|
11 |
</div>
|
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>
|
src/views/admin-feedback-notice/many-contacts.php
CHANGED
@@ -10,6 +10,6 @@
|
|
10 |
<?= __( 'contacts are ready for a Creative Mail email campaign. Send one now!', 'ce4wp' ); ?>
|
11 |
</p>
|
12 |
</section>
|
13 |
-
<button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, 'd25f690a-217a-4d68-9c58-8693965d4673',
|
14 |
<span id="close" onclick="hideAdminFeedbackNotice('feedback_notice_many_contacts')"></span>
|
15 |
</div>
|
10 |
<?= __( 'contacts are ready for a Creative Mail email campaign. Send one now!', 'ce4wp' ); ?>
|
11 |
</p>
|
12 |
</section>
|
13 |
+
<button class="button button-primary" onclick="ce4wpNavigateToDashboard(this, 'd25f690a-217a-4d68-9c58-8693965d4673', { source: 'feedback_notice' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)"><?= __( 'Get started', 'ce4wp' ); ?></button>
|
14 |
<span id="close" onclick="hideAdminFeedbackNotice('feedback_notice_many_contacts')"></span>
|
15 |
</div>
|
src/views/dashboard.php
CHANGED
@@ -21,7 +21,7 @@
|
|
21 |
<?= __( 'You’re all set! Creative Mail and WordPress have been linked.', 'ce4wp'); ?>
|
22 |
</p>
|
23 |
<div id="ce4wploaded">
|
24 |
-
<a id='ce4wp-go-button' onclick="ce4wpNavigateToDashboard(this,
|
25 |
<span class="ce4wp-button-label" style="width: 100%;"><?= __( 'Open your Creative Mail dashboard', 'ce4wp'); ?><span class="ce4wp-button-endIcon">
|
26 |
<svg class="ce4wp-Svgicon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
|
27 |
<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>
|
@@ -33,7 +33,7 @@
|
|
33 |
<?= __( 'Or jump straight into:', 'ce4wp'); ?>
|
34 |
</h6>
|
35 |
<div id='ce4wp-sub-apps-container' class="ce4wp-grid ce4wp-mt-3">
|
36 |
-
<div class="ce4wp-grid-item" onclick="ce4wpNavigateToDashboard(this, '1fabdbe2-95ed-4e1e-a2f3-ba0278f5096f',
|
37 |
<div class="ce4wp-grid-item-card ce4wp-mb-4">
|
38 |
<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>
|
39 |
<div class="ce4wp-grid-item-card-content-root">
|
@@ -42,7 +42,7 @@
|
|
42 |
</div>
|
43 |
</div>
|
44 |
</div>
|
45 |
-
<div class="ce4wp-grid-item" onclick="ce4wpNavigateToDashboard(this, 'd5baea05-c603-4cca-852e-f8e82414f6b0',
|
46 |
<div class="ce4wp-grid-item-card ce4wp-mb-4">
|
47 |
<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>
|
48 |
<div class="ce4wp-grid-item-card-content-root">
|
@@ -51,7 +51,7 @@
|
|
51 |
</div>
|
52 |
</div>
|
53 |
</div>
|
54 |
-
<div class="ce4wp-grid-item" onclick="ce4wpNavigateToDashboard(this, '836b20fc-9ff1-41b2-912b-a8646caf05a4',
|
55 |
<div class="ce4wp-grid-item-card ce4wp-mb-4">
|
56 |
<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>
|
57 |
<div class="ce4wp-grid-item-card-content-root">
|
21 |
<?= __( 'You’re all set! Creative Mail and WordPress have been linked.', 'ce4wp'); ?>
|
22 |
</p>
|
23 |
<div id="ce4wploaded">
|
24 |
+
<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">
|
25 |
<span class="ce4wp-button-label" style="width: 100%;"><?= __( 'Open your Creative Mail dashboard', 'ce4wp'); ?><span class="ce4wp-button-endIcon">
|
26 |
<svg class="ce4wp-Svgicon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
|
27 |
<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>
|
33 |
<?= __( 'Or jump straight into:', 'ce4wp'); ?>
|
34 |
</h6>
|
35 |
<div id='ce4wp-sub-apps-container' class="ce4wp-grid ce4wp-mt-3">
|
36 |
+
<div class="ce4wp-grid-item" onclick="ce4wpNavigateToDashboard(this, '1fabdbe2-95ed-4e1e-a2f3-ba0278f5096f', { source: 'ce4wp_dashboard' }, ce4wpDashboardStartCallback, ce4wpDashboardFinishCallback)">
|
37 |
<div class="ce4wp-grid-item-card ce4wp-mb-4">
|
38 |
<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>
|
39 |
<div class="ce4wp-grid-item-card-content-root">
|
42 |
</div>
|
43 |
</div>
|
44 |
</div>
|
45 |
+
<div class="ce4wp-grid-item" onclick="ce4wpNavigateToDashboard(this, 'd5baea05-c603-4cca-852e-f8e82414f6b0', { source: 'ce4wp_dashboard' }, ce4wpDashboardStartCallback, ce4wpDashboardFinishCallback)">
|
46 |
<div class="ce4wp-grid-item-card ce4wp-mb-4">
|
47 |
<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>
|
48 |
<div class="ce4wp-grid-item-card-content-root">
|
51 |
</div>
|
52 |
</div>
|
53 |
</div>
|
54 |
+
<div class="ce4wp-grid-item" onclick="ce4wpNavigateToDashboard(this, '836b20fc-9ff1-41b2-912b-a8646caf05a4', { source: 'ce4wp_dashboard' }, ce4wpDashboardStartCallback, ce4wpDashboardFinishCallback)">
|
55 |
<div class="ce4wp-grid-item-card ce4wp-mb-4">
|
56 |
<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>
|
57 |
<div class="ce4wp-grid-item-card-content-root">
|
src/views/onboarding.php
CHANGED
@@ -1,27 +1,3 @@
|
|
1 |
-
<?php
|
2 |
-
use CreativeMail\Helpers\EnvironmentHelper;
|
3 |
-
use CreativeMail\Helpers\OptionsHelper;
|
4 |
-
|
5 |
-
$redirectUrl = EnvironmentHelper::get_app_gateway_url('wordpress/v1.0/instances/open?clearSession=true&redirectUrl=');
|
6 |
-
$onboardingUrl = EnvironmentHelper::get_app_url() . 'marketing/onboarding/signup?wp_site_name=' . $this->instance_name
|
7 |
-
. '&wp_site_uuid=' . $this->instance_uuid
|
8 |
-
. '&wp_handshake=' . $this->instance_handshake_token
|
9 |
-
. '&wp_callback_url=' . $this->instance_callback_url
|
10 |
-
. '&wp_instance_url=' . $this->instance_url
|
11 |
-
. '&wp_version=' . get_bloginfo('version')
|
12 |
-
. '&plugin_version=' . CE4WP_PLUGIN_VERSION;
|
13 |
-
$referred_by = OptionsHelper::get_referred_by();
|
14 |
-
if (isset($referred_by)) {
|
15 |
-
$utm_campaign = '';
|
16 |
-
if (is_array($referred_by) && array_key_exists('plugin', $referred_by) && array_key_exists('source', $referred_by)) {
|
17 |
-
$utm_campaign = $referred_by['plugin'] . $referred_by['source'];
|
18 |
-
} else if (is_string($referred_by)) {
|
19 |
-
$utm_campaign = str_replace(';', '|', $referred_by);
|
20 |
-
}
|
21 |
-
$onboardingUrl .= '&utm_source=wordpress&utm_medium=plugin&utm_campaign=' . $utm_campaign;
|
22 |
-
}
|
23 |
-
?>
|
24 |
-
|
25 |
<div class="ce4wp-admin-wrapper">
|
26 |
<header class="ce4wp-swoosh-header"></header>
|
27 |
|
@@ -74,12 +50,12 @@ if (isset($referred_by)) {
|
|
74 |
</li>
|
75 |
</ul>
|
76 |
<a id='ce4wp-go-button'
|
77 |
-
href="<?php echo esc_url($redirectUrl . rawurlencode($onboardingUrl)) ?>"
|
78 |
target="_blank"
|
79 |
class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-button-contained-primary ce4wp-mb-4 ce4wp-mt-2"
|
80 |
tabindex="0"
|
81 |
type="button"
|
82 |
-
data-element-type="button"
|
|
|
83 |
<span class="ce4wp-button-label" style="width: 100%;">
|
84 |
<?= __('I Agree and let\'s get started!', 'ce4wp') ?><span class="ce4wp-button-endIcon">
|
85 |
<svg class="ce4wp-Svgicon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<div class="ce4wp-admin-wrapper">
|
2 |
<header class="ce4wp-swoosh-header"></header>
|
3 |
|
50 |
</li>
|
51 |
</ul>
|
52 |
<a id='ce4wp-go-button'
|
|
|
53 |
target="_blank"
|
54 |
class="ce4wp-button-base-root ce4wp-button-root ce4wp-button-contained ce4wp-button-contained-primary ce4wp-mb-4 ce4wp-mt-2"
|
55 |
tabindex="0"
|
56 |
type="button"
|
57 |
+
data-element-type="button"
|
58 |
+
onclick="ce4wpNavigateToDashboard(this, undefined, { source: 'onboarding' }, ce4wpWidgetStartCallback, ce4wpWidgetFinishCallback)">
|
59 |
<span class="ce4wp-button-label" style="width: 100%;">
|
60 |
<?= __('I Agree and let\'s get started!', 'ce4wp') ?><span class="ce4wp-button-endIcon">
|
61 |
<svg class="ce4wp-Svgicon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
|
src/views/settings.php
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
|
7 |
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
8 |
|
1 |
<?php
|
2 |
|
3 |
+
use CreativeMail\CreativeMail;
|
4 |
+
use CreativeMail\Helpers\EnvironmentHelper;
|
5 |
+
use CreativeMail\Helpers\OptionsHelper;
|
6 |
|
7 |
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
8 |
|
vendor/autoload.php
CHANGED
@@ -4,4 +4,4 @@
|
|
4 |
|
5 |
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
|
7 |
-
return
|
4 |
|
5 |
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
|
7 |
+
return ComposerAutoloaderInit5218f9aec364198b823da642da7b30b2::getLoader();
|
vendor/composer/ClassLoader.php
CHANGED
@@ -60,7 +60,7 @@ class ClassLoader
|
|
60 |
public function getPrefixes()
|
61 |
{
|
62 |
if (!empty($this->prefixesPsr0)) {
|
63 |
-
return call_user_func_array('array_merge', $this->prefixesPsr0);
|
64 |
}
|
65 |
|
66 |
return array();
|
60 |
public function getPrefixes()
|
61 |
{
|
62 |
if (!empty($this->prefixesPsr0)) {
|
63 |
+
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
64 |
}
|
65 |
|
66 |
return array();
|
vendor/composer/autoload_classmap.php
CHANGED
@@ -18,6 +18,8 @@ return array(
|
|
18 |
'CreativeMail\\Integrations\\Integration' => $baseDir . '/src/integrations/Integration.php',
|
19 |
'CreativeMail\\Managers\\AdminManager' => $baseDir . '/src/managers/AdminManager.php',
|
20 |
'CreativeMail\\Managers\\ApiManager' => $baseDir . '/src/managers/ApiManager.php',
|
|
|
|
|
21 |
'CreativeMail\\Managers\\EmailManager' => $baseDir . '/src/managers/EmailManager.php',
|
22 |
'CreativeMail\\Managers\\InstanceManager' => $baseDir . '/src/managers/InstanceManager.php',
|
23 |
'CreativeMail\\Managers\\IntegrationManager' => $baseDir . '/src/managers/IntegrationManager.php',
|
18 |
'CreativeMail\\Integrations\\Integration' => $baseDir . '/src/integrations/Integration.php',
|
19 |
'CreativeMail\\Managers\\AdminManager' => $baseDir . '/src/managers/AdminManager.php',
|
20 |
'CreativeMail\\Managers\\ApiManager' => $baseDir . '/src/managers/ApiManager.php',
|
21 |
+
'CreativeMail\\Managers\\CheckoutManager' => $baseDir . '/src/managers/CheckoutManager.php',
|
22 |
+
'CreativeMail\\Managers\\DatabaseManager' => $baseDir . '/src/managers/DatabaseManager.php',
|
23 |
'CreativeMail\\Managers\\EmailManager' => $baseDir . '/src/managers/EmailManager.php',
|
24 |
'CreativeMail\\Managers\\InstanceManager' => $baseDir . '/src/managers/InstanceManager.php',
|
25 |
'CreativeMail\\Managers\\IntegrationManager' => $baseDir . '/src/managers/IntegrationManager.php',
|
vendor/composer/autoload_real.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
-
class
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
@@ -22,15 +22,15 @@ class ComposerAutoloaderInit1bf2baaec5a947c9725005d396762edd
|
|
22 |
return self::$loader;
|
23 |
}
|
24 |
|
25 |
-
spl_autoload_register(array('
|
26 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
27 |
-
spl_autoload_unregister(array('
|
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\
|
34 |
} else {
|
35 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
36 |
foreach ($map as $namespace => $path) {
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
+
class ComposerAutoloaderInit5218f9aec364198b823da642da7b30b2
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
22 |
return self::$loader;
|
23 |
}
|
24 |
|
25 |
+
spl_autoload_register(array('ComposerAutoloaderInit5218f9aec364198b823da642da7b30b2', 'loadClassLoader'), true, true);
|
26 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
27 |
+
spl_autoload_unregister(array('ComposerAutoloaderInit5218f9aec364198b823da642da7b30b2', '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\ComposerStaticInit5218f9aec364198b823da642da7b30b2::getInitializer($loader));
|
34 |
} else {
|
35 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
36 |
foreach ($map as $namespace => $path) {
|
vendor/composer/autoload_static.php
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
-
class
|
8 |
{
|
9 |
public static $prefixLengthsPsr4 = array (
|
10 |
'F' =>
|
@@ -74,6 +74,8 @@ class ComposerStaticInit1bf2baaec5a947c9725005d396762edd
|
|
74 |
'CreativeMail\\Integrations\\Integration' => __DIR__ . '/../..' . '/src/integrations/Integration.php',
|
75 |
'CreativeMail\\Managers\\AdminManager' => __DIR__ . '/../..' . '/src/managers/AdminManager.php',
|
76 |
'CreativeMail\\Managers\\ApiManager' => __DIR__ . '/../..' . '/src/managers/ApiManager.php',
|
|
|
|
|
77 |
'CreativeMail\\Managers\\EmailManager' => __DIR__ . '/../..' . '/src/managers/EmailManager.php',
|
78 |
'CreativeMail\\Managers\\InstanceManager' => __DIR__ . '/../..' . '/src/managers/InstanceManager.php',
|
79 |
'CreativeMail\\Managers\\IntegrationManager' => __DIR__ . '/../..' . '/src/managers/IntegrationManager.php',
|
@@ -128,9 +130,9 @@ class ComposerStaticInit1bf2baaec5a947c9725005d396762edd
|
|
128 |
public static function getInitializer(ClassLoader $loader)
|
129 |
{
|
130 |
return \Closure::bind(function () use ($loader) {
|
131 |
-
$loader->prefixLengthsPsr4 =
|
132 |
-
$loader->prefixDirsPsr4 =
|
133 |
-
$loader->classMap =
|
134 |
|
135 |
}, null, ClassLoader::class);
|
136 |
}
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
+
class ComposerStaticInit5218f9aec364198b823da642da7b30b2
|
8 |
{
|
9 |
public static $prefixLengthsPsr4 = array (
|
10 |
'F' =>
|
74 |
'CreativeMail\\Integrations\\Integration' => __DIR__ . '/../..' . '/src/integrations/Integration.php',
|
75 |
'CreativeMail\\Managers\\AdminManager' => __DIR__ . '/../..' . '/src/managers/AdminManager.php',
|
76 |
'CreativeMail\\Managers\\ApiManager' => __DIR__ . '/../..' . '/src/managers/ApiManager.php',
|
77 |
+
'CreativeMail\\Managers\\CheckoutManager' => __DIR__ . '/../..' . '/src/managers/CheckoutManager.php',
|
78 |
+
'CreativeMail\\Managers\\DatabaseManager' => __DIR__ . '/../..' . '/src/managers/DatabaseManager.php',
|
79 |
'CreativeMail\\Managers\\EmailManager' => __DIR__ . '/../..' . '/src/managers/EmailManager.php',
|
80 |
'CreativeMail\\Managers\\InstanceManager' => __DIR__ . '/../..' . '/src/managers/InstanceManager.php',
|
81 |
'CreativeMail\\Managers\\IntegrationManager' => __DIR__ . '/../..' . '/src/managers/IntegrationManager.php',
|
130 |
public static function getInitializer(ClassLoader $loader)
|
131 |
{
|
132 |
return \Closure::bind(function () use ($loader) {
|
133 |
+
$loader->prefixLengthsPsr4 = ComposerStaticInit5218f9aec364198b823da642da7b30b2::$prefixLengthsPsr4;
|
134 |
+
$loader->prefixDirsPsr4 = ComposerStaticInit5218f9aec364198b823da642da7b30b2::$prefixDirsPsr4;
|
135 |
+
$loader->classMap = ComposerStaticInit5218f9aec364198b823da642da7b30b2::$classMap;
|
136 |
|
137 |
}, null, ClassLoader::class);
|
138 |
}
|