Version Description
- 2019-06-27 =
- CSRF handling for Ajax calls like ajax_woo_infobanner_post_click, ajax_woo_infobanner_post_xout, ajax_fb_toggle_visibility
- use phpcs to adhere to WP coding standards
- Minor UI changes on the iFrame
Download this release
Release Info
Developer | facebook4woocommerce |
Plugin | Facebook for WooCommerce |
Version | 1.9.15 |
Comparing to | |
See all releases |
Code changes from version 1.9.14 to 1.9.15
- assets/css/facebook.css +9 -9
- assets/js/facebook-infobanner.js +34 -21
- assets/js/facebook-metabox.js +58 -45
- assets/js/facebook-products.js +62 -47
- assets/js/facebook-settings.js +836 -752
- changelog.txt +5 -0
- facebook-commerce-events-tracker.php +421 -374
- facebook-commerce-messenger-chat.php +40 -38
- facebook-commerce-pixel-event.php +276 -258
- facebook-commerce.php +2876 -2484
- facebook-config-warmer.php +8 -6
- facebook-for-woocommerce.php +80 -69
- includes/fbasync.php +21 -22
- includes/fbbackground.php +147 -136
- includes/fbgraph.php +298 -284
- includes/fbinfobanner.php +247 -224
- includes/fbproduct.php +786 -736
- includes/fbproductfeed.php +386 -353
- includes/fbutils.php +491 -471
- includes/fbwpml.php +113 -109
- includes/test/facebook-integration-test.php +620 -555
- includes/test/fbproductfeed-test.php +22 -22
- readme.txt +9 -7
assets/css/facebook.css
CHANGED
@@ -42,16 +42,16 @@
|
|
42 |
}
|
43 |
|
44 |
#fbsetup .loader {
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
}
|
52 |
@keyframes spin {
|
53 |
-
|
54 |
-
|
55 |
}
|
56 |
|
57 |
#fbsetup .btn {
|
@@ -199,7 +199,7 @@
|
|
199 |
.tooltip {
|
200 |
position: relative;
|
201 |
border-bottom: 1px dotted black;
|
202 |
-
|
203 |
border: 1px solid;
|
204 |
border-radius: 2px;
|
205 |
/* Launch Test: */
|
42 |
}
|
43 |
|
44 |
#fbsetup .loader {
|
45 |
+
border: 4px solid #f3f3f3; /* Light grey */
|
46 |
+
border-top: 4px solid #3498db; /* Blue */
|
47 |
+
border-radius: 50%;
|
48 |
+
width: 20px;
|
49 |
+
height: 20px;
|
50 |
+
animation: spin 2s linear infinite;
|
51 |
}
|
52 |
@keyframes spin {
|
53 |
+
0% { transform: rotate(0deg); }
|
54 |
+
100% { transform: rotate(360deg); }
|
55 |
}
|
56 |
|
57 |
#fbsetup .btn {
|
199 |
.tooltip {
|
200 |
position: relative;
|
201 |
border-bottom: 1px dotted black;
|
202 |
+
/* container: */
|
203 |
border: 1px solid;
|
204 |
border-radius: 2px;
|
205 |
/* Launch Test: */
|
assets/js/facebook-infobanner.js
CHANGED
@@ -11,32 +11,45 @@
|
|
11 |
* Takes optional payload for POST and optional callback.
|
12 |
*/
|
13 |
function ajax(action, payload = null, callback = null, failcallback = null) {
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
if (payload){
|
18 |
-
for (var attrname in payload) { data[attrname] = payload[attrname]; }
|
19 |
-
}
|
20 |
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
}
|
33 |
|
34 |
function fb_woo_infobanner_post_click(){
|
35 |
-
|
36 |
-
|
|
|
|
|
|
|
|
|
|
|
37 |
}
|
38 |
|
39 |
function fb_woo_infobanner_post_xout() {
|
40 |
-
|
41 |
-
|
|
|
|
|
|
|
|
|
|
|
42 |
}
|
11 |
* Takes optional payload for POST and optional callback.
|
12 |
*/
|
13 |
function ajax(action, payload = null, callback = null, failcallback = null) {
|
14 |
+
var data = Object.assign( {}, {
|
15 |
+
'action': action,
|
16 |
+
}, payload );
|
|
|
|
|
|
|
17 |
|
18 |
+
// Since Wordpress 2.8 ajaxurl is always defined in admin header and
|
19 |
+
// points to admin-ajax.php
|
20 |
+
jQuery.post(
|
21 |
+
ajaxurl,
|
22 |
+
data,
|
23 |
+
function(response) {
|
24 |
+
if (callback) {
|
25 |
+
callback( response );
|
26 |
+
}
|
27 |
+
}
|
28 |
+
).fail(
|
29 |
+
function(errorResponse){
|
30 |
+
if (failcallback) {
|
31 |
+
failcallback( errorResponse );
|
32 |
+
}
|
33 |
+
}
|
34 |
+
);
|
35 |
}
|
36 |
|
37 |
function fb_woo_infobanner_post_click(){
|
38 |
+
console.log( "Woo infobanner post tip click!" );
|
39 |
+
return ajax(
|
40 |
+
'ajax_woo_infobanner_post_click',
|
41 |
+
{
|
42 |
+
"_ajax_nonce": wc_facebook_infobanner_jsx.nonce
|
43 |
+
},
|
44 |
+
);
|
45 |
}
|
46 |
|
47 |
function fb_woo_infobanner_post_xout() {
|
48 |
+
console.log( "Woo infobanner post tip xout!" );
|
49 |
+
return ajax(
|
50 |
+
'ajax_woo_infobanner_post_xout',
|
51 |
+
{
|
52 |
+
"_ajax_nonce": wc_facebook_infobanner_jsx.nonce
|
53 |
+
},
|
54 |
+
);
|
55 |
}
|
assets/js/facebook-metabox.js
CHANGED
@@ -12,56 +12,69 @@
|
|
12 |
* Takes optional payload for POST and optional callback.
|
13 |
*/
|
14 |
function ajax(action, payload = null, cb = null, failcb = null) {
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
if (payload){
|
19 |
-
for (var attrname in payload) { data[attrname] = payload[attrname]; }
|
20 |
-
}
|
21 |
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
}
|
34 |
|
35 |
function fb_reset_product(wp_id) {
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
50 |
}
|
51 |
|
52 |
function fb_delete_product(wp_id) {
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
|
|
|
|
|
|
|
|
|
|
67 |
}
|
12 |
* Takes optional payload for POST and optional callback.
|
13 |
*/
|
14 |
function ajax(action, payload = null, cb = null, failcb = null) {
|
15 |
+
var data = Object.assign( {}, {
|
16 |
+
'action': action,
|
17 |
+
}, payload);
|
|
|
|
|
|
|
18 |
|
19 |
+
// Since Wordpress 2.8 ajaxurl is always defined in admin header and
|
20 |
+
// points to admin-ajax.php
|
21 |
+
jQuery.post(
|
22 |
+
ajaxurl,
|
23 |
+
data,
|
24 |
+
function(response) {
|
25 |
+
if (cb) {
|
26 |
+
cb( response );
|
27 |
+
}
|
28 |
+
}
|
29 |
+
).fail(
|
30 |
+
function(errorResponse){
|
31 |
+
if (failcb) {
|
32 |
+
failcb( errorResponse );
|
33 |
+
}
|
34 |
+
}
|
35 |
+
);
|
36 |
}
|
37 |
|
38 |
function fb_reset_product(wp_id) {
|
39 |
+
if (confirm(
|
40 |
+
'Resetting Facebook metadata will not remove this product from your shop. ' +
|
41 |
+
'If you have duplicated another product and are trying to publish a new Facebook product, ' +
|
42 |
+
'click OK to proceed. ' +
|
43 |
+
'Otherwise, Facebook metadata will be restored when this product is updated again.'
|
44 |
+
)) {
|
45 |
+
var metadata = document.querySelector( '#fb_metadata' );
|
46 |
+
if (metadata) {
|
47 |
+
metadata.innerHTML =
|
48 |
+
"<b>This product is not yet synced to Facebook.</b>";
|
49 |
+
}
|
50 |
+
return ajax(
|
51 |
+
'ajax_reset_single_fb_product',
|
52 |
+
{
|
53 |
+
'wp_id': wp_id,
|
54 |
+
"_ajax_nonce": wc_facebook_metabox_jsx.nonce
|
55 |
+
}
|
56 |
+
);
|
57 |
+
}
|
58 |
}
|
59 |
|
60 |
function fb_delete_product(wp_id) {
|
61 |
+
if (confirm(
|
62 |
+
'Are you sure you want to delete this product on Facebook? If you only want to "hide" the product, ' +
|
63 |
+
'uncheck the "Visible" checkbox and hit "Update". If you delete a product on Facebook and hit "Update" after, ' +
|
64 |
+
'this product will be recreated. To permanently remove this product from Facebook, hit "OK" and close the window.' +
|
65 |
+
'This will not delete the product from WooCommerce.'
|
66 |
+
)) {
|
67 |
+
var metadata = document.querySelector( '#fb_metadata' );
|
68 |
+
if (metadata) {
|
69 |
+
metadata.innerHTML =
|
70 |
+
"<b>This product is not yet synced to Facebook.</b>";
|
71 |
+
}
|
72 |
+
return ajax(
|
73 |
+
'ajax_delete_fb_product',
|
74 |
+
{
|
75 |
+
'wp_id': wp_id,
|
76 |
+
"_ajax_nonce": wc_facebook_metabox_jsx.nonce,
|
77 |
+
}
|
78 |
+
);
|
79 |
+
}
|
80 |
}
|
assets/js/facebook-products.js
CHANGED
@@ -12,58 +12,73 @@
|
|
12 |
* Takes optional payload for POST and optional callback.
|
13 |
*/
|
14 |
function ajax(action, payload = null, cb = null, failcb = null) {
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
}
|
21 |
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
}
|
34 |
|
35 |
function fb_toggle_visibility(wp_id, published) {
|
36 |
-
|
37 |
-
|
38 |
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
|
|
|
|
54 |
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
|
|
|
|
|
|
|
|
64 |
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
|
|
|
|
|
|
|
|
69 |
}
|
12 |
* Takes optional payload for POST and optional callback.
|
13 |
*/
|
14 |
function ajax(action, payload = null, cb = null, failcb = null) {
|
15 |
+
var data = Object.assign( {},
|
16 |
+
{
|
17 |
+
'action': action,
|
18 |
+
}, payload
|
19 |
+
);
|
|
|
20 |
|
21 |
+
// Since Wordpress 2.8 ajaxurl is always defined in admin header and
|
22 |
+
// points to admin-ajax.php
|
23 |
+
jQuery.post(
|
24 |
+
ajaxurl,
|
25 |
+
data,
|
26 |
+
function(response) {
|
27 |
+
if (cb) {
|
28 |
+
cb( response );
|
29 |
+
}
|
30 |
+
}
|
31 |
+
).fail(
|
32 |
+
function(errorResponse){
|
33 |
+
if (failcb) {
|
34 |
+
failcb( errorResponse );
|
35 |
+
}
|
36 |
+
}
|
37 |
+
);
|
38 |
}
|
39 |
|
40 |
function fb_toggle_visibility(wp_id, published) {
|
41 |
+
var buttonId = document.querySelector( "#viz_" + wp_id );
|
42 |
+
var tooltip = document.querySelector( "#tip_" + wp_id );
|
43 |
|
44 |
+
if (published) {
|
45 |
+
tooltip.setAttribute(
|
46 |
+
'data-tip',
|
47 |
+
'Product is synced and published (visible) on Facebook.'
|
48 |
+
);
|
49 |
+
buttonId.setAttribute( 'onclick','fb_toggle_visibility(' + wp_id + ', false)' );
|
50 |
+
buttonId.innerHTML = 'Hide';
|
51 |
+
buttonId.setAttribute( 'class', 'button' );
|
52 |
+
} else {
|
53 |
+
tooltip.setAttribute(
|
54 |
+
'data-tip',
|
55 |
+
'Product is synced but not marked as published (visible) on Facebook.'
|
56 |
+
);
|
57 |
+
buttonId.setAttribute( 'onclick','fb_toggle_visibility(' + wp_id + ', true)' );
|
58 |
+
buttonId.innerHTML = 'Show';
|
59 |
+
buttonId.setAttribute( 'class', 'button button-primary button-large' );
|
60 |
+
}
|
61 |
|
62 |
+
// Reset tooltip
|
63 |
+
jQuery(
|
64 |
+
function($) {
|
65 |
+
$( '.tips' ).tipTip(
|
66 |
+
{
|
67 |
+
'attribute': 'data-tip',
|
68 |
+
'fadeIn': 50,
|
69 |
+
'fadeOut': 50,
|
70 |
+
'delay': 200
|
71 |
+
}
|
72 |
+
);
|
73 |
+
}
|
74 |
+
);
|
75 |
|
76 |
+
return ajax(
|
77 |
+
'ajax_fb_toggle_visibility',
|
78 |
+
{
|
79 |
+
'wp_id': wp_id,
|
80 |
+
'published': published,
|
81 |
+
"_ajax_nonce": wc_facebook_product_jsx.nonce
|
82 |
+
}
|
83 |
+
);
|
84 |
}
|
assets/js/facebook-settings.js
CHANGED
@@ -8,200 +8,230 @@
|
|
8 |
*/
|
9 |
|
10 |
var fb_sync_no_response_count = 0;
|
11 |
-
var fb_show_advanced_options
|
12 |
|
13 |
function toggleAdvancedOptions() {
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
}
|
24 |
|
25 |
function openPopup() {
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
|
|
|
|
|
|
49 |
}
|
50 |
|
51 |
function prepend_protocol(url) {
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
}
|
58 |
|
59 |
function get_product_catalog_id_box() {
|
60 |
-
|
61 |
}
|
62 |
function get_pixel_id_box() {
|
63 |
-
|
64 |
}
|
65 |
function get_pixel_use_pii_id_box() {
|
66 |
-
|
67 |
}
|
68 |
function get_api_key_box() {
|
69 |
-
|
70 |
}
|
71 |
function get_page_id_box() {
|
72 |
-
|
73 |
}
|
74 |
function get_ems_id_box() {
|
75 |
-
|
76 |
}
|
77 |
|
78 |
/*
|
79 |
* Ajax helper function.
|
80 |
* Takes optional payload for POST and optional callback.
|
81 |
*/
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
var pixel_settings = {'facebook_for_woocommerce' : 1};
|
102 |
|
103 |
function facebookConfig() {
|
104 |
-
|
105 |
-
|
106 |
}
|
107 |
|
108 |
function fb_flush(){
|
109 |
-
|
110 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
}
|
112 |
|
113 |
function sync_confirm(verbose = null) {
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
}
|
138 |
|
139 |
// Launch the confirm dialog immediately if the param is in the URL.
|
140 |
-
if (window.location.href.includes("fb_force_resync")) {
|
141 |
-
|
142 |
-
} else if (window.location.href.includes("fb_test_product_sync")) {
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
}
|
147 |
|
148 |
function sync_all_products($using_feed = false, $is_test = false) {
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
167 |
}
|
168 |
|
169 |
// Reset all state
|
170 |
function delete_all_settings(callback = null, failcallback = null) {
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
}
|
206 |
|
207 |
// save_settings and save_settings_and_sync should only be called once
|
@@ -211,690 +241,744 @@ function delete_all_settings(callback = null, failcallback = null) {
|
|
211 |
// It's also called again if the pixel id is ever changed or pixel pii is
|
212 |
// enabled or disabled.
|
213 |
function save_settings(callback = null, failcallback = null, localsettings = null){
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
|
|
|
|
|
|
229 |
}
|
230 |
|
231 |
// save_settings wrapper for plugins as we do not need to:
|
232 |
-
//
|
233 |
-
//
|
234 |
-
//
|
235 |
function save_settings_for_plugin(callback, failcallback) {
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
|
|
250 |
}
|
251 |
|
252 |
// see comments in save_settings function above
|
253 |
function save_settings_and_sync(message) {
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
}
|
276 |
-
|
277 |
-
//Reset buttons to brand new setup state
|
278 |
function reset_buttons(){
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
}
|
310 |
-
|
311 |
-
//Remove reset/settings buttons during product sync
|
312 |
function sync_in_progress(){
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
}
|
340 |
|
341 |
function sync_not_in_progress(){
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
|
|
|
|
394 |
}
|
395 |
|
396 |
function not_connected(){
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
}
|
414 |
|
415 |
function addAnEventListener(obj,evt,func) {
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
}
|
422 |
|
423 |
function setMerchantSettings(message) {
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
|
433 |
-
|
434 |
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
}
|
439 |
|
440 |
function setCatalog(message) {
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
|
450 |
-
|
451 |
|
452 |
-
|
453 |
}
|
454 |
|
455 |
|
456 |
function setPixel(message) {
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
}
|
491 |
|
492 |
function genFeed(message) {
|
493 |
-
|
494 |
}
|
495 |
|
496 |
function setAccessTokenAndPageId(message) {
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
|
|
|
|
525 |
}
|
526 |
|
527 |
function setMsgerChatSetup(data) {
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
}
|
557 |
|
558 |
function iFrameListener(event) {
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
}
|
615 |
-
|
616 |
-
|
|
|
|
|
|
|
|
|
617 |
|
618 |
function urlFromSameDomain(url1, url2) {
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
}
|
628 |
|
629 |
function parseURL(url) {
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
}
|
634 |
|
635 |
// Only do pings for supporting older (pre 1.8) setups.
|
636 |
window.fb_pings =
|
637 |
(window.facebookAdsToolboxConfig.feed.hasClientSideFeedUpload) ?
|
638 |
null :
|
639 |
-
setInterval(
|
640 |
-
|
641 |
-
|
642 |
-
|
|
|
|
|
|
|
643 |
|
644 |
function ping_feed_status_queue(count = 0) {
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
}
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
713 |
}
|
714 |
|
715 |
function parse_response_check_connection(res) {
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
}
|
728 |
|
729 |
function check_feed_upload_queue(check_num) {
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
763 |
}
|
764 |
|
765 |
function display_test_result() {
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
809 |
}
|
810 |
|
811 |
function show_debug_info() {
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
}
|
821 |
|
822 |
function fbe_init_nux_messages() {
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
842 |
}
|
843 |
|
844 |
function saveAutoSyncSchedule() {
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
864 |
}
|
865 |
|
866 |
function onSetDisableSyncOnDevEnvironment() {
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
}
|
884 |
|
885 |
function syncShortDescription() {
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
}
|
8 |
*/
|
9 |
|
10 |
var fb_sync_no_response_count = 0;
|
11 |
+
var fb_show_advanced_options = false;
|
12 |
|
13 |
function toggleAdvancedOptions() {
|
14 |
+
var opts = document.getElementById( "fbAdvancedOptions" );
|
15 |
+
if ( ! fb_show_advanced_options) {
|
16 |
+
opts.style.display = "block";
|
17 |
+
document.getElementById( 'fbAdvancedOptionsText' ).innerHTML = 'Hide Advanced Settings';
|
18 |
+
} else {
|
19 |
+
opts.style.display = "none";
|
20 |
+
document.getElementById( 'fbAdvancedOptionsText' ).innerHTML = 'Show Advanced Settings';
|
21 |
+
}
|
22 |
+
fb_show_advanced_options = ! fb_show_advanced_options;
|
23 |
}
|
24 |
|
25 |
function openPopup() {
|
26 |
+
var width = 1153;
|
27 |
+
var height = 808;
|
28 |
+
var topPos = screen.height / 2 - height / 2;
|
29 |
+
var leftPos = screen.width / 2 - width / 2;
|
30 |
+
window.originParam = window.location.protocol + '//' + window.location.host;
|
31 |
+
var popupUrl;
|
32 |
+
if (window.facebookAdsToolboxConfig.popupOrigin.includes( 'staticxx' )) {
|
33 |
+
window.facebookAdsToolboxConfig.popupOrigin = 'https://www.facebook.com/';
|
34 |
+
}
|
35 |
+
window.facebookAdsToolboxConfig.popupOrigin = prepend_protocol(
|
36 |
+
window.facebookAdsToolboxConfig.popupOrigin
|
37 |
+
);
|
38 |
+
popupUrl = window.facebookAdsToolboxConfig.popupOrigin;
|
39 |
+
|
40 |
+
var path = '/ads/dia';
|
41 |
+
var page = window.open( popupUrl + '/login.php?display=popup&next=' + encodeURIComponent( popupUrl + path + '?origin=' + window.originParam + ' &merchant_settings_id=' + window.facebookAdsToolboxConfig.diaSettingId ), 'DiaWizard', ['toolbar=no', 'location=no', 'directories=no', 'status=no', 'menubar=no', 'scrollbars=no', 'resizable=no', 'copyhistory=no', 'width=' + width, 'height=' + height, 'top=' + topPos, 'left=' + leftPos].join( ',' ) );
|
42 |
+
|
43 |
+
return function (type, params) {
|
44 |
+
page.postMessage(
|
45 |
+
{
|
46 |
+
type: type,
|
47 |
+
params: params
|
48 |
+
},
|
49 |
+
window.facebookAdsToolboxConfig.popupOrigin
|
50 |
+
);
|
51 |
+
};
|
52 |
}
|
53 |
|
54 |
function prepend_protocol(url) {
|
55 |
+
// Preprend https if the url begis with //www.
|
56 |
+
if (url.indexOf( '//www.' ) === 0) {
|
57 |
+
url = 'https:' + url;
|
58 |
+
}
|
59 |
+
return url;
|
60 |
}
|
61 |
|
62 |
function get_product_catalog_id_box() {
|
63 |
+
return document.querySelector( '#woocommerce_facebookcommerce_fb_product_catalog_id' ) || null;
|
64 |
}
|
65 |
function get_pixel_id_box() {
|
66 |
+
return document.querySelector( '#woocommerce_facebookcommerce_fb_pixel_id' ) || null;
|
67 |
}
|
68 |
function get_pixel_use_pii_id_box() {
|
69 |
+
return document.querySelector( '#woocommerce_facebookcommerce_fb_pixel_use_pii' ) || null;
|
70 |
}
|
71 |
function get_api_key_box() {
|
72 |
+
return document.querySelector( '#woocommerce_facebookcommerce_fb_api_key' ) || null;
|
73 |
}
|
74 |
function get_page_id_box() {
|
75 |
+
return document.querySelector( '#woocommerce_facebookcommerce_fb_page_id' ) || null;
|
76 |
}
|
77 |
function get_ems_id_box() {
|
78 |
+
return document.querySelector( '#woocommerce_facebookcommerce_fb_external_merchant_settings_id' ) || null;
|
79 |
}
|
80 |
|
81 |
/*
|
82 |
* Ajax helper function.
|
83 |
* Takes optional payload for POST and optional callback.
|
84 |
*/
|
85 |
+
function ajax(action, payload = null, callback = null, failcallback = null) {
|
86 |
+
var data = Object.assign(
|
87 |
+
{},
|
88 |
+
{
|
89 |
+
'action': action,
|
90 |
+
},
|
91 |
+
payload
|
92 |
+
);
|
93 |
+
|
94 |
+
// Since Wordpress 2.8 ajaxurl is always defined in admin header and
|
95 |
+
// points to admin-ajax.php
|
96 |
+
jQuery.post(
|
97 |
+
ajaxurl,
|
98 |
+
data,
|
99 |
+
function(response) {
|
100 |
+
if (callback) {
|
101 |
+
callback( response );
|
102 |
+
}
|
103 |
+
}
|
104 |
+
).fail(
|
105 |
+
function(errorResponse){
|
106 |
+
if (failcallback) {
|
107 |
+
failcallback( errorResponse );
|
108 |
+
}
|
109 |
+
}
|
110 |
+
);
|
111 |
+
}
|
112 |
+
|
113 |
+
var settings = {'facebook_for_woocommerce' : 1};
|
114 |
var pixel_settings = {'facebook_for_woocommerce' : 1};
|
115 |
|
116 |
function facebookConfig() {
|
117 |
+
window.sendToFacebook = openPopup();
|
118 |
+
window.diaConfig = { 'clientSetup': window.facebookAdsToolboxConfig };
|
119 |
}
|
120 |
|
121 |
function fb_flush(){
|
122 |
+
console.log( "Removing all FBIDs from all products!" );
|
123 |
+
return ajax(
|
124 |
+
'ajax_reset_all_fb_products',
|
125 |
+
{"_ajax_nonce": wc_facebook_settings_jsx.nonce},
|
126 |
+
null,
|
127 |
+
function fb_flushFailCallback(error) {
|
128 |
+
console.log('Failed to reset all FB products');
|
129 |
+
}
|
130 |
+
);
|
131 |
}
|
132 |
|
133 |
function sync_confirm(verbose = null) {
|
134 |
+
var msg = '';
|
135 |
+
switch (verbose) {
|
136 |
+
case 'fb_force_resync':
|
137 |
+
msg = 'Your products will now be resynced with Facebook, ' +
|
138 |
+
'this may take some time.';
|
139 |
+
break;
|
140 |
+
case 'fb_test_product_sync':
|
141 |
+
msg = 'Launch Test?';
|
142 |
+
break;
|
143 |
+
default:
|
144 |
+
msg = 'Facebook for WooCommerce automatically syncs your products on ' +
|
145 |
+
'create/update. Are you sure you want to force product resync? ' +
|
146 |
+
'This will query all published products and may take some time. ' +
|
147 |
+
'You only need to do this if your products are out of sync ' +
|
148 |
+
'or some of your products did not sync.';
|
149 |
+
}
|
150 |
+
if (confirm( msg )) {
|
151 |
+
sync_all_products(
|
152 |
+
window.facebookAdsToolboxConfig.feed.hasClientSideFeedUpload,
|
153 |
+
verbose == 'fb_test_product_sync'
|
154 |
+
);
|
155 |
+
window.fb_sync_start_time = new Date().getTime();
|
156 |
+
}
|
157 |
}
|
158 |
|
159 |
// Launch the confirm dialog immediately if the param is in the URL.
|
160 |
+
if (window.location.href.includes( "fb_force_resync" )) {
|
161 |
+
window.onload = function() { sync_confirm( "fb_force_resync" ); };
|
162 |
+
} else if (window.location.href.includes( "fb_test_product_sync" )) {
|
163 |
+
// Test products sync by feed.
|
164 |
+
window.is_test = true;
|
165 |
+
window.onload = function() { sync_confirm( "fb_test_product_sync" ); };
|
166 |
}
|
167 |
|
168 |
function sync_all_products($using_feed = false, $is_test = false) {
|
169 |
+
if (get_product_catalog_id_box() && ! get_product_catalog_id_box().value) {
|
170 |
+
return;
|
171 |
+
}
|
172 |
+
if (get_api_key_box() && ! get_api_key_box().value) {
|
173 |
+
return;
|
174 |
+
}
|
175 |
+
console.log( 'Syncing all products!' );
|
176 |
+
window.fb_connected = true;
|
177 |
+
sync_in_progress();
|
178 |
+
if ($using_feed) {
|
179 |
+
window.facebookAdsToolboxConfig.feed.hasClientSideFeedUpload = true;
|
180 |
+
window.feed_upload = true;
|
181 |
+
ping_feed_status_queue();
|
182 |
+
return $is_test ? ajax( 'ajax_test_sync_products_using_feed' )
|
183 |
+
: ajax(
|
184 |
+
'ajax_sync_all_fb_products_using_feed',
|
185 |
+
{
|
186 |
+
"_ajax_nonce": wc_facebook_settings_jsx.nonce,
|
187 |
+
},
|
188 |
+
);
|
189 |
+
} else {
|
190 |
+
return ajax(
|
191 |
+
'ajax_sync_all_fb_products',
|
192 |
+
{
|
193 |
+
"_ajax_nonce": wc_facebook_settings_jsx.nonce,
|
194 |
+
}
|
195 |
+
);
|
196 |
+
}
|
197 |
}
|
198 |
|
199 |
// Reset all state
|
200 |
function delete_all_settings(callback = null, failcallback = null) {
|
201 |
+
if (get_product_catalog_id_box()) {
|
202 |
+
get_product_catalog_id_box().value = '';
|
203 |
+
}
|
204 |
+
if (get_pixel_id_box()) {
|
205 |
+
get_pixel_id_box().value = '';
|
206 |
+
}
|
207 |
+
if (get_pixel_use_pii_id_box()) {
|
208 |
+
get_pixel_use_pii_id_box().checked = false;
|
209 |
+
}
|
210 |
+
if (get_api_key_box()) {
|
211 |
+
get_api_key_box().value = '';
|
212 |
+
}
|
213 |
+
if (get_page_id_box()) {
|
214 |
+
get_page_id_box().value = '';
|
215 |
+
}
|
216 |
+
if (get_ems_id_box()) {
|
217 |
+
get_ems_id_box().value = '';
|
218 |
+
}
|
219 |
+
|
220 |
+
window.facebookAdsToolboxConfig.pixel.pixelId = '';
|
221 |
+
window.facebookAdsToolboxConfig.diaSettingId = '';
|
222 |
+
|
223 |
+
reset_buttons();
|
224 |
+
window.fb_connected = false;
|
225 |
+
|
226 |
+
console.log( 'Deleting all settings and removing all FBIDs!' );
|
227 |
+
return ajax(
|
228 |
+
'ajax_delete_fb_settings',
|
229 |
+
{
|
230 |
+
"_ajax_nonce": wc_facebook_settings_jsx.nonce,
|
231 |
+
},
|
232 |
+
callback,
|
233 |
+
failcallback
|
234 |
+
);
|
235 |
}
|
236 |
|
237 |
// save_settings and save_settings_and_sync should only be called once
|
241 |
// It's also called again if the pixel id is ever changed or pixel pii is
|
242 |
// enabled or disabled.
|
243 |
function save_settings(callback = null, failcallback = null, localsettings = null){
|
244 |
+
if ( ! localsettings) {
|
245 |
+
localsettings = settings;
|
246 |
+
}
|
247 |
+
localsettings["_ajax_nonce"] = wc_facebook_settings_jsx.nonce;
|
248 |
+
ajax(
|
249 |
+
'ajax_save_fb_settings',
|
250 |
+
localsettings,
|
251 |
+
function(response){
|
252 |
+
if (callback) {
|
253 |
+
callback( response );
|
254 |
+
}
|
255 |
+
},
|
256 |
+
function(errorResponse){
|
257 |
+
if (failcallback) {
|
258 |
+
failcallback( errorResponse );
|
259 |
+
}
|
260 |
+
}
|
261 |
+
);
|
262 |
}
|
263 |
|
264 |
// save_settings wrapper for plugins as we do not need to:
|
265 |
+
// 1. sync products again after plugin is configured
|
266 |
+
// 2. check api_key, which is from facebook and is only necessary
|
267 |
+
// for following sync products
|
268 |
function save_settings_for_plugin(callback, failcallback) {
|
269 |
+
save_settings(
|
270 |
+
function(response){
|
271 |
+
if (response && response.includes( 'settings_saved' )) {
|
272 |
+
console.log( response );
|
273 |
+
callback( response );
|
274 |
+
} else {
|
275 |
+
console.log( 'Fail response on save_settings_and_sync' );
|
276 |
+
failcallback( response );
|
277 |
+
}
|
278 |
+
},
|
279 |
+
function(errorResponse){
|
280 |
+
console.log( 'Ajax error while saving settings:' + JSON.stringify( errorResponse ) );
|
281 |
+
failcallback( errorResponse );
|
282 |
+
}
|
283 |
+
);
|
284 |
}
|
285 |
|
286 |
// see comments in save_settings function above
|
287 |
function save_settings_and_sync(message) {
|
288 |
+
if ('api_key' in settings) {
|
289 |
+
save_settings(
|
290 |
+
function(response){
|
291 |
+
if (response && response.includes( 'settings_saved' )) {
|
292 |
+
console.log( response );
|
293 |
+
// Final acks
|
294 |
+
window.sendToFacebook( 'ack set pixel', message.params );
|
295 |
+
window.sendToFacebook( 'ack set page access token', message.params );
|
296 |
+
window.sendToFacebook( 'ack set merchant settings', message.params );
|
297 |
+
sync_all_products( true );
|
298 |
+
} else {
|
299 |
+
window.sendToFacebook( 'fail save_settings', response );
|
300 |
+
console.log( 'Fail response on save_settings_and_sync' );
|
301 |
+
}
|
302 |
+
},
|
303 |
+
function(errorResponse){
|
304 |
+
console.log( 'Ajax error while saving settings:' + JSON.stringify( errorResponse ) );
|
305 |
+
window.sendToFacebook( 'fail save_settings_ajax', JSON.stringify( errorResponse ) );
|
306 |
+
}
|
307 |
+
);
|
308 |
+
}
|
309 |
+
}
|
310 |
+
|
311 |
+
// Reset buttons to brand new setup state
|
312 |
function reset_buttons(){
|
313 |
+
if (document.querySelector( '#settings' )) {
|
314 |
+
document.querySelector( '#settings' ).style.display = 'none';
|
315 |
+
}
|
316 |
+
if (document.querySelector( '#cta_button' )) {
|
317 |
+
var cta_element = document.querySelector( '#cta_button' );
|
318 |
+
cta_element.innerHTML = 'Get Started';
|
319 |
+
cta_element.style['font-size'] = '13px';
|
320 |
+
cta_element.style.width = '80px';
|
321 |
+
cta_element.href = '#';
|
322 |
+
cta_element.onclick = function() { facebookConfig(); };
|
323 |
+
}
|
324 |
+
if (document.querySelector( '#learnmore_button' )) {
|
325 |
+
document.querySelector( '#learnmore_button' ).style.display = 'none';
|
326 |
+
}
|
327 |
+
if (document.querySelector( '#setup_h1' )) {
|
328 |
+
document.querySelector( '#setup_h1' ).innerHTML =
|
329 |
+
'Grow your business on Facebook';
|
330 |
+
}
|
331 |
+
if (document.querySelector( '#setup_l1' )) {
|
332 |
+
document.querySelector( '#setup_l1' ).innerHTML =
|
333 |
+
'Easily install a tracking pixel';
|
334 |
+
}
|
335 |
+
if (document.querySelector( '#setup_l2' )) {
|
336 |
+
document.querySelector( '#setup_l2' ).innerHTML =
|
337 |
+
'Upload your products and create a shop';
|
338 |
+
}
|
339 |
+
if (document.querySelector( '#setup_l3' )) {
|
340 |
+
document.querySelector( '#setup_l3' ).innerHTML =
|
341 |
+
'Create dynamic ads with your products and pixel';
|
342 |
+
}
|
343 |
+
}
|
344 |
+
|
345 |
+
// Remove reset/settings buttons during product sync
|
346 |
function sync_in_progress(){
|
347 |
+
if (document.querySelector( '#settings' )) {
|
348 |
+
document.querySelector( '#settings' ).style.display = '';
|
349 |
+
}
|
350 |
+
if (document.querySelector( '#connection_status' )) {
|
351 |
+
document.querySelector( '#connection_status' ).style.display = '';
|
352 |
+
}
|
353 |
+
if (document.querySelector( '#sync_complete' )) {
|
354 |
+
document.querySelector( '#sync_complete' ).style.display = 'none';
|
355 |
+
}
|
356 |
+
// Get rid of all the buttons
|
357 |
+
if (document.querySelector( '#setting_button' )) {
|
358 |
+
document.querySelector( '#setting_button' ).style['pointer-events'] = 'none';
|
359 |
+
}
|
360 |
+
if (document.querySelector( '#resync_products' )) {
|
361 |
+
document.querySelector( '#resync_products' ).style['pointer-events'] = 'none';
|
362 |
+
}
|
363 |
+
if (document.querySelector( '#test_product_sync' )) {
|
364 |
+
document.querySelector( '#test_product_sync' ).style.display = 'none';
|
365 |
+
}
|
366 |
+
// Set a product sync status
|
367 |
+
if (document.querySelector( '#sync_progress' )) {
|
368 |
+
document.querySelector( '#sync_progress' ).innerHTML =
|
369 |
+
'Syncing... Keep this browser open <br/>' +
|
370 |
+
'Until sync is complete<br/>' +
|
371 |
+
'<div class="loader"></div>';
|
372 |
+
}
|
373 |
}
|
374 |
|
375 |
function sync_not_in_progress(){
|
376 |
+
// Reset to pre-setup state.
|
377 |
+
if (document.querySelector( '#cta_button' )) {
|
378 |
+
var cta_element = document.querySelector( '#cta_button' );
|
379 |
+
cta_element.innerHTML = 'Create Ad';
|
380 |
+
cta_element.style['font-size'] = '12px';
|
381 |
+
cta_element.style.width = '60px';
|
382 |
+
if (window.facebookAdsToolboxConfig.diaSettingId) {
|
383 |
+
cta_element.onclick = function() {
|
384 |
+
window.open(
|
385 |
+
'https://www.facebook.com/ads/dia/redirect/?settings_id=' +
|
386 |
+
window.facebookAdsToolboxConfig.diaSettingId + '&version=2' +
|
387 |
+
'&entry_point=admin_panel'
|
388 |
+
);
|
389 |
+
};
|
390 |
+
} else {
|
391 |
+
cta_element.style['pointer-events'] = 'none';
|
392 |
+
}
|
393 |
+
}
|
394 |
+
if (document.querySelector( '#learnmore_button' )) {
|
395 |
+
var learnmore_element = document.querySelector( '#learnmore_button' );
|
396 |
+
if (window.facebookAdsToolboxConfig.diaSettingId) {
|
397 |
+
learnmore_element.style.display = '';
|
398 |
+
}
|
399 |
+
}
|
400 |
+
if (document.querySelector( '#setup_h1' )) {
|
401 |
+
document.querySelector( '#setup_h1' ).innerHTML =
|
402 |
+
'Reach the right people and sell more products';
|
403 |
+
}
|
404 |
+
if (document.querySelector( '#setup_l1' )) {
|
405 |
+
document.querySelector( '#setup_l1' ).innerHTML =
|
406 |
+
'Create an ad in a few steps';
|
407 |
+
}
|
408 |
+
if (document.querySelector( '#setup_l2' )) {
|
409 |
+
document.querySelector( '#setup_l2' ).innerHTML =
|
410 |
+
'Use built-in best practice for online sales';
|
411 |
+
}
|
412 |
+
if (document.querySelector( '#setup_l3' )) {
|
413 |
+
document.querySelector( '#setup_l3' ).innerHTML =
|
414 |
+
'Get reporting on sales and revenue';
|
415 |
+
}
|
416 |
+
if (document.querySelector( '#settings' )) {
|
417 |
+
document.querySelector( '#settings' ).style.display = '';
|
418 |
+
}
|
419 |
+
// Enable buttons.
|
420 |
+
if (document.querySelector( '#setting_button' )) {
|
421 |
+
document.querySelector( '#setting_button' ).style['pointer-events'] = 'auto';
|
422 |
+
}
|
423 |
+
if (document.querySelector( '#resync_products' )) {
|
424 |
+
document.querySelector( '#resync_products' ).style ['pointer-events'] = 'auto';
|
425 |
+
}
|
426 |
+
// Remove sync progress.
|
427 |
+
if (document.querySelector( '#sync_progress' )) {
|
428 |
+
document.querySelector( '#sync_progress' ).innerHTML = '';
|
429 |
+
}
|
430 |
}
|
431 |
|
432 |
function not_connected(){
|
433 |
+
if (document.querySelector( '#connection_status' )) {
|
434 |
+
document.querySelector( '#connection_status' ).style.display = 'none';
|
435 |
+
}
|
436 |
+
|
437 |
+
if (document.querySelector( '#setting_button' )) {
|
438 |
+
document.querySelector( '#setting_button' ).style['pointer-events'] = 'auto';
|
439 |
+
}
|
440 |
+
if (document.querySelector( '#resync_products' )) {
|
441 |
+
document.querySelector( '#resync_products' ).style['pointer-events'] = 'none';
|
442 |
+
}
|
443 |
+
if (document.querySelector( '#sync_complete' )) {
|
444 |
+
document.querySelector( '#sync_complete' ).style.display = 'none';
|
445 |
+
}
|
446 |
+
if (document.querySelector( '#sync_progress' )) {
|
447 |
+
document.querySelector( '#sync_progress' ).innerHTML = '';
|
448 |
+
}
|
449 |
}
|
450 |
|
451 |
function addAnEventListener(obj,evt,func) {
|
452 |
+
if ('addEventListener' in obj) {
|
453 |
+
obj.addEventListener( evt,func, false );
|
454 |
+
} else if ('attachEvent' in obj) {// IE
|
455 |
+
obj.attachEvent( 'on' + evt,func );
|
456 |
+
}
|
457 |
}
|
458 |
|
459 |
function setMerchantSettings(message) {
|
460 |
+
if ( ! message.params.setting_id) {
|
461 |
+
console.error( 'Facebook Extension Error: got no setting_id', message.params );
|
462 |
+
window.sendToFacebook( 'fail set merchant settings', message.params );
|
463 |
+
return;
|
464 |
+
}
|
465 |
+
if (get_ems_id_box()) {
|
466 |
+
get_ems_id_box().value = message.params.setting_id;
|
467 |
+
}
|
468 |
|
469 |
+
settings.external_merchant_settings_id = message.params.setting_id;
|
470 |
|
471 |
+
// Immediately set in case button is clicked again
|
472 |
+
window.facebookAdsToolboxConfig.diaSettingId = message.params.setting_id;
|
473 |
+
// Ack merchant settings happens after settings are saved
|
474 |
}
|
475 |
|
476 |
function setCatalog(message) {
|
477 |
+
if ( ! message.params.catalog_id) {
|
478 |
+
console.error( 'Facebook Extension Error: got no catalog_id', message.params );
|
479 |
+
window.sendToFacebook( 'fail set catalog', message.params );
|
480 |
+
return;
|
481 |
+
}
|
482 |
+
if (get_api_key_box()) {
|
483 |
+
get_product_catalog_id_box().value = message.params.catalog_id;
|
484 |
+
}
|
485 |
|
486 |
+
settings.product_catalog_id = message.params.catalog_id;
|
487 |
|
488 |
+
window.sendToFacebook( 'ack set catalog', message.params );
|
489 |
}
|
490 |
|
491 |
|
492 |
function setPixel(message) {
|
493 |
+
if ( ! message.params.pixel_id) {
|
494 |
+
console.error( 'Facebook Ads Extension Error: got no pixel_id', message.params );
|
495 |
+
window.sendToFacebook( 'fail set pixel', message.params );
|
496 |
+
return;
|
497 |
+
}
|
498 |
+
if (get_pixel_id_box()) {
|
499 |
+
get_pixel_id_box().value = message.params.pixel_id;
|
500 |
+
}
|
501 |
+
|
502 |
+
settings.pixel_id = message.params.pixel_id;
|
503 |
+
pixel_settings.pixel_id = settings.pixel_id;
|
504 |
+
if (message.params.pixel_use_pii !== undefined) {
|
505 |
+
if (get_pixel_use_pii_id_box()) {
|
506 |
+
// !! will explicitly convert truthy/falsy values to a boolean
|
507 |
+
get_pixel_use_pii_id_box().checked = ! ! message.params.pixel_use_pii;
|
508 |
+
}
|
509 |
+
settings.pixel_use_pii = message.params.pixel_use_pii;
|
510 |
+
pixel_settings.pixel_use_pii = settings.pixel_use_pii;
|
511 |
+
}
|
512 |
+
|
513 |
+
// We need this to support changing the pixel id after setup.
|
514 |
+
save_settings(
|
515 |
+
function(response){
|
516 |
+
if (response && response.includes( 'settings_saved' )) {
|
517 |
+
window.sendToFacebook( 'ack set pixel', message.params );
|
518 |
+
} //may not get settings_saved if we try to save pixel before an API key
|
519 |
+
},
|
520 |
+
function(errorResponse){
|
521 |
+
console.log( errorResponse );
|
522 |
+
window.sendToFacebook( 'fail set pixel', errorResponse );
|
523 |
+
},
|
524 |
+
pixel_settings
|
525 |
+
);
|
526 |
}
|
527 |
|
528 |
function genFeed(message) {
|
529 |
+
// no-op
|
530 |
}
|
531 |
|
532 |
function setAccessTokenAndPageId(message) {
|
533 |
+
if ( ! message.params.page_token) {
|
534 |
+
console.error(
|
535 |
+
'Facebook Ads Extension Error: got no page_token',
|
536 |
+
message.params
|
537 |
+
);
|
538 |
+
window.sendToFacebook( 'fail set page access token', message.params );
|
539 |
+
return;
|
540 |
+
}
|
541 |
+
/*
|
542 |
+
Set page_token here
|
543 |
+
*/
|
544 |
+
|
545 |
+
if (get_api_key_box()) {
|
546 |
+
get_api_key_box().value = message.params.page_token;
|
547 |
+
}
|
548 |
+
|
549 |
+
if (get_page_id_box()) {
|
550 |
+
get_page_id_box().value = message.params.page_id;
|
551 |
+
}
|
552 |
+
|
553 |
+
settings.api_key = message.params.page_token;
|
554 |
+
settings.page_id = message.params.page_id;
|
555 |
+
// Ack token in "save_settings_and_sync" for final ack
|
556 |
+
|
557 |
+
window.facebookAdsToolboxConfig.tokenExpired = false;
|
558 |
+
if (document.querySelector( '#token_text' )) {
|
559 |
+
document.querySelector( '#token_text' ).innerHTML =
|
560 |
+
` < strong > Your API key has been updated.<br / >
|
561 |
+
Please refresh the page.< / strong > `;
|
562 |
+
}
|
563 |
}
|
564 |
|
565 |
function setMsgerChatSetup(data) {
|
566 |
+
if (data.hasOwnProperty( 'is_messenger_chat_plugin_enabled' )) {
|
567 |
+
settings.is_messenger_chat_plugin_enabled =
|
568 |
+
data.is_messenger_chat_plugin_enabled;
|
569 |
+
}
|
570 |
+
if (data.hasOwnProperty( 'facebook_jssdk_version' )) {
|
571 |
+
settings.facebook_jssdk_version =
|
572 |
+
data.facebook_jssdk_version;
|
573 |
+
}
|
574 |
+
if (data.hasOwnProperty( 'page_id' )) {
|
575 |
+
settings.fb_page_id = data.page_id;
|
576 |
+
}
|
577 |
+
|
578 |
+
if (data.hasOwnProperty( 'customization' )) {
|
579 |
+
var customization = data.customization;
|
580 |
+
|
581 |
+
if (customization.hasOwnProperty( 'greetingTextCode' )) {
|
582 |
+
settings.msger_chat_customization_greeting_text_code =
|
583 |
+
customization.greetingTextCode;
|
584 |
+
}
|
585 |
+
if (customization.hasOwnProperty( 'locale' )) {
|
586 |
+
settings.msger_chat_customization_locale =
|
587 |
+
customization.locale;
|
588 |
+
}
|
589 |
+
if (customization.hasOwnProperty( 'themeColorCode' )) {
|
590 |
+
settings.msger_chat_customization_theme_color_code =
|
591 |
+
customization.themeColorCode;
|
592 |
+
}
|
593 |
+
}
|
594 |
}
|
595 |
|
596 |
function iFrameListener(event) {
|
597 |
+
// Fix for web.facebook.com
|
598 |
+
const origin = event.origin || event.originalEvent.origin;
|
599 |
+
if (origin != window.facebookAdsToolboxConfig.popupOrigin &&
|
600 |
+
urlFromSameDomain( origin, window.facebookAdsToolboxConfig.popupOrigin )) {
|
601 |
+
window.facebookAdsToolboxConfig.popupOrigin = origin;
|
602 |
+
}
|
603 |
+
|
604 |
+
switch (event.data.type) {
|
605 |
+
case 'reset':
|
606 |
+
delete_all_settings(
|
607 |
+
function(res){
|
608 |
+
if (res && event.data.params) {
|
609 |
+
if (res === 'Settings Deleted') {
|
610 |
+
window.sendToFacebook( 'ack reset', event.data.params );
|
611 |
+
} else {
|
612 |
+
console.log( res );
|
613 |
+
alert( res );
|
614 |
+
}
|
615 |
+
} else {
|
616 |
+
console.log( "Got no response from delete_all_settings" );
|
617 |
+
}
|
618 |
+
},
|
619 |
+
function(err){
|
620 |
+
console.error( err );
|
621 |
+
}
|
622 |
+
);
|
623 |
+
break;
|
624 |
+
case 'get dia settings':
|
625 |
+
window.sendToFacebook( 'dia settings', window.diaConfig );
|
626 |
+
break;
|
627 |
+
case 'set merchant settings':
|
628 |
+
setMerchantSettings( event.data );
|
629 |
+
break;
|
630 |
+
case 'set catalog':
|
631 |
+
setCatalog( event.data );
|
632 |
+
break;
|
633 |
+
case 'set pixel':
|
634 |
+
setPixel( event.data );
|
635 |
+
break;
|
636 |
+
case 'gen feed':
|
637 |
+
genFeed();
|
638 |
+
break;
|
639 |
+
case 'set page access token':
|
640 |
+
// Should be last message received
|
641 |
+
setAccessTokenAndPageId( event.data );
|
642 |
+
save_settings_and_sync( event.data );
|
643 |
+
break;
|
644 |
+
case 'set msger chat':
|
645 |
+
setMsgerChatSetup( event.data.params );
|
646 |
+
save_settings_for_plugin(
|
647 |
+
function(response) {
|
648 |
+
window.sendToFacebook( 'ack msger chat', event.data );
|
649 |
+
},
|
650 |
+
function(response) {
|
651 |
+
window.sendToFacebook( 'fail ack msger chat', event.data );
|
652 |
+
}
|
653 |
+
);
|
654 |
+
break;
|
655 |
+
}
|
656 |
+
}
|
657 |
+
|
658 |
+
addAnEventListener( window,'message',iFrameListener );
|
659 |
|
660 |
function urlFromSameDomain(url1, url2) {
|
661 |
+
if ( ! url1.startsWith( 'http' ) || ! url2.startsWith( 'http' )) {
|
662 |
+
return false;
|
663 |
+
}
|
664 |
+
var u1 = parseURL( url1 );
|
665 |
+
var u2 = parseURL( url2 );
|
666 |
+
var u1host = u1.host.replace( /^\w+\./, 'www.' );
|
667 |
+
var u2host = u2.host.replace( /^\w+\./, 'www.' );
|
668 |
+
return u1.protocol === u2.protocol && u1host === u2host;
|
669 |
}
|
670 |
|
671 |
function parseURL(url) {
|
672 |
+
var parser = document.createElement( 'a' );
|
673 |
+
parser.href = url;
|
674 |
+
return parser;
|
675 |
}
|
676 |
|
677 |
// Only do pings for supporting older (pre 1.8) setups.
|
678 |
window.fb_pings =
|
679 |
(window.facebookAdsToolboxConfig.feed.hasClientSideFeedUpload) ?
|
680 |
null :
|
681 |
+
setInterval(
|
682 |
+
function(){
|
683 |
+
console.log( "Pinging queue..." );
|
684 |
+
check_queues();
|
685 |
+
},
|
686 |
+
10000
|
687 |
+
);
|
688 |
|
689 |
function ping_feed_status_queue(count = 0) {
|
690 |
+
window.fb_feed_pings = setInterval(
|
691 |
+
function() {
|
692 |
+
console.log( 'Pinging feed uploading queue...' );
|
693 |
+
check_feed_upload_queue( count );
|
694 |
+
},
|
695 |
+
30000 * (1 << count)
|
696 |
+
);
|
697 |
+
}
|
698 |
+
|
699 |
+
function product_sync_complete(sync_progress_element) {
|
700 |
+
sync_not_in_progress();
|
701 |
+
if (document.querySelector( '#sync_complete' )) {
|
702 |
+
document.querySelector( '#sync_complete' ).style.display = '';
|
703 |
+
}
|
704 |
+
if (sync_progress_element) {
|
705 |
+
sync_progress_element.innerHTML = '';
|
706 |
+
}
|
707 |
+
clearInterval( window.fb_pings );
|
708 |
+
}
|
709 |
+
|
710 |
+
function check_queues() {
|
711 |
+
ajax(
|
712 |
+
'ajax_fb_background_check_queue',
|
713 |
+
{
|
714 |
+
"request_time": new Date().getTime(),
|
715 |
+
"_ajax_nonce": wc_facebook_settings_jsx.nonce,
|
716 |
+
},
|
717 |
+
function( response ) {
|
718 |
+
if ( window.feed_upload ) {
|
719 |
+
clearInterval( window.fb_pings );
|
720 |
+
return;
|
721 |
+
}
|
722 |
+
var sync_progress_element = document.querySelector( '#sync_progress' );
|
723 |
+
var res = parse_response_check_connection( response );
|
724 |
+
if ( !res ) {
|
725 |
+
if ( fb_sync_no_response_count++ > 5 ) {
|
726 |
+
clearInterval( window.fb_pings );
|
727 |
+
}
|
728 |
+
return;
|
729 |
+
}
|
730 |
+
fb_sync_no_response_count = 0;
|
731 |
+
|
732 |
+
if ( res ) {
|
733 |
+
if ( !res.background ) {
|
734 |
+
console.log( "No background sync found, disabling pings" );
|
735 |
+
clearInterval( window.fb_pings );
|
736 |
+
}
|
737 |
+
|
738 |
+
var processing = !!res.processing; // explicit boolean conversion
|
739 |
+
var remaining = res.remaining;
|
740 |
+
if ( processing ) {
|
741 |
+
if ( sync_progress_element ) {
|
742 |
+
sync_progress_element.innerHTML =
|
743 |
+
'<strong>Progress:</strong> ' + remaining + ' item' +
|
744 |
+
( remaining > 1 ? 's' : '' ) + ' remaining.';
|
745 |
+
}
|
746 |
+
if ( remaining === 0 ) {
|
747 |
+
product_sync_complete( sync_progress_element );
|
748 |
+
}
|
749 |
+
} else {
|
750 |
+
// Not processing, none remaining. Either long complete, or just completed
|
751 |
+
if ( window.fb_sync_start_time && res.request_time ) {
|
752 |
+
var request_time = new Date( parseInt( res.request_time ) );
|
753 |
+
if ( window.fb_sync_start_time > request_time ) {
|
754 |
+
// Old ping, do nothing.
|
755 |
+
console.log( "OLD PING" );
|
756 |
+
return;
|
757 |
+
}
|
758 |
+
}
|
759 |
+
|
760 |
+
if ( remaining === 0 ) {
|
761 |
+
product_sync_complete( sync_progress_element );
|
762 |
+
}
|
763 |
+
}
|
764 |
+
}
|
765 |
+
}
|
766 |
+
);
|
767 |
}
|
768 |
|
769 |
function parse_response_check_connection(res) {
|
770 |
+
if (res) {
|
771 |
+
console.log( res );
|
772 |
+
var response = res.substring( res.indexOf( "{" ) ); // Trim leading extra chars (rnrnr)
|
773 |
+
response = JSON.parse( response );
|
774 |
+
if ( ! response.connected && ! window.fb_connected) {
|
775 |
+
not_connected();
|
776 |
+
return null;
|
777 |
+
}
|
778 |
+
return response;
|
779 |
+
}
|
780 |
+
return null;
|
781 |
}
|
782 |
|
783 |
function check_feed_upload_queue(check_num) {
|
784 |
+
ajax(
|
785 |
+
'ajax_check_feed_upload_status',
|
786 |
+
{
|
787 |
+
"_ajax_nonce": wc_facebook_settings_jsx.nonce,
|
788 |
+
},
|
789 |
+
function(response) {
|
790 |
+
var sync_progress_element = document.querySelector( '#sync_progress' );
|
791 |
+
var res = parse_response_check_connection( response );
|
792 |
+
clearInterval( window.fb_feed_pings );
|
793 |
+
if (res) {
|
794 |
+
var status = res.status;
|
795 |
+
switch (status) {
|
796 |
+
case 'complete':
|
797 |
+
window.feed_upload = false;
|
798 |
+
if (window.is_test) {
|
799 |
+
display_test_result();
|
800 |
+
} else {
|
801 |
+
product_sync_complete( sync_progress_element );
|
802 |
+
}
|
803 |
+
break;
|
804 |
+
case 'in progress':
|
805 |
+
if (sync_progress_element) {
|
806 |
+
sync_progress_element.innerHTML =
|
807 |
+
'Syncing... Keep this browser open <br/>' +
|
808 |
+
'Until sync is complete<br/>';
|
809 |
+
}
|
810 |
+
ping_feed_status_queue( check_num + 1 );
|
811 |
+
break;
|
812 |
+
default:
|
813 |
+
sync_progress_element.innerHTML =
|
814 |
+
'<strong>Something wrong when uploading, please try again.</strong>';
|
815 |
+
window.feed_upload = false;
|
816 |
+
if (window.is_test) {
|
817 |
+
display_test_result();
|
818 |
+
}
|
819 |
+
}
|
820 |
+
}
|
821 |
+
}
|
822 |
+
);
|
823 |
}
|
824 |
|
825 |
function display_test_result() {
|
826 |
+
ajax(
|
827 |
+
'ajax_display_test_result',
|
828 |
+
{
|
829 |
+
"_ajax_nonce": wc_facebook_settings_jsx.nonce
|
830 |
+
},
|
831 |
+
function(response) {
|
832 |
+
var sync_complete_element = document.querySelector( '#sync_complete' );
|
833 |
+
var sync_progress_element = document.querySelector( '#sync_progress' );
|
834 |
+
var res = parse_response_check_connection( response );
|
835 |
+
if (res) {
|
836 |
+
var status = res.pass;
|
837 |
+
switch (status) {
|
838 |
+
case 'true':
|
839 |
+
sync_not_in_progress();
|
840 |
+
if (sync_complete_element) {
|
841 |
+
sync_complete_element.style.display = '';
|
842 |
+
sync_complete_element.innerHTML =
|
843 |
+
'<strong>Status: </strong>Test Pass.';
|
844 |
+
}
|
845 |
+
if (sync_progress_element) {
|
846 |
+
sync_progress_element.innerHTML = '';
|
847 |
+
}
|
848 |
+
window.is_test = false;
|
849 |
+
break;
|
850 |
+
case 'in progress':
|
851 |
+
if (sync_progress_element) {
|
852 |
+
sync_progress_element.innerHTML =
|
853 |
+
'<strong>Integration test in progress...</strong>';
|
854 |
+
}
|
855 |
+
ping_feed_status_queue();
|
856 |
+
break;
|
857 |
+
default:
|
858 |
+
window.debug_info = res.debug_info + '<br/>' + res.stack_trace;
|
859 |
+
if (sync_complete_element) {
|
860 |
+
sync_complete_element.style.display = '';
|
861 |
+
sync_complete_element.innerHTML =
|
862 |
+
'<strong>Status: </strong>Test Fail.';
|
863 |
+
}
|
864 |
+
if (sync_progress_element) {
|
865 |
+
sync_progress_element.innerHTML = '';
|
866 |
+
}
|
867 |
+
if (document.querySelector( '#debug_info' )) {
|
868 |
+
document.querySelector( '#debug_info' ).style.display = '';
|
869 |
+
}
|
870 |
+
window.is_test = false;
|
871 |
+
}
|
872 |
+
}
|
873 |
+
}
|
874 |
+
);
|
875 |
}
|
876 |
|
877 |
function show_debug_info() {
|
878 |
+
var stack_trace_element = document.querySelector( '#stack_trace' );
|
879 |
+
if (stack_trace_element) {
|
880 |
+
stack_trace_element.innerHTML = window.debug_info;
|
881 |
+
}
|
882 |
+
if (document.querySelector( '#debug_info' )) {
|
883 |
+
document.querySelector( '#debug_info' ).style.display = 'none';
|
884 |
+
}
|
885 |
+
window.debug_info = '';
|
886 |
}
|
887 |
|
888 |
function fbe_init_nux_messages() {
|
889 |
+
var jQuery = window.jQuery;
|
890 |
+
jQuery(
|
891 |
+
function() {
|
892 |
+
jQuery.each(
|
893 |
+
jQuery( '.nux-message' ),
|
894 |
+
function(_index, nux_msg) {
|
895 |
+
var nux_msg_elem = jQuery( nux_msg );
|
896 |
+
var targetid = nux_msg_elem.data( 'target' );
|
897 |
+
var target_elem = jQuery( '#' + targetid );
|
898 |
+
var t_pos = target_elem.position();
|
899 |
+
var t_half_height = target_elem.height() / 2;
|
900 |
+
var t_width = target_elem.outerWidth();
|
901 |
+
nux_msg_elem.css(
|
902 |
+
{
|
903 |
+
'top': '' + Math.ceil( t_pos.top + t_half_height ) + 'px',
|
904 |
+
'left': '' + Math.ceil( t_pos.left + t_width ) + 'px',
|
905 |
+
'display': 'block'
|
906 |
+
}
|
907 |
+
);
|
908 |
+
jQuery( '.nux-message-close-btn', nux_msg_elem ).click(
|
909 |
+
function() {
|
910 |
+
jQuery( nux_msg ).hide();
|
911 |
+
}
|
912 |
+
);
|
913 |
+
}
|
914 |
+
);
|
915 |
+
}
|
916 |
+
);
|
917 |
}
|
918 |
|
919 |
function saveAutoSyncSchedule() {
|
920 |
+
var isChecked = document.getElementsByClassName( 'autosyncCheck' )[0].checked;
|
921 |
+
var timebox = document.getElementsByClassName( 'autosyncTime' )[0];
|
922 |
+
var button = document.getElementsByClassName( 'autosyncSaveButton' )[0];
|
923 |
+
var saved = document.getElementsByClassName( 'autosyncSavedNotice' )[0];
|
924 |
+
|
925 |
+
if ( ! isChecked) {
|
926 |
+
timebox.setAttribute( 'disabled', true );
|
927 |
+
} else {
|
928 |
+
timebox.removeAttribute( 'disabled' );
|
929 |
+
saved.style.transition = '';
|
930 |
+
saved.style.opacity = 1;
|
931 |
+
// Fade out the small 'Saved' after 3 seconds.
|
932 |
+
setTimeout(
|
933 |
+
function() {
|
934 |
+
saved.style.opacity = 0;
|
935 |
+
saved.style.transition = 'opacity 5s';}
|
936 |
+
,
|
937 |
+
3000
|
938 |
+
);
|
939 |
+
}
|
940 |
+
|
941 |
+
ajax( 'ajax_schedule_force_resync',
|
942 |
+
{
|
943 |
+
"enabled": isChecked ? 1 : 0,
|
944 |
+
"time" : timebox.value,
|
945 |
+
"_ajax_nonce": wc_facebook_settings_jsx.nonce,
|
946 |
+
}
|
947 |
+
);
|
948 |
}
|
949 |
|
950 |
function onSetDisableSyncOnDevEnvironment() {
|
951 |
+
var isChecked = document.getElementsByClassName( 'disableOnDevEnvironment' )[0].checked;
|
952 |
+
ajax(
|
953 |
+
'ajax_update_fb_option',
|
954 |
+
{
|
955 |
+
"option": "fb_disable_sync_on_dev_environment",
|
956 |
+
"option_value": isChecked ? 1 : 0,
|
957 |
+
"_ajax_nonce": wc_facebook_settings_jsx.nonce,
|
958 |
+
},
|
959 |
+
null,
|
960 |
+
function onSetDisableSyncOnDevEnvironmentFailCallback(error) {
|
961 |
+
document.getElementsByClassName(
|
962 |
+
'onSetDisableSyncOnDevEnvironment'
|
963 |
+
)[0].checked = ! isChecked;
|
964 |
+
console.log( 'Failed to disable sync on dev environment' );
|
965 |
+
}
|
966 |
+
);
|
967 |
}
|
968 |
|
969 |
function syncShortDescription() {
|
970 |
+
var isChecked = document.getElementsByClassName( 'syncShortDescription' )[0].checked;
|
971 |
+
ajax(
|
972 |
+
'ajax_update_fb_option',
|
973 |
+
{
|
974 |
+
"option": "fb_sync_short_description",
|
975 |
+
"option_value": isChecked ? 1 : 0,
|
976 |
+
"_ajax_nonce": wc_facebook_settings_jsx.nonce,
|
977 |
+
},
|
978 |
+
null,
|
979 |
+
function syncShortDescriptionFailCallback(error) {
|
980 |
+
document.getElementsByClassName( 'syncShortDescription' )[0].checked = ! isChecked;
|
981 |
+
console.log( 'Failed to sync Short Description' );
|
982 |
+
}
|
983 |
+
);
|
984 |
}
|
changelog.txt
CHANGED
@@ -1,4 +1,9 @@
|
|
1 |
*** Facebook for WooCommerce Changelog ***
|
|
|
|
|
|
|
|
|
|
|
2 |
2019-06-20 - Version 1.9.14
|
3 |
* Revisit CSRF security issue
|
4 |
* Remove rest controller which is not used
|
1 |
*** Facebook for WooCommerce Changelog ***
|
2 |
+
2019-06-27 - Version 1.9.15
|
3 |
+
* CSRF handling for Ajax calls like ajax_woo_infobanner_post_click, ajax_woo_infobanner_post_xout, ajax_fb_toggle_visibility
|
4 |
+
* use phpcs to adhere to WP coding standards
|
5 |
+
* Minor UI changes on the iFrame
|
6 |
+
|
7 |
2019-06-20 - Version 1.9.14
|
8 |
* Revisit CSRF security issue
|
9 |
* Remove rest controller which is not used
|
facebook-commerce-events-tracker.php
CHANGED
@@ -8,379 +8,426 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
-
if (!class_exists('WC_Facebookcommerce_EventsTracker')) :
|
12 |
-
|
13 |
-
if (!class_exists('WC_Facebookcommerce_Utils')) {
|
14 |
-
|
15 |
-
}
|
16 |
-
|
17 |
-
if (!class_exists('WC_Facebookcommerce_Pixel')) {
|
18 |
-
|
19 |
-
}
|
20 |
-
|
21 |
-
class WC_Facebookcommerce_EventsTracker {
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
385 |
|
386 |
endif;
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
12 |
+
|
13 |
+
if ( ! class_exists( 'WC_Facebookcommerce_Utils' ) ) {
|
14 |
+
include_once 'includes/fbutils.php';
|
15 |
+
}
|
16 |
+
|
17 |
+
if ( ! class_exists( 'WC_Facebookcommerce_Pixel' ) ) {
|
18 |
+
include_once 'facebook-commerce-pixel-event.php';
|
19 |
+
}
|
20 |
+
|
21 |
+
class WC_Facebookcommerce_EventsTracker {
|
22 |
+
private $pixel;
|
23 |
+
private static $isEnabled = true;
|
24 |
+
const FB_PRIORITY_HIGH = 2;
|
25 |
+
const FB_PRIORITY_LOW = 11;
|
26 |
+
|
27 |
+
public function __construct( $user_info ) {
|
28 |
+
$this->pixel = new WC_Facebookcommerce_Pixel( $user_info );
|
29 |
+
|
30 |
+
add_action( 'wp_head', array( $this, 'apply_filters' ) );
|
31 |
+
|
32 |
+
// Pixel Tracking Hooks
|
33 |
+
add_action(
|
34 |
+
'wp_head',
|
35 |
+
array( $this, 'inject_base_pixel' )
|
36 |
+
);
|
37 |
+
add_action(
|
38 |
+
'wp_footer',
|
39 |
+
array( $this, 'inject_base_pixel_noscript' )
|
40 |
+
);
|
41 |
+
add_action(
|
42 |
+
'woocommerce_after_single_product',
|
43 |
+
array( $this, 'inject_view_content_event' ),
|
44 |
+
self::FB_PRIORITY_HIGH
|
45 |
+
);
|
46 |
+
add_action(
|
47 |
+
'woocommerce_after_shop_loop',
|
48 |
+
array( $this, 'inject_view_category_event' )
|
49 |
+
);
|
50 |
+
add_action(
|
51 |
+
'pre_get_posts',
|
52 |
+
array( $this, 'inject_search_event' )
|
53 |
+
);
|
54 |
+
add_action(
|
55 |
+
'woocommerce_after_cart',
|
56 |
+
array( $this, 'inject_add_to_cart_redirect_event' )
|
57 |
+
);
|
58 |
+
add_action(
|
59 |
+
'woocommerce_add_to_cart',
|
60 |
+
array( $this, 'inject_add_to_cart_event' ),
|
61 |
+
self::FB_PRIORITY_HIGH
|
62 |
+
);
|
63 |
+
add_action(
|
64 |
+
'wc_ajax_fb_inject_add_to_cart_event',
|
65 |
+
array( $this, 'inject_ajax_add_to_cart_event' ),
|
66 |
+
self::FB_PRIORITY_HIGH
|
67 |
+
);
|
68 |
+
add_action(
|
69 |
+
'woocommerce_after_checkout_form',
|
70 |
+
array( $this, 'inject_initiate_checkout_event' )
|
71 |
+
);
|
72 |
+
add_action(
|
73 |
+
'woocommerce_thankyou',
|
74 |
+
array( $this, 'inject_gateway_purchase_event' ),
|
75 |
+
self::FB_PRIORITY_HIGH
|
76 |
+
);
|
77 |
+
add_action(
|
78 |
+
'woocommerce_payment_complete',
|
79 |
+
array( $this, 'inject_purchase_event' ),
|
80 |
+
self::FB_PRIORITY_HIGH
|
81 |
+
);
|
82 |
+
add_action(
|
83 |
+
'wpcf7_contact_form',
|
84 |
+
array( $this, 'inject_lead_event_hook' ),
|
85 |
+
self::FB_PRIORITY_LOW
|
86 |
+
);
|
87 |
+
|
88 |
+
}
|
89 |
+
|
90 |
+
public function apply_filters() {
|
91 |
+
self::$isEnabled = apply_filters(
|
92 |
+
'facebook_for_woocommerce_integration_pixel_enabled',
|
93 |
+
self::$isEnabled
|
94 |
+
);
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Base pixel code to be injected on page head. Because of this, it's better
|
99 |
+
* to echo the return value than using
|
100 |
+
* WC_Facebookcommerce_Utils::wc_enqueue_js() in this case
|
101 |
+
*/
|
102 |
+
public function inject_base_pixel() {
|
103 |
+
if ( self::$isEnabled ) {
|
104 |
+
echo $this->pixel->pixel_base_code();
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Base pixel noscript to be injected on page body. This is to avoid W3
|
110 |
+
* validation error.
|
111 |
+
*/
|
112 |
+
public function inject_base_pixel_noscript() {
|
113 |
+
if ( self::$isEnabled ) {
|
114 |
+
echo $this->pixel->pixel_base_code_noscript();
|
115 |
+
}
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Triggers ViewCategory for product category listings
|
120 |
+
*/
|
121 |
+
public function inject_view_category_event() {
|
122 |
+
global $wp_query;
|
123 |
+
if ( ! self::$isEnabled ) {
|
124 |
+
return;
|
125 |
+
}
|
126 |
+
|
127 |
+
$products = array_values(
|
128 |
+
array_map(
|
129 |
+
function( $item ) {
|
130 |
+
return wc_get_product( $item->ID );
|
131 |
+
},
|
132 |
+
$wp_query->posts
|
133 |
+
)
|
134 |
+
);
|
135 |
+
|
136 |
+
// if any product is a variant, fire the pixel with
|
137 |
+
// content_type: product_group
|
138 |
+
$content_type = 'product';
|
139 |
+
$product_ids = array();
|
140 |
+
foreach ( $products as $product ) {
|
141 |
+
if ( ! $product ) {
|
142 |
+
continue;
|
143 |
+
}
|
144 |
+
$product_ids = array_merge(
|
145 |
+
$product_ids,
|
146 |
+
WC_Facebookcommerce_Utils::get_fb_content_ids( $product )
|
147 |
+
);
|
148 |
+
if ( WC_Facebookcommerce_Utils::is_variable_type( $product->get_type() ) ) {
|
149 |
+
$content_type = 'product_group';
|
150 |
+
}
|
151 |
+
}
|
152 |
+
|
153 |
+
$categories =
|
154 |
+
WC_Facebookcommerce_Utils::get_product_categories( get_the_ID() );
|
155 |
+
|
156 |
+
$this->pixel->inject_event(
|
157 |
+
'ViewCategory',
|
158 |
+
array(
|
159 |
+
'content_name' => $categories['name'],
|
160 |
+
'content_category' => $categories['categories'],
|
161 |
+
'content_ids' => json_encode( array_slice( $product_ids, 0, 10 ) ),
|
162 |
+
'content_type' => $content_type,
|
163 |
+
),
|
164 |
+
'trackCustom'
|
165 |
+
);
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Triggers Search for result pages (deduped)
|
170 |
+
*/
|
171 |
+
public function inject_search_event() {
|
172 |
+
if ( ! self::$isEnabled ) {
|
173 |
+
return;
|
174 |
+
}
|
175 |
+
|
176 |
+
if ( ! is_admin() && is_search() && get_search_query() !== '' ) {
|
177 |
+
if ( $this->pixel->check_last_event( 'Search' ) ) {
|
178 |
+
return;
|
179 |
+
}
|
180 |
+
|
181 |
+
if ( WC_Facebookcommerce_Utils::isWoocommerceIntegration() ) {
|
182 |
+
$this->actually_inject_search_event();
|
183 |
+
} else {
|
184 |
+
add_action( 'wp_head', array( $this, 'actually_inject_search_event' ), 11 );
|
185 |
+
}
|
186 |
+
}
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Triggers Search for result pages
|
191 |
+
*/
|
192 |
+
public function actually_inject_search_event() {
|
193 |
+
if ( ! self::$isEnabled ) {
|
194 |
+
return;
|
195 |
+
}
|
196 |
+
|
197 |
+
$this->pixel->inject_event(
|
198 |
+
'Search',
|
199 |
+
array(
|
200 |
+
'search_string' => get_search_query(),
|
201 |
+
)
|
202 |
+
);
|
203 |
+
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Helper function to iterate through a cart and gather all content ids
|
207 |
+
*/
|
208 |
+
private function get_content_ids_from_cart( $cart ) {
|
209 |
+
$product_ids = array();
|
210 |
+
foreach ( $cart as $item ) {
|
211 |
+
$product_ids = array_merge(
|
212 |
+
$product_ids,
|
213 |
+
WC_Facebookcommerce_Utils::get_fb_content_ids( $item['data'] )
|
214 |
+
);
|
215 |
+
}
|
216 |
+
return $product_ids;
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Triggers ViewContent product pages
|
221 |
+
*/
|
222 |
+
public function inject_view_content_event() {
|
223 |
+
if ( ! self::$isEnabled ) {
|
224 |
+
return;
|
225 |
+
}
|
226 |
+
global $post;
|
227 |
+
$product = wc_get_product( $post->ID );
|
228 |
+
$content_type = 'product_group';
|
229 |
+
if ( ! $product ) {
|
230 |
+
return;
|
231 |
+
}
|
232 |
+
|
233 |
+
// if product is a variant, fire the pixel with content_type: product_group
|
234 |
+
if ( WC_Facebookcommerce_Utils::is_variation_type( $product->get_type() ) ) {
|
235 |
+
$content_type = 'product';
|
236 |
+
}
|
237 |
+
|
238 |
+
$content_ids = WC_Facebookcommerce_Utils::get_fb_content_ids( $product );
|
239 |
+
$this->pixel->inject_event(
|
240 |
+
'ViewContent',
|
241 |
+
array(
|
242 |
+
'content_name' => $product->get_title(),
|
243 |
+
'content_ids' => json_encode( $content_ids ),
|
244 |
+
'content_type' => $content_type,
|
245 |
+
'value' => $product->get_price(),
|
246 |
+
'currency' => get_woocommerce_currency(),
|
247 |
+
)
|
248 |
+
);
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Triggers AddToCart for cart page and add_to_cart button clicks
|
253 |
+
*/
|
254 |
+
public function inject_add_to_cart_event() {
|
255 |
+
if ( ! self::$isEnabled ) {
|
256 |
+
return;
|
257 |
+
}
|
258 |
+
|
259 |
+
$product_ids = $this->get_content_ids_from_cart( WC()->cart->get_cart() );
|
260 |
+
|
261 |
+
$this->pixel->inject_event(
|
262 |
+
'AddToCart',
|
263 |
+
array(
|
264 |
+
'content_ids' => json_encode( $product_ids ),
|
265 |
+
'content_type' => 'product',
|
266 |
+
'value' => WC()->cart->total,
|
267 |
+
'currency' => get_woocommerce_currency(),
|
268 |
+
)
|
269 |
+
);
|
270 |
+
}
|
271 |
+
|
272 |
+
/**
|
273 |
+
* Triggered by add_to_cart jquery trigger
|
274 |
+
*/
|
275 |
+
public function inject_ajax_add_to_cart_event() {
|
276 |
+
if ( ! self::$isEnabled ) {
|
277 |
+
return;
|
278 |
+
}
|
279 |
+
|
280 |
+
ob_start();
|
281 |
+
|
282 |
+
echo '<script>';
|
283 |
+
|
284 |
+
$product_ids = $this->get_content_ids_from_cart( WC()->cart->get_cart() );
|
285 |
+
|
286 |
+
echo $this->pixel->build_event(
|
287 |
+
'AddToCart',
|
288 |
+
array(
|
289 |
+
'content_ids' => json_encode( $product_ids ),
|
290 |
+
'content_type' => 'product',
|
291 |
+
'value' => WC()->cart->total,
|
292 |
+
'currency' => get_woocommerce_currency(),
|
293 |
+
)
|
294 |
+
);
|
295 |
+
echo '</script>';
|
296 |
+
|
297 |
+
$pixel = ob_get_clean();
|
298 |
+
|
299 |
+
wp_send_json( $pixel );
|
300 |
+
}
|
301 |
+
|
302 |
+
/**
|
303 |
+
* Trigger AddToCart for cart page and woocommerce_after_cart hook.
|
304 |
+
* When set 'redirect to cart', ajax call for button click and
|
305 |
+
* woocommerce_add_to_cart will be skipped.
|
306 |
+
*/
|
307 |
+
public function inject_add_to_cart_redirect_event() {
|
308 |
+
if ( ! self::$isEnabled ) {
|
309 |
+
return;
|
310 |
+
}
|
311 |
+
$redirect_checked = get_option( 'woocommerce_cart_redirect_after_add', 'no' );
|
312 |
+
if ( $redirect_checked == 'yes' ) {
|
313 |
+
$this->inject_add_to_cart_event();
|
314 |
+
}
|
315 |
+
}
|
316 |
+
|
317 |
+
/**
|
318 |
+
* Triggers InitiateCheckout for checkout page
|
319 |
+
*/
|
320 |
+
public function inject_initiate_checkout_event() {
|
321 |
+
if ( ! self::$isEnabled ||
|
322 |
+
$this->pixel->check_last_event( 'InitiateCheckout' ) ) {
|
323 |
+
return;
|
324 |
+
}
|
325 |
+
|
326 |
+
$product_ids = $this->get_content_ids_from_cart( WC()->cart->get_cart() );
|
327 |
+
|
328 |
+
$this->pixel->inject_event(
|
329 |
+
'InitiateCheckout',
|
330 |
+
array(
|
331 |
+
'num_items' => WC()->cart->get_cart_contents_count(),
|
332 |
+
'content_ids' => json_encode( $product_ids ),
|
333 |
+
'content_type' => 'product',
|
334 |
+
'value' => WC()->cart->total,
|
335 |
+
'currency' => get_woocommerce_currency(),
|
336 |
+
)
|
337 |
+
);
|
338 |
+
}
|
339 |
+
|
340 |
+
/**
|
341 |
+
* Triggers Purchase for payment transaction complete and for the thank you
|
342 |
+
* page in cases of delayed payment.
|
343 |
+
*/
|
344 |
+
public function inject_purchase_event( $order_id ) {
|
345 |
+
if ( ! self::$isEnabled ||
|
346 |
+
$this->pixel->check_last_event( 'Purchase' ) ) {
|
347 |
+
return;
|
348 |
+
}
|
349 |
+
|
350 |
+
$this->inject_subscribe_event( $order_id );
|
351 |
+
|
352 |
+
$order = new WC_Order( $order_id );
|
353 |
+
$content_type = 'product';
|
354 |
+
$product_ids = array();
|
355 |
+
foreach ( $order->get_items() as $item ) {
|
356 |
+
$product = wc_get_product( $item['product_id'] );
|
357 |
+
$product_ids = array_merge(
|
358 |
+
$product_ids,
|
359 |
+
WC_Facebookcommerce_Utils::get_fb_content_ids( $product )
|
360 |
+
);
|
361 |
+
if ( WC_Facebookcommerce_Utils::is_variable_type( $product->get_type() ) ) {
|
362 |
+
$content_type = 'product_group';
|
363 |
+
}
|
364 |
+
}
|
365 |
+
|
366 |
+
$this->pixel->inject_event(
|
367 |
+
'Purchase',
|
368 |
+
array(
|
369 |
+
'content_ids' => json_encode( $product_ids ),
|
370 |
+
'content_type' => $content_type,
|
371 |
+
'value' => $order->get_total(),
|
372 |
+
'currency' => get_woocommerce_currency(),
|
373 |
+
)
|
374 |
+
);
|
375 |
+
}
|
376 |
+
|
377 |
+
/**
|
378 |
+
* Triggers Subscribe for payment transaction complete of purchase with
|
379 |
+
* subscription.
|
380 |
+
*/
|
381 |
+
public function inject_subscribe_event( $order_id ) {
|
382 |
+
if ( ! function_exists( 'wcs_get_subscriptions_for_order' ) ) {
|
383 |
+
return;
|
384 |
+
}
|
385 |
+
|
386 |
+
$subscription_ids = wcs_get_subscriptions_for_order( $order_id );
|
387 |
+
foreach ( $subscription_ids as $subscription_id ) {
|
388 |
+
$subscription = new WC_Subscription( $subscription_id );
|
389 |
+
$this->pixel->inject_event(
|
390 |
+
'Subscribe',
|
391 |
+
array(
|
392 |
+
'sign_up_fee' => $subscription->get_sign_up_fee(),
|
393 |
+
'value' => $subscription->get_total(),
|
394 |
+
'currency' => get_woocommerce_currency(),
|
395 |
+
)
|
396 |
+
);
|
397 |
+
}
|
398 |
+
}
|
399 |
+
|
400 |
+
/**
|
401 |
+
* Triggers Purchase for thank you page for COD, BACS CHEQUE payment
|
402 |
+
* which won't invoke woocommerce_payment_complete.
|
403 |
+
*/
|
404 |
+
public function inject_gateway_purchase_event( $order_id ) {
|
405 |
+
if ( ! self::$isEnabled ||
|
406 |
+
$this->pixel->check_last_event( 'Purchase' ) ) {
|
407 |
+
return;
|
408 |
+
}
|
409 |
+
|
410 |
+
$order = new WC_Order( $order_id );
|
411 |
+
$payment = $order->get_payment_method();
|
412 |
+
$this->inject_purchase_event( $order_id );
|
413 |
+
$this->inject_subscribe_event( $order_id );
|
414 |
+
}
|
415 |
+
|
416 |
+
/** Contact Form 7 Support **/
|
417 |
+
public function inject_lead_event_hook() {
|
418 |
+
add_action( 'wp_footer', array( $this, 'inject_lead_event' ), 11 );
|
419 |
+
}
|
420 |
+
|
421 |
+
public function inject_lead_event() {
|
422 |
+
if ( ! is_admin() ) {
|
423 |
+
$this->pixel->inject_conditional_event(
|
424 |
+
'Lead',
|
425 |
+
array(),
|
426 |
+
'wpcf7submit',
|
427 |
+
'{ em: event.detail.inputs.filter(ele => ele.name.includes("email"))[0].value }'
|
428 |
+
);
|
429 |
+
}
|
430 |
+
}
|
431 |
+
}
|
432 |
|
433 |
endif;
|
facebook-commerce-messenger-chat.php
CHANGED
@@ -8,45 +8,46 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
-
if (!class_exists('WC_Facebookcommerce_MessengerChat')) :
|
12 |
|
13 |
-
if (!class_exists('WC_Facebookcommerce_Utils')) {
|
14 |
-
|
15 |
-
}
|
16 |
|
17 |
-
class WC_Facebookcommerce_MessengerChat {
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
|
44 |
-
|
45 |
-
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
|
|
|
50 |
attribution=\"fbe_woocommerce\"
|
51 |
class=\"fb-customerchat\"
|
52 |
page_id=\"%s\"
|
@@ -73,15 +74,16 @@ class WC_Facebookcommerce_MessengerChat {
|
|
73 |
}(document, 'script', 'facebook-jssdk'));
|
74 |
</script>
|
75 |
<div></div>",
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
|
|
84 |
|
85 |
-
}
|
86 |
|
87 |
endif;
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
if ( ! class_exists( 'WC_Facebookcommerce_MessengerChat' ) ) :
|
12 |
|
13 |
+
if ( ! class_exists( 'WC_Facebookcommerce_Utils' ) ) {
|
14 |
+
include_once 'includes/fbutils.php';
|
15 |
+
}
|
16 |
|
17 |
+
class WC_Facebookcommerce_MessengerChat {
|
18 |
|
19 |
+
public function __construct( $settings ) {
|
20 |
+
$this->enabled = isset( $settings['is_messenger_chat_plugin_enabled'] )
|
21 |
+
? $settings['is_messenger_chat_plugin_enabled']
|
22 |
+
: 'no';
|
23 |
|
24 |
+
$this->page_id = isset( $settings['fb_page_id'] )
|
25 |
+
? $settings['fb_page_id']
|
26 |
+
: '';
|
27 |
|
28 |
+
$this->jssdk_version = isset( $settings['facebook_jssdk_version'] )
|
29 |
+
? $settings['facebook_jssdk_version']
|
30 |
+
: '';
|
31 |
|
32 |
+
$this->greeting_text_code = isset( $settings['msger_chat_customization_greeting_text_code'] )
|
33 |
+
? $settings['msger_chat_customization_greeting_text_code']
|
34 |
+
: null;
|
35 |
|
36 |
+
$this->locale = isset( $settings['msger_chat_customization_locale'] )
|
37 |
+
? $settings['msger_chat_customization_locale']
|
38 |
+
: null;
|
39 |
|
40 |
+
$this->theme_color_code = isset( $settings['msger_chat_customization_theme_color_code'] )
|
41 |
+
? $settings['msger_chat_customization_theme_color_code']
|
42 |
+
: null;
|
43 |
|
44 |
+
add_action( 'wp_footer', array( $this, 'inject_messenger_chat_plugin' ) );
|
45 |
+
}
|
46 |
|
47 |
+
public function inject_messenger_chat_plugin() {
|
48 |
+
if ( $this->enabled === 'yes' ) {
|
49 |
+
echo sprintf(
|
50 |
+
"<div
|
51 |
attribution=\"fbe_woocommerce\"
|
52 |
class=\"fb-customerchat\"
|
53 |
page_id=\"%s\"
|
74 |
}(document, 'script', 'facebook-jssdk'));
|
75 |
</script>
|
76 |
<div></div>",
|
77 |
+
$this->page_id,
|
78 |
+
$this->theme_color_code ? sprintf( 'theme_color="%s"', $this->theme_color_code ) : '',
|
79 |
+
$this->greeting_text_code ? sprintf( 'logged_in_greeting="%s"', $this->greeting_text_code ) : '',
|
80 |
+
$this->greeting_text_code ? sprintf( 'logged_out_greeting="%s"', $this->greeting_text_code ) : '',
|
81 |
+
$this->jssdk_version,
|
82 |
+
$this->locale ? $this->locale : 'en_US'
|
83 |
+
);
|
84 |
+
}
|
85 |
+
}
|
86 |
|
87 |
+
}
|
88 |
|
89 |
endif;
|
facebook-commerce-pixel-event.php
CHANGED
@@ -8,22 +8,22 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
-
if (!class_exists('WC_Facebookcommerce_Pixel')) :
|
12 |
|
13 |
|
14 |
-
class WC_Facebookcommerce_Pixel {
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
|
19 |
-
|
20 |
-
|
21 |
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
|
26 |
-
|
27 |
<script type='text/javascript'>
|
28 |
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
|
29 |
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
|
@@ -33,61 +33,62 @@ document,'script','https://connect.facebook.net/en_US/fbevents.js');
|
|
33 |
</script>
|
34 |
";
|
35 |
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
|
|
91 |
<!-- %s Facebook Integration Begin -->
|
92 |
%s
|
93 |
<script>
|
@@ -109,55 +110,59 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
109 |
<!-- DO NOT MODIFY -->
|
110 |
<!-- %s Facebook Integration end -->
|
111 |
",
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
|
|
|
|
138 |
<!-- Facebook Pixel Event Code -->
|
139 |
<script>
|
140 |
%s
|
141 |
</script>
|
142 |
<!-- End Facebook Pixel Event Code -->
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
|
|
|
|
161 |
<!-- Facebook Pixel Event Code -->
|
162 |
<script>
|
163 |
document.addEventListener('%s', function (event) {
|
@@ -166,158 +171,171 @@ document.addEventListener('%s', function (event) {
|
|
166 |
</script>
|
167 |
<!-- End Facebook Pixel Event Code -->
|
168 |
",
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
|
|
|
|
192 |
<!-- Facebook Pixel Code -->
|
193 |
<noscript>
|
194 |
-
<img height
|
195 |
-
src
|
196 |
</noscript>
|
197 |
<!-- DO NOT MODIFY -->
|
198 |
<!-- End Facebook Pixel Code -->
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
322 |
|
323 |
endif;
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
if ( ! class_exists( 'WC_Facebookcommerce_Pixel' ) ) :
|
12 |
|
13 |
|
14 |
+
class WC_Facebookcommerce_Pixel {
|
15 |
+
const SETTINGS_KEY = 'facebook_config';
|
16 |
+
const PIXEL_ID_KEY = 'pixel_id';
|
17 |
+
const USE_PII_KEY = 'use_pii';
|
18 |
|
19 |
+
const PIXEL_RENDER = 'pixel_render';
|
20 |
+
const NO_SCRIPT_RENDER = 'no_script_render';
|
21 |
|
22 |
+
private $user_info;
|
23 |
+
private $last_event;
|
24 |
+
static $render_cache = array();
|
25 |
|
26 |
+
static $default_pixel_basecode = "
|
27 |
<script type='text/javascript'>
|
28 |
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
|
29 |
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
|
33 |
</script>
|
34 |
";
|
35 |
|
36 |
+
public function __construct( $user_info = array() ) {
|
37 |
+
$this->user_info = $user_info;
|
38 |
+
$this->last_event = '';
|
39 |
+
}
|
40 |
+
|
41 |
+
public static function initialize() {
|
42 |
+
if ( ! is_admin() ) {
|
43 |
+
return;
|
44 |
+
}
|
45 |
+
|
46 |
+
// Initialize PixelID in storage - this will only need to happen when the
|
47 |
+
// user is an admin
|
48 |
+
$pixel_id = self::get_pixel_id();
|
49 |
+
if ( ! WC_Facebookcommerce_Utils::is_valid_id( $pixel_id ) &&
|
50 |
+
class_exists( 'WC_Facebookcommerce_WarmConfig' ) ) {
|
51 |
+
$fb_warm_pixel_id = WC_Facebookcommerce_WarmConfig::$fb_warm_pixel_id;
|
52 |
+
|
53 |
+
if ( WC_Facebookcommerce_Utils::is_valid_id( $fb_warm_pixel_id ) &&
|
54 |
+
(int) $fb_warm_pixel_id == $fb_warm_pixel_id ) {
|
55 |
+
$fb_warm_pixel_id = (string) $fb_warm_pixel_id;
|
56 |
+
self::set_pixel_id( $fb_warm_pixel_id );
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
$is_advanced_matching_enabled = self::get_use_pii_key();
|
61 |
+
if ( $is_advanced_matching_enabled == null &&
|
62 |
+
class_exists( 'WC_Facebookcommerce_WarmConfig' ) ) {
|
63 |
+
$fb_warm_is_advanced_matching_enabled =
|
64 |
+
WC_Facebookcommerce_WarmConfig::$fb_warm_is_advanced_matching_enabled;
|
65 |
+
if ( is_bool( $fb_warm_is_advanced_matching_enabled ) ) {
|
66 |
+
self::set_use_pii_key( $fb_warm_is_advanced_matching_enabled ? 1 : 0 );
|
67 |
+
}
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Returns FB pixel code script part
|
73 |
+
*/
|
74 |
+
public function pixel_base_code() {
|
75 |
+
$pixel_id = self::get_pixel_id();
|
76 |
+
if (
|
77 |
+
(
|
78 |
+
isset( self::$render_cache[ self::PIXEL_RENDER ] ) &&
|
79 |
+
self::$render_cache[ self::PIXEL_RENDER ] === true
|
80 |
+
) ||
|
81 |
+
! isset( $pixel_id ) ||
|
82 |
+
$pixel_id === 0
|
83 |
+
) {
|
84 |
+
return;
|
85 |
+
}
|
86 |
+
|
87 |
+
self::$render_cache[ self::PIXEL_RENDER ] = true;
|
88 |
+
$params = self::add_version_info();
|
89 |
+
|
90 |
+
return sprintf(
|
91 |
+
"
|
92 |
<!-- %s Facebook Integration Begin -->
|
93 |
%s
|
94 |
<script>
|
110 |
<!-- DO NOT MODIFY -->
|
111 |
<!-- %s Facebook Integration end -->
|
112 |
",
|
113 |
+
WC_Facebookcommerce_Utils::getIntegrationName(),
|
114 |
+
self::get_basecode(),
|
115 |
+
$this->pixel_init_code(),
|
116 |
+
json_encode( $params, JSON_PRETTY_PRINT | JSON_FORCE_OBJECT ),
|
117 |
+
WC_Facebookcommerce_Utils::getIntegrationName()
|
118 |
+
);
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Prevent double-fires by checking the last event
|
123 |
+
*/
|
124 |
+
public function check_last_event( $event_name ) {
|
125 |
+
return $event_name === $this->last_event;
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Preferred method to inject events in a page, normally you should use this
|
130 |
+
* instead of WC_Facebookcommerce_Pixel::build_event()
|
131 |
+
*/
|
132 |
+
public function inject_event( $event_name, $params, $method = 'track' ) {
|
133 |
+
$code = self::build_event( $event_name, $params, $method );
|
134 |
+
$this->last_event = $event_name;
|
135 |
+
|
136 |
+
if ( WC_Facebookcommerce_Utils::isWoocommerceIntegration() ) {
|
137 |
+
WC_Facebookcommerce_Utils::wc_enqueue_js( $code );
|
138 |
+
} else {
|
139 |
+
printf(
|
140 |
+
'
|
141 |
<!-- Facebook Pixel Event Code -->
|
142 |
<script>
|
143 |
%s
|
144 |
</script>
|
145 |
<!-- End Facebook Pixel Event Code -->
|
146 |
+
',
|
147 |
+
$code
|
148 |
+
);
|
149 |
+
}
|
150 |
+
}
|
151 |
+
|
152 |
+
public function inject_conditional_event(
|
153 |
+
$event_name, $params, $listener, $jsonified_pii = '' ) {
|
154 |
+
$code = self::build_event( $event_name, $params, 'track' );
|
155 |
+
$this->last_event = $event_name;
|
156 |
+
|
157 |
+
// Prepends fbq(...) with pii information to the injected code.
|
158 |
+
if ( $jsonified_pii && get_option( self::SETTINGS_KEY )[ self::USE_PII_KEY ] ) {
|
159 |
+
$this->user_info = '%s';
|
160 |
+
$code =
|
161 |
+
sprintf( $this->pixel_init_code(), '" || ' . $jsonified_pii . ' || "' ) . $code;
|
162 |
+
}
|
163 |
+
|
164 |
+
printf(
|
165 |
+
"
|
166 |
<!-- Facebook Pixel Event Code -->
|
167 |
<script>
|
168 |
document.addEventListener('%s', function (event) {
|
171 |
</script>
|
172 |
<!-- End Facebook Pixel Event Code -->
|
173 |
",
|
174 |
+
$listener,
|
175 |
+
$code
|
176 |
+
);
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Returns FB pixel code noscript part to avoid W3 validation error
|
181 |
+
*/
|
182 |
+
public function pixel_base_code_noscript() {
|
183 |
+
$pixel_id = self::get_pixel_id();
|
184 |
+
if (
|
185 |
+
(
|
186 |
+
isset( self::$render_cache[ self::NO_SCRIPT_RENDER ] ) &&
|
187 |
+
self::$render_cache[ self::NO_SCRIPT_RENDER ] === true
|
188 |
+
) ||
|
189 |
+
! isset( $pixel_id ) ||
|
190 |
+
$pixel_id === 0
|
191 |
+
) {
|
192 |
+
return;
|
193 |
+
}
|
194 |
+
|
195 |
+
self::$render_cache[ self::NO_SCRIPT_RENDER ] = true;
|
196 |
+
|
197 |
+
return sprintf(
|
198 |
+
'
|
199 |
<!-- Facebook Pixel Code -->
|
200 |
<noscript>
|
201 |
+
<img height="1" width="1" style="display:none" alt="fbpx"
|
202 |
+
src="https://www.facebook.com/tr?id=%s&ev=PageView&noscript=1"/>
|
203 |
</noscript>
|
204 |
<!-- DO NOT MODIFY -->
|
205 |
<!-- End Facebook Pixel Code -->
|
206 |
+
',
|
207 |
+
esc_js( $pixel_id )
|
208 |
+
);
|
209 |
+
}
|
210 |
+
|
211 |
+
/**
|
212 |
+
* You probably should use WC_Facebookcommerce_Pixel::inject_event() but
|
213 |
+
* this method is available if you need to modify the JS code somehow
|
214 |
+
*/
|
215 |
+
public static function build_event( $event_name, $params, $method = 'track' ) {
|
216 |
+
$params = self::add_version_info( $params );
|
217 |
+
return sprintf(
|
218 |
+
"/* %s Facebook Integration Event Tracking */\n" .
|
219 |
+
"fbq('%s', '%s', %s);",
|
220 |
+
WC_Facebookcommerce_Utils::getIntegrationName(),
|
221 |
+
$method,
|
222 |
+
$event_name,
|
223 |
+
json_encode( $params, JSON_PRETTY_PRINT | JSON_FORCE_OBJECT )
|
224 |
+
);
|
225 |
+
}
|
226 |
+
|
227 |
+
public static function get_pixel_id() {
|
228 |
+
$fb_options = self::get_options();
|
229 |
+
if ( ! $fb_options ) {
|
230 |
+
return '';
|
231 |
+
}
|
232 |
+
return isset( $fb_options[ self::PIXEL_ID_KEY ] ) ?
|
233 |
+
$fb_options[ self::PIXEL_ID_KEY ] : '';
|
234 |
+
}
|
235 |
+
|
236 |
+
public static function set_pixel_id( $pixel_id ) {
|
237 |
+
$fb_options = self::get_options();
|
238 |
+
|
239 |
+
if ( isset( $fb_options[ self::PIXEL_ID_KEY ] )
|
240 |
+
&& $fb_options[ self::PIXEL_ID_KEY ] == $pixel_id ) {
|
241 |
+
return;
|
242 |
+
}
|
243 |
+
|
244 |
+
$fb_options[ self::PIXEL_ID_KEY ] = $pixel_id;
|
245 |
+
update_option( self::SETTINGS_KEY, $fb_options );
|
246 |
+
}
|
247 |
+
|
248 |
+
public static function get_use_pii_key() {
|
249 |
+
$fb_options = self::get_options();
|
250 |
+
if ( ! $fb_options ) {
|
251 |
+
return null;
|
252 |
+
}
|
253 |
+
return isset( $fb_options[ self::USE_PII_KEY ] ) ?
|
254 |
+
$fb_options[ self::USE_PII_KEY ] : null;
|
255 |
+
}
|
256 |
+
|
257 |
+
public static function set_use_pii_key( $use_pii ) {
|
258 |
+
$fb_options = self::get_options();
|
259 |
+
|
260 |
+
if ( isset( $fb_options[ self::USE_PII_KEY ] )
|
261 |
+
&& $fb_options[ self::USE_PII_KEY ] == $use_pii ) {
|
262 |
+
return;
|
263 |
+
}
|
264 |
+
|
265 |
+
$fb_options[ self::USE_PII_KEY ] = $use_pii;
|
266 |
+
update_option( self::SETTINGS_KEY, $fb_options );
|
267 |
+
}
|
268 |
+
|
269 |
+
public static function get_basecode() {
|
270 |
+
return self::$default_pixel_basecode;
|
271 |
+
}
|
272 |
+
|
273 |
+
private static function get_version_info() {
|
274 |
+
global $wp_version;
|
275 |
+
|
276 |
+
if ( WC_Facebookcommerce_Utils::isWoocommerceIntegration() ) {
|
277 |
+
return array(
|
278 |
+
'source' => 'woocommerce',
|
279 |
+
'version' => WC()->version,
|
280 |
+
'pluginVersion' => WC_Facebookcommerce_Utils::PLUGIN_VERSION,
|
281 |
+
);
|
282 |
+
}
|
283 |
+
|
284 |
+
return array(
|
285 |
+
'source' => 'wordpress',
|
286 |
+
'version' => $wp_version,
|
287 |
+
'pluginVersion' => WC_Facebookcommerce_Utils::PLUGIN_VERSION,
|
288 |
+
);
|
289 |
+
}
|
290 |
+
|
291 |
+
public static function get_options() {
|
292 |
+
return get_option(
|
293 |
+
self::SETTINGS_KEY,
|
294 |
+
array(
|
295 |
+
self::PIXEL_ID_KEY => '0',
|
296 |
+
self::USE_PII_KEY => 0,
|
297 |
+
)
|
298 |
+
);
|
299 |
+
}
|
300 |
+
|
301 |
+
/**
|
302 |
+
* Returns an array with version_info for pixel fires. Parameters provided by
|
303 |
+
* users should not be overwritten by this function
|
304 |
+
*/
|
305 |
+
private static function add_version_info( $params = array() ) {
|
306 |
+
// if any parameter is passed in the pixel, do not overwrite it
|
307 |
+
return array_replace( self::get_version_info(), $params );
|
308 |
+
}
|
309 |
+
|
310 |
+
/**
|
311 |
+
* Init code might contain additional information to help matching website
|
312 |
+
* users with facebook users. Information is hashed in JS side using SHA256
|
313 |
+
* before sending to Facebook.
|
314 |
+
*/
|
315 |
+
private function pixel_init_code() {
|
316 |
+
$version_info = self::get_version_info();
|
317 |
+
$agent_string = sprintf(
|
318 |
+
'%s-%s-%s',
|
319 |
+
$version_info['source'],
|
320 |
+
$version_info['version'],
|
321 |
+
$version_info['pluginVersion']
|
322 |
+
);
|
323 |
+
|
324 |
+
$params = array(
|
325 |
+
'agent' => $agent_string,
|
326 |
+
);
|
327 |
+
|
328 |
+
return apply_filters(
|
329 |
+
'facebook_woocommerce_pixel_init',
|
330 |
+
sprintf(
|
331 |
+
"fbq('init', '%s', %s, %s);\n",
|
332 |
+
esc_js( self::get_pixel_id() ),
|
333 |
+
json_encode( $this->user_info, JSON_PRETTY_PRINT | JSON_FORCE_OBJECT ),
|
334 |
+
json_encode( $params, JSON_PRETTY_PRINT | JSON_FORCE_OBJECT )
|
335 |
+
)
|
336 |
+
);
|
337 |
+
}
|
338 |
+
|
339 |
+
}
|
340 |
|
341 |
endif;
|
facebook-commerce.php
CHANGED
@@ -8,2536 +8,2928 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
-
if (!defined('ABSPATH'))
|
|
|
|
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
|
17 |
class WC_Facebookcommerce_Integration extends WC_Integration {
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
511 |
checkout URL that may be different than your shop checkout URL.
|
512 |
<a href="' . WOOCOMMERCE_FACEBOOK_PLUGIN_SETTINGS_URL . '">
|
513 |
-
Re-sync your products to update checkout URLs on Facebook.</a>'
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
'
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
540 |
on Facebook.' :
|
541 |
-
|
542 |
|
543 |
-
|
544 |
-
|
545 |
-
|
|
|
|
|
546 |
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
href="javascript:;" onclick="fb_toggle_visibility(%1$s, true)">Show</a>',
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
|
|
555 |
onclick="fb_toggle_visibility(%1$s, false)">Hide</a>',
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
add_meta_box(
|
567 |
-
'facebook_metabox', // Meta box ID
|
568 |
-
'Facebook', // Meta box Title
|
569 |
-
array($this, 'fb_product_meta_box_html'), // Callback
|
570 |
-
'product', // Screen to which to add the meta box
|
571 |
-
'side' // Context
|
572 |
);
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
if ($fb_product_group_id) {
|
584 |
-
printf('Facebook ID: <a href="https://facebook.com/'.
|
585 |
-
$fb_product_group_id . '" target="_blank">' .
|
586 |
-
$fb_product_group_id . '</a><p/>');
|
587 |
-
if (WC_Facebookcommerce_Utils::is_variable_type($woo_product->get_type())) {
|
588 |
-
printf('<p>Variant IDs:<br/>');
|
589 |
-
$children = $woo_product->get_children();
|
590 |
-
foreach ($children as $child_id) {
|
591 |
-
$fb_product_item_id = $this->get_product_fbid(
|
592 |
-
self::FB_PRODUCT_ITEM_ID,
|
593 |
-
$child_id);
|
594 |
-
printf($child_id .' : <a href="https://facebook.com/'.
|
595 |
-
$fb_product_item_id . '" target="_blank">' .
|
596 |
-
$fb_product_item_id . '</a><br/>');
|
597 |
-
}
|
598 |
-
printf('</p>');
|
599 |
-
}
|
600 |
-
|
601 |
-
$checkbox_value = get_post_meta($post->ID, self::FB_VISIBILITY, true);
|
602 |
-
|
603 |
-
printf('Visible: <input name="%1$s" type="checkbox" value="1" %2$s/>',
|
604 |
-
self::FB_VISIBILITY,
|
605 |
-
$checkbox_value === '' ? '' : 'checked');
|
606 |
-
printf('<p/><input name="is_product_page" type="hidden" value="1"');
|
607 |
-
|
608 |
-
printf(
|
609 |
-
'<p/><a href="#" onclick="fb_reset_product(%1$s)">
|
610 |
-
Reset Facebook metadata</a>',
|
611 |
-
$post->ID);
|
612 |
-
|
613 |
-
printf(
|
614 |
-
'<p/><a href="#" onclick="fb_delete_product(%1$s)">
|
615 |
-
Delete product(s) on Facebook</a>',
|
616 |
-
$post->ID);
|
617 |
-
} else {
|
618 |
-
printf("<b>This product is not yet synced to Facebook.</b>");
|
619 |
-
}
|
620 |
-
printf('</span>');
|
621 |
-
}
|
622 |
-
|
623 |
-
private function get_product_count() {
|
624 |
-
$args = array(
|
625 |
-
'post_type' => 'product',
|
626 |
-
'post_status' => 'publish',
|
627 |
-
'posts_per_page' => -1,
|
628 |
-
'fields' => 'ids'
|
629 |
-
);
|
630 |
-
$products = new WP_Query($args);
|
631 |
-
|
632 |
-
wp_reset_postdata();
|
633 |
-
|
634 |
-
echo $products->found_posts;
|
635 |
-
}
|
636 |
-
|
637 |
-
/**
|
638 |
-
* Load DIA specific JS Data
|
639 |
-
*/
|
640 |
-
public function load_assets() {
|
641 |
-
$screen = get_current_screen();
|
642 |
-
|
643 |
-
// load banner assets
|
644 |
-
wp_enqueue_script('wc_facebook_infobanner_jsx', plugins_url(
|
645 |
-
'/assets/js/facebook-infobanner.js?ts=' . time(), __FILE__));
|
646 |
-
|
647 |
-
wp_enqueue_style('wc_facebook_infobanner_css', plugins_url(
|
648 |
-
'/assets/css/facebook-infobanner.css', __FILE__));
|
649 |
-
|
650 |
-
if (strpos($screen->id , "page_wc-settings") == 0) {
|
651 |
-
return;
|
652 |
-
}
|
653 |
-
|
654 |
-
if (empty($_GET['tab'])) {
|
655 |
-
return;
|
656 |
-
}
|
657 |
-
|
658 |
-
if ('integration' !== $_GET['tab']) {
|
659 |
-
return;
|
660 |
-
}
|
661 |
-
|
662 |
-
?>
|
663 |
-
<script>
|
664 |
-
window.facebookAdsToolboxConfig = {
|
665 |
-
hasGzipSupport:
|
666 |
-
'<?php echo extension_loaded('zlib') ? 'true' : 'false' ?>'
|
667 |
-
,enabledPlugins: ['MESSENGER_CHAT','INSTAGRAM_SHOP', 'PAGE_SHOP']
|
668 |
-
,enableSubscription:
|
669 |
-
'<?php echo class_exists('WC_Subscriptions') ? 'true' : 'false' ?>'
|
670 |
-
,popupOrigin: '<?php echo isset($_GET['url']) ? esc_js($_GET['url']) :
|
671 |
-
'https://www.facebook.com/' ?>'
|
672 |
-
,feedWasDisabled: 'true'
|
673 |
-
,platform: 'WooCommerce'
|
674 |
-
,pixel: {
|
675 |
-
pixelId: '<?php echo $this->pixel_id ?: '' ?>'
|
676 |
-
,advanced_matching_supported: true
|
677 |
-
}
|
678 |
-
,diaSettingId: '<?php echo $this->external_merchant_settings_id ?: '' ?>'
|
679 |
-
,store: {
|
680 |
-
baseUrl: window.location.protocol + '//' + window.location.host
|
681 |
-
,baseCurrency:
|
682 |
-
'<?php echo esc_js(
|
683 |
-
WC_Admin_Settings::get_option('woocommerce_currency'))?>'
|
684 |
-
,timezoneId: '<?php echo date('Z') ?>'
|
685 |
-
,storeName:
|
686 |
-
'<?php echo esc_js(WC_Facebookcommerce_Utils::get_store_name()); ?>'
|
687 |
-
,version: '<?php echo WC()->version ?>'
|
688 |
-
,php_version: '<?php echo PHP_VERSION ?>'
|
689 |
-
,plugin_version:
|
690 |
-
'<?php echo WC_Facebookcommerce_Utils::PLUGIN_VERSION ?>'
|
691 |
-
}
|
692 |
-
,feed: {
|
693 |
-
totalVisibleProducts: '<?php echo $this->get_product_count() ?>'
|
694 |
-
,hasClientSideFeedUpload: '<?php echo !!$this->feed_id ?>'
|
695 |
-
}
|
696 |
-
,feedPrepared: {
|
697 |
-
feedUrl: ''
|
698 |
-
,feedPingUrl: ''
|
699 |
-
,samples: <?php echo $this->get_sample_product_feed()?>
|
700 |
-
}
|
701 |
-
,tokenExpired: '<?php echo $this->settings['fb_api_key'] &&
|
702 |
-
!$this->get_page_name()?>'
|
703 |
-
};
|
704 |
-
</script>
|
705 |
-
<?php
|
706 |
-
$ajax_data = array(
|
707 |
-
'nonce' => wp_create_nonce( 'wc_facebook_settings_jsx' ),
|
708 |
-
);
|
709 |
-
wp_enqueue_script('wc_facebook_settings_jsx', plugins_url(
|
710 |
-
'/assets/js/facebook-settings.js?ts=' . time(), __FILE__));
|
711 |
-
wp_localize_script(
|
712 |
-
'wc_facebook_settings_jsx',
|
713 |
-
'wc_facebook_settings_jsx',
|
714 |
$ajax_data
|
715 |
);
|
716 |
-
wp_enqueue_style('wc_facebook_css', plugins_url(
|
717 |
-
'/assets/css/facebook.css', __FILE__));
|
718 |
-
}
|
719 |
-
|
720 |
-
function on_product_delete($wp_id) {
|
721 |
-
$woo_product = new WC_Facebook_Product($wp_id);
|
722 |
-
if (!$woo_product->exists()) {
|
723 |
-
// This happens when the wp_id is not a product or it's already
|
724 |
-
// been deleted.
|
725 |
-
return;
|
726 |
-
}
|
727 |
-
$fb_product_group_id = $this->get_product_fbid(
|
728 |
-
self::FB_PRODUCT_GROUP_ID,
|
729 |
-
$wp_id,
|
730 |
-
$woo_product);
|
731 |
-
$fb_product_item_id = $this->get_product_fbid(
|
732 |
-
self::FB_PRODUCT_ITEM_ID,
|
733 |
-
$wp_id,
|
734 |
-
$woo_product);
|
735 |
-
if (! ($fb_product_group_id || $fb_product_item_id ) ) {
|
736 |
-
return; // No synced product, no-op.
|
737 |
-
}
|
738 |
-
$products = array($wp_id);
|
739 |
-
if (WC_Facebookcommerce_Utils::is_variable_type($woo_product->get_type())) {
|
740 |
-
$children = $woo_product->get_children();
|
741 |
-
$products = array_merge($products, $children);
|
742 |
-
}
|
743 |
-
foreach ($products as $item_id) {
|
744 |
-
$this->delete_product_item($item_id);
|
745 |
-
}
|
746 |
-
if ($fb_product_group_id) {
|
747 |
-
$pg_result = $this->fbgraph->delete_product_group($fb_product_group_id);
|
748 |
-
WC_Facebookcommerce_Utils::log($pg_result);
|
749 |
-
}
|
750 |
-
}
|
751 |
-
|
752 |
-
/**
|
753 |
-
* Update FB visibility for trashing and restore.
|
754 |
-
*/
|
755 |
-
function fb_change_product_published_status($new_status, $old_status, $post) {
|
756 |
-
global $post;
|
757 |
-
$visibility = $new_status == 'publish' ? 'published' : 'staging';
|
758 |
-
|
759 |
-
// change from publish status -> unpublish status, e.g. trash, draft, etc.
|
760 |
-
// change from trash status -> publish status
|
761 |
-
// no need to update for change from trash <-> unpublish status
|
762 |
-
if (($old_status == 'publish' && $new_status != 'publish') ||
|
763 |
-
($old_status == 'trash' && $new_status == 'publish')) {
|
764 |
-
$this->update_fb_visibility($post->ID, $visibility);
|
765 |
-
}
|
766 |
-
}
|
767 |
-
|
768 |
-
/**
|
769 |
-
* Generic function for use with any product publishing.
|
770 |
-
* Will determine product type (simple or variable) and delegate to
|
771 |
-
* appropriate handler.
|
772 |
-
*/
|
773 |
-
function on_product_publish($wp_id) {
|
774 |
-
if (get_post_status($wp_id) != 'publish') {
|
775 |
-
return;
|
776 |
-
}
|
777 |
-
|
778 |
-
$woo_product = new WC_Facebook_Product($wp_id);
|
779 |
-
$product_type = $woo_product->get_type();
|
780 |
-
if (WC_Facebookcommerce_Utils::is_variable_type($woo_product->get_type())) {
|
781 |
-
$this->on_variable_product_publish($wp_id, $woo_product);
|
782 |
-
} else {
|
783 |
-
$this->on_simple_product_publish($wp_id, $woo_product);
|
784 |
-
}
|
785 |
-
}
|
786 |
-
|
787 |
-
/**
|
788 |
-
* If the user has opt-in to remove products that are out of stock,
|
789 |
-
* this function will delete the product from FB Page as well.
|
790 |
-
*/
|
791 |
-
function delete_on_out_of_stock($wp_id, $woo_product) {
|
792 |
-
if (get_option('woocommerce_hide_out_of_stock_items') === 'yes' &&
|
793 |
-
!$woo_product->is_in_stock()) {
|
794 |
-
$this->delete_product_item($wp_id);
|
795 |
-
return true;
|
796 |
-
}
|
797 |
-
return false;
|
798 |
-
}
|
799 |
-
|
800 |
-
function on_variable_product_publish($wp_id, $woo_product = null) {
|
801 |
-
if (get_option('fb_disable_sync_on_dev_environment', false)) {
|
802 |
-
return;
|
803 |
-
}
|
804 |
-
|
805 |
-
if (get_post_status($wp_id) != 'publish') {
|
806 |
-
return;
|
807 |
-
}
|
808 |
-
// Check if product group has been published to FB. If not, it's new.
|
809 |
-
// If yes, loop through variants and see if product items are published.
|
810 |
-
if (!$woo_product) {
|
811 |
-
$woo_product = new WC_Facebook_Product($wp_id);
|
812 |
-
}
|
813 |
-
|
814 |
-
if ($this->delete_on_out_of_stock($wp_id, $woo_product)) {
|
815 |
-
return;
|
816 |
-
}
|
817 |
-
|
818 |
-
if (isset($_POST[self::FB_PRODUCT_DESCRIPTION])) {
|
819 |
-
$woo_product->set_description($_POST[self::FB_PRODUCT_DESCRIPTION]);
|
820 |
-
}
|
821 |
-
if (isset($_POST[WC_Facebook_Product::FB_PRODUCT_PRICE])) {
|
822 |
-
$woo_product->set_price($_POST[WC_Facebook_Product::FB_PRODUCT_PRICE]);
|
823 |
-
}
|
824 |
-
if (isset($_POST[WC_Facebook_Product::FB_PRODUCT_IMAGE])) {
|
825 |
-
$woo_product->set_product_image($_POST[WC_Facebook_Product::FB_PRODUCT_IMAGE]);
|
826 |
-
}
|
827 |
-
|
828 |
-
$woo_product->set_use_parent_image(
|
829 |
-
(isset($_POST[self::FB_VARIANT_IMAGE])) ?
|
830 |
-
$_POST[self::FB_VARIANT_IMAGE] :
|
831 |
-
null);
|
832 |
-
$fb_product_group_id = $this->get_product_fbid(
|
833 |
-
self::FB_PRODUCT_GROUP_ID,
|
834 |
-
$wp_id,
|
835 |
-
$woo_product);
|
836 |
-
|
837 |
-
if ($fb_product_group_id) {
|
838 |
-
$woo_product->update_visibility(
|
839 |
-
isset($_POST['is_product_page']),
|
840 |
-
isset($_POST[self::FB_VISIBILITY]));
|
841 |
-
$this->update_product_group($woo_product);
|
842 |
-
$child_products = $woo_product->get_children();
|
843 |
-
$variation_id = $woo_product->find_matching_product_variation();
|
844 |
-
// check if item_id is default variation. If yes, update in the end.
|
845 |
-
// If default variation value is to update, delete old fb_product_item_id
|
846 |
-
// and create new one in order to make it order correctly.
|
847 |
-
foreach ($child_products as $item_id) {
|
848 |
-
$fb_product_item_id =
|
849 |
-
$this->on_simple_product_publish($item_id, null, $woo_product);
|
850 |
-
if ($item_id == $variation_id && $fb_product_item_id) {
|
851 |
-
$this->set_default_variant($fb_product_group_id, $fb_product_item_id);
|
852 |
-
}
|
853 |
-
}
|
854 |
-
} else {
|
855 |
-
$this->create_product_variable($woo_product);
|
856 |
-
}
|
857 |
-
}
|
858 |
-
|
859 |
-
function on_simple_product_publish(
|
860 |
-
$wp_id,
|
861 |
-
$woo_product = null,
|
862 |
-
&$parent_product = null) {
|
863 |
-
if (get_option('fb_disable_sync_on_dev_environment', false)) {
|
864 |
-
return;
|
865 |
-
}
|
866 |
-
|
867 |
-
if (get_post_status($wp_id) != 'publish') {
|
868 |
-
return;
|
869 |
-
}
|
870 |
-
|
871 |
-
if (!$woo_product) {
|
872 |
-
$woo_product = new WC_Facebook_Product($wp_id, $parent_product);
|
873 |
-
}
|
874 |
-
|
875 |
-
if ($this->delete_on_out_of_stock($wp_id, $woo_product)) {
|
876 |
-
return;
|
877 |
-
}
|
878 |
-
|
879 |
-
if (isset($_POST[self::FB_PRODUCT_DESCRIPTION])) {
|
880 |
-
$woo_product->set_description($_POST[self::FB_PRODUCT_DESCRIPTION]);
|
881 |
-
}
|
882 |
-
|
883 |
-
if (isset($_POST[WC_Facebook_Product::FB_PRODUCT_PRICE])) {
|
884 |
-
$woo_product->set_price($_POST[WC_Facebook_Product::FB_PRODUCT_PRICE]);
|
885 |
-
}
|
886 |
-
|
887 |
-
if (isset($_POST[WC_Facebook_Product::FB_PRODUCT_IMAGE])) {
|
888 |
-
$woo_product->set_product_image($_POST[WC_Facebook_Product::FB_PRODUCT_IMAGE]);
|
889 |
-
}
|
890 |
-
|
891 |
-
// Check if this product has already been published to FB.
|
892 |
-
// If not, it's new!
|
893 |
-
$fb_product_item_id = $this->get_product_fbid(
|
894 |
-
self::FB_PRODUCT_ITEM_ID,
|
895 |
-
$wp_id,
|
896 |
-
$woo_product);
|
897 |
-
|
898 |
-
if ($fb_product_item_id) {
|
899 |
-
$woo_product->update_visibility(
|
900 |
-
isset($_POST['is_product_page']),
|
901 |
-
isset($_POST[self::FB_VISIBILITY]));
|
902 |
-
$this->update_product_item($woo_product, $fb_product_item_id);
|
903 |
-
return $fb_product_item_id;
|
904 |
-
} else {
|
905 |
-
// Check if this is a new product item for an existing product group
|
906 |
-
if ($woo_product->get_parent_id()) {
|
907 |
-
$fb_product_group_id = $this->get_product_fbid(
|
908 |
-
self::FB_PRODUCT_GROUP_ID,
|
909 |
-
$woo_product->get_parent_id(),
|
910 |
-
$woo_product);
|
911 |
-
|
912 |
-
// New variant added
|
913 |
-
if ($fb_product_group_id) {
|
914 |
-
return
|
915 |
-
$this->create_product_simple($woo_product, $fb_product_group_id);
|
916 |
-
} else {
|
917 |
-
WC_Facebookcommerce_Utils::fblog(
|
918 |
-
"Wrong! simple_product_publish called without group ID for
|
919 |
-
a variable product!", array(), true);
|
920 |
-
}
|
921 |
-
} else {
|
922 |
-
return $this->create_product_simple($woo_product); // new product
|
923 |
-
}
|
924 |
-
}
|
925 |
-
}
|
926 |
-
|
927 |
-
function create_product_variable($woo_product) {
|
928 |
-
$retailer_id = WC_Facebookcommerce_Utils::get_fb_retailer_id($woo_product);
|
929 |
-
|
930 |
-
$fb_product_group_id = $this->create_product_group(
|
931 |
-
$woo_product,
|
932 |
-
$retailer_id,
|
933 |
-
true);
|
934 |
-
|
935 |
-
if ($fb_product_group_id) {
|
936 |
-
$child_products = $woo_product->get_children();
|
937 |
-
$variation_id = $woo_product->find_matching_product_variation();
|
938 |
-
foreach ($child_products as $item_id) {
|
939 |
-
$child_product = new WC_Facebook_Product($item_id, $woo_product);
|
940 |
-
$retailer_id =
|
941 |
-
WC_Facebookcommerce_Utils::get_fb_retailer_id($child_product);
|
942 |
-
$fb_product_item_id = $this->create_product_item(
|
943 |
-
$child_product,
|
944 |
-
$retailer_id,
|
945 |
-
$fb_product_group_id);
|
946 |
-
if ($item_id == $variation_id && $fb_product_item_id) {
|
947 |
-
$this->set_default_variant($fb_product_group_id, $fb_product_item_id);
|
948 |
-
}
|
949 |
-
}
|
950 |
-
}
|
951 |
-
}
|
952 |
-
|
953 |
-
/**
|
954 |
-
* Create product group and product, store fb-specific info
|
955 |
-
**/
|
956 |
-
function create_product_simple($woo_product, $fb_product_group_id = null) {
|
957 |
-
$retailer_id = WC_Facebookcommerce_Utils::get_fb_retailer_id($woo_product);
|
958 |
-
|
959 |
-
if (!$fb_product_group_id) {
|
960 |
-
$fb_product_group_id = $this->create_product_group(
|
961 |
-
$woo_product,
|
962 |
-
$retailer_id);
|
963 |
-
}
|
964 |
-
|
965 |
-
if ($fb_product_group_id) {
|
966 |
-
$fb_product_item_id = $this->create_product_item(
|
967 |
-
$woo_product,
|
968 |
-
$retailer_id,
|
969 |
-
$fb_product_group_id);
|
970 |
-
return $fb_product_item_id;
|
971 |
-
}
|
972 |
-
}
|
973 |
-
|
974 |
-
function create_product_group($woo_product, $retailer_id, $variants = false) {
|
975 |
-
|
976 |
-
$product_group_data = array(
|
977 |
-
'retailer_id' => $retailer_id,
|
978 |
-
);
|
979 |
|
980 |
-
|
981 |
-
|
982 |
-
|
983 |
-
|
984 |
-
|
985 |
-
|
986 |
-
|
987 |
-
|
988 |
-
|
989 |
-
|
990 |
-
|
991 |
-
|
992 |
-
|
993 |
-
|
994 |
-
|
995 |
-
|
996 |
-
|
997 |
-
|
998 |
-
|
999 |
-
|
1000 |
-
|
1001 |
-
|
1002 |
-
|
1003 |
-
|
1004 |
-
|
1005 |
-
|
1006 |
-
|
1007 |
-
|
1008 |
-
|
1009 |
-
|
1010 |
-
|
1011 |
-
|
1012 |
-
|
1013 |
-
|
1014 |
-
|
1015 |
-
|
1016 |
-
|
1017 |
-
|
1018 |
-
|
1019 |
-
|
1020 |
-
|
1021 |
-
|
1022 |
-
|
1023 |
-
|
1024 |
-
|
1025 |
-
|
1026 |
-
|
1027 |
-
|
1028 |
-
|
1029 |
-
|
1030 |
-
|
1031 |
-
|
1032 |
-
|
1033 |
-
|
1034 |
-
|
1035 |
-
|
1036 |
-
update_post_meta($woo_product->get_id(),
|
1037 |
-
self::FB_PRODUCT_ITEM_ID, $fb_product_item_id);
|
1038 |
-
|
1039 |
-
$this->display_success_message(
|
1040 |
-
'Created product item <a href="https://facebook.com/'.
|
1041 |
-
$fb_product_item_id . '" target="_blank">' .
|
1042 |
-
$fb_product_item_id . '</a> on Facebook.');
|
1043 |
-
|
1044 |
-
return $fb_product_item_id;
|
1045 |
-
}
|
1046 |
-
}
|
1047 |
-
|
1048 |
-
|
1049 |
-
/**
|
1050 |
-
* Update existing product group (variant data only)
|
1051 |
-
**/
|
1052 |
-
function update_product_group($woo_product) {
|
1053 |
-
$fb_product_group_id = $this->get_product_fbid(
|
1054 |
-
self::FB_PRODUCT_GROUP_ID,
|
1055 |
-
$woo_product->get_id(),
|
1056 |
-
$woo_product);
|
1057 |
-
|
1058 |
-
if (!$fb_product_group_id) {
|
1059 |
-
return;
|
1060 |
-
}
|
1061 |
-
|
1062 |
-
$variants = $woo_product->prepare_variants_for_group();
|
1063 |
-
|
1064 |
-
if (!$variants) {
|
1065 |
-
WC_Facebookcommerce_Utils::log(
|
1066 |
-
sprintf(__('Nothing to update for product group for %1$s',
|
1067 |
-
'facebook-for-woocommerce'),
|
1068 |
-
$fb_product_group_id));
|
1069 |
-
return;
|
1070 |
-
}
|
1071 |
-
|
1072 |
-
$product_group_data = array(
|
1073 |
-
'variants' => $variants
|
1074 |
-
);
|
1075 |
|
1076 |
-
|
1077 |
-
|
1078 |
-
|
1079 |
-
|
1080 |
-
|
1081 |
-
|
1082 |
-
|
1083 |
-
|
1084 |
-
|
1085 |
-
|
1086 |
-
|
1087 |
-
|
1088 |
-
|
1089 |
-
|
1090 |
-
|
1091 |
-
|
1092 |
-
|
1093 |
-
|
1094 |
-
|
1095 |
-
|
1096 |
-
|
1097 |
-
|
1098 |
-
|
1099 |
-
|
1100 |
-
|
1101 |
-
|
1102 |
-
|
1103 |
-
|
1104 |
-
|
1105 |
-
|
1106 |
-
|
1107 |
-
|
1108 |
-
|
1109 |
-
|
1110 |
-
|
1111 |
-
|
1112 |
-
|
1113 |
-
|
1114 |
-
|
1115 |
-
|
1116 |
-
|
1117 |
-
|
1118 |
-
|
1119 |
-
|
1120 |
-
|
1121 |
-
|
1122 |
-
|
1123 |
-
|
1124 |
-
|
1125 |
-
|
1126 |
-
|
1127 |
-
|
1128 |
-
|
1129 |
-
|
1130 |
-
|
1131 |
-
|
1132 |
-
|
1133 |
-
|
1134 |
-
|
1135 |
-
|
1136 |
-
|
1137 |
-
|
1138 |
-
|
1139 |
-
|
1140 |
-
|
1141 |
-
|
1142 |
-
|
1143 |
-
|
1144 |
-
|
1145 |
-
|
1146 |
-
|
1147 |
-
|
1148 |
-
|
1149 |
-
|
1150 |
-
|
1151 |
-
|
1152 |
-
|
1153 |
-
|
1154 |
-
|
1155 |
-
|
1156 |
-
|
1157 |
-
|
1158 |
-
|
1159 |
-
|
1160 |
-
|
1161 |
-
|
1162 |
-
|
1163 |
-
|
1164 |
-
|
1165 |
-
|
1166 |
-
|
1167 |
-
|
1168 |
-
|
1169 |
-
|
1170 |
-
|
1171 |
-
|
1172 |
-
|
1173 |
-
|
1174 |
-
|
1175 |
-
|
1176 |
-
|
1177 |
-
|
1178 |
-
|
1179 |
-
|
1180 |
-
|
1181 |
-
|
1182 |
-
|
1183 |
-
|
1184 |
-
|
1185 |
-
|
1186 |
-
|
1187 |
-
|
1188 |
-
|
1189 |
-
|
1190 |
-
|
1191 |
-
|
1192 |
-
|
1193 |
-
|
1194 |
-
|
1195 |
-
|
1196 |
-
|
1197 |
-
|
1198 |
-
|
1199 |
-
|
1200 |
-
|
1201 |
-
|
1202 |
-
|
1203 |
-
|
1204 |
-
|
1205 |
-
|
1206 |
-
|
1207 |
-
|
1208 |
-
|
1209 |
-
|
1210 |
-
|
1211 |
-
|
1212 |
-
|
1213 |
-
|
1214 |
-
|
1215 |
-
|
1216 |
-
|
1217 |
-
|
1218 |
-
|
1219 |
-
|
1220 |
-
|
1221 |
-
|
1222 |
-
|
1223 |
-
|
1224 |
-
|
1225 |
-
|
1226 |
-
|
1227 |
-
|
1228 |
-
|
1229 |
-
|
1230 |
-
|
1231 |
-
|
1232 |
-
|
1233 |
-
|
1234 |
-
|
1235 |
-
|
1236 |
-
|
1237 |
-
|
1238 |
-
|
1239 |
-
|
1240 |
-
|
1241 |
-
|
1242 |
-
|
1243 |
-
|
1244 |
-
|
1245 |
-
|
1246 |
-
|
1247 |
-
|
1248 |
-
|
1249 |
-
|
1250 |
-
|
1251 |
-
|
1252 |
-
|
1253 |
-
|
1254 |
-
|
1255 |
-
|
1256 |
-
|
1257 |
-
|
1258 |
-
|
1259 |
-
|
1260 |
-
|
1261 |
-
|
1262 |
-
|
1263 |
-
|
1264 |
-
|
1265 |
-
|
1266 |
-
|
1267 |
-
|
1268 |
-
|
1269 |
-
|
1270 |
-
|
1271 |
-
|
1272 |
-
|
1273 |
-
|
1274 |
-
|
1275 |
-
|
1276 |
-
|
1277 |
-
|
1278 |
-
|
1279 |
-
|
1280 |
-
|
1281 |
-
|
1282 |
-
|
1283 |
-
|
1284 |
-
|
1285 |
-
|
1286 |
-
|
1287 |
-
|
1288 |
-
|
1289 |
-
|
1290 |
-
|
1291 |
-
|
1292 |
-
|
1293 |
-
|
1294 |
-
|
1295 |
-
|
1296 |
-
|
1297 |
-
|
1298 |
-
|
1299 |
-
|
1300 |
-
|
1301 |
-
|
1302 |
-
|
1303 |
-
|
1304 |
-
|
1305 |
-
|
1306 |
-
|
1307 |
-
|
1308 |
-
|
1309 |
-
|
1310 |
-
|
1311 |
-
|
1312 |
-
|
1313 |
-
|
1314 |
-
|
1315 |
-
|
1316 |
-
|
1317 |
-
|
1318 |
-
|
1319 |
-
|
1320 |
-
|
1321 |
-
|
1322 |
-
|
1323 |
-
|
1324 |
-
|
1325 |
-
|
1326 |
-
|
1327 |
-
|
1328 |
-
|
1329 |
-
|
1330 |
-
|
1331 |
-
|
1332 |
-
|
1333 |
-
|
1334 |
-
|
1335 |
-
|
1336 |
-
|
1337 |
-
|
1338 |
-
|
1339 |
-
|
1340 |
-
|
1341 |
-
|
1342 |
-
|
1343 |
-
|
1344 |
-
|
1345 |
-
|
1346 |
-
|
1347 |
-
|
1348 |
-
|
1349 |
-
|
1350 |
-
|
1351 |
-
|
1352 |
-
|
1353 |
-
|
1354 |
-
|
1355 |
-
|
1356 |
-
|
1357 |
-
|
1358 |
-
|
1359 |
-
|
1360 |
-
|
1361 |
-
|
1362 |
-
|
1363 |
-
|
1364 |
-
|
1365 |
-
|
1366 |
-
|
1367 |
-
|
1368 |
-
|
1369 |
-
|
1370 |
-
|
1371 |
-
|
1372 |
-
|
1373 |
-
|
1374 |
-
|
1375 |
-
|
1376 |
-
|
1377 |
-
|
1378 |
-
|
1379 |
-
|
1380 |
-
|
1381 |
-
|
1382 |
-
|
1383 |
-
|
1384 |
-
|
1385 |
-
|
1386 |
-
|
1387 |
-
|
1388 |
-
|
1389 |
-
|
1390 |
-
|
1391 |
-
|
1392 |
-
|
1393 |
-
|
1394 |
-
|
1395 |
-
|
1396 |
-
|
1397 |
-
|
1398 |
-
|
1399 |
-
|
1400 |
-
|
1401 |
-
|
1402 |
-
|
1403 |
-
|
1404 |
-
|
1405 |
-
|
1406 |
-
|
1407 |
-
|
1408 |
-
|
1409 |
-
|
1410 |
-
|
1411 |
-
|
1412 |
-
|
1413 |
-
|
1414 |
-
|
1415 |
-
|
1416 |
-
|
1417 |
-
|
1418 |
-
|
1419 |
-
|
1420 |
-
|
1421 |
-
|
1422 |
-
|
1423 |
-
|
1424 |
-
|
1425 |
-
|
1426 |
-
|
1427 |
-
|
1428 |
-
|
1429 |
-
|
1430 |
-
|
1431 |
-
|
1432 |
-
|
1433 |
-
|
1434 |
-
|
1435 |
-
|
1436 |
-
|
1437 |
-
|
1438 |
-
|
1439 |
-
|
1440 |
-
|
1441 |
-
|
1442 |
-
|
1443 |
-
|
1444 |
-
|
1445 |
-
|
1446 |
-
|
1447 |
-
|
1448 |
-
|
1449 |
-
|
1450 |
-
|
1451 |
-
|
1452 |
-
|
1453 |
-
|
1454 |
-
|
1455 |
-
|
1456 |
-
|
1457 |
-
|
1458 |
-
|
1459 |
-
|
1460 |
-
|
1461 |
-
|
1462 |
-
|
1463 |
-
|
1464 |
-
|
1465 |
-
|
1466 |
-
|
1467 |
-
|
1468 |
-
|
1469 |
-
|
1470 |
-
|
1471 |
-
|
1472 |
-
|
1473 |
-
|
1474 |
-
|
1475 |
-
|
1476 |
-
|
1477 |
-
|
1478 |
-
|
1479 |
-
|
1480 |
-
|
1481 |
-
|
1482 |
-
|
1483 |
-
|
1484 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1485 |
is almost ready.%2$s To complete your configuration, %3$scomplete the
|
1486 |
setup steps%4$s.',
|
1487 |
-
|
1488 |
-
|
1489 |
-
|
1490 |
-
|
1491 |
-
|
1492 |
-
|
1493 |
-
|
1494 |
-
|
1495 |
-
|
1496 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1497 |
%1$s. Please upgrade to WooCommerce 3.',
|
1498 |
-
|
1499 |
-
|
1500 |
-
|
1501 |
-
|
1502 |
-
|
1503 |
-
|
1504 |
-
|
1505 |
-
|
1506 |
-
|
1507 |
-
|
1508 |
-
|
1509 |
-
|
1510 |
-
|
1511 |
-
|
1512 |
-
|
1513 |
-
|
1514 |
-
|
1515 |
-
|
1516 |
-
|
1517 |
-
|
1518 |
-
|
1519 |
-
|
1520 |
-
|
1521 |
-
|
1522 |
-
|
1523 |
-
|
1524 |
-
|
1525 |
-
|
1526 |
-
|
1527 |
-
|
1528 |
-
|
1529 |
-
|
1530 |
-
|
1531 |
-
|
1532 |
-
|
1533 |
-
|
1534 |
-
|
1535 |
-
|
1536 |
-
|
1537 |
-
|
1538 |
-
|
1539 |
-
|
1540 |
-
|
1541 |
-
|
1542 |
-
|
1543 |
-
|
1544 |
-
|
1545 |
-
|
1546 |
-
|
1547 |
-
|
1548 |
-
|
1549 |
-
|
1550 |
-
|
1551 |
-
|
1552 |
-
|
1553 |
-
|
1554 |
-
|
1555 |
-
|
1556 |
-
|
1557 |
-
|
1558 |
-
|
1559 |
-
|
1560 |
-
|
1561 |
-
|
1562 |
-
|
1563 |
-
|
1564 |
-
|
1565 |
-
|
1566 |
-
|
1567 |
-
|
1568 |
-
|
1569 |
-
|
1570 |
-
|
1571 |
-
|
1572 |
-
|
1573 |
-
|
1574 |
-
|
1575 |
-
|
1576 |
-
|
1577 |
-
|
1578 |
-
|
1579 |
-
|
1580 |
-
|
1581 |
-
|
1582 |
-
|
1583 |
-
|
1584 |
-
|
1585 |
-
|
1586 |
-
|
1587 |
-
|
1588 |
-
|
1589 |
-
|
1590 |
-
|
1591 |
-
|
1592 |
-
|
1593 |
-
|
1594 |
-
|
1595 |
-
|
1596 |
-
|
1597 |
-
|
1598 |
-
|
1599 |
-
|
1600 |
-
|
1601 |
-
|
1602 |
-
|
1603 |
-
|
1604 |
-
|
1605 |
-
|
1606 |
-
|
1607 |
-
|
1608 |
-
|
1609 |
-
|
1610 |
-
|
1611 |
-
|
1612 |
-
|
1613 |
-
|
1614 |
-
|
1615 |
-
|
1616 |
-
|
1617 |
-
|
1618 |
-
|
1619 |
-
|
1620 |
-
|
1621 |
-
|
1622 |
-
|
1623 |
-
|
1624 |
-
|
1625 |
-
|
1626 |
-
|
1627 |
-
|
1628 |
-
|
1629 |
-
|
1630 |
-
|
1631 |
-
|
1632 |
-
|
1633 |
-
|
1634 |
-
|
1635 |
-
|
1636 |
-
|
1637 |
-
|
1638 |
-
|
1639 |
-
|
1640 |
-
|
1641 |
-
|
1642 |
-
|
1643 |
-
|
1644 |
-
|
1645 |
-
|
1646 |
-
|
1647 |
-
|
1648 |
-
|
1649 |
-
|
1650 |
-
|
1651 |
-
|
1652 |
-
|
1653 |
-
|
1654 |
-
|
1655 |
-
|
1656 |
-
|
1657 |
-
|
1658 |
-
|
1659 |
-
|
1660 |
-
|
1661 |
-
|
1662 |
-
|
1663 |
-
|
1664 |
-
|
1665 |
-
|
1666 |
-
|
1667 |
-
|
1668 |
-
|
1669 |
-
|
1670 |
-
|
1671 |
-
|
1672 |
-
|
1673 |
-
|
1674 |
-
|
1675 |
-
|
1676 |
-
|
1677 |
-
|
1678 |
-
|
1679 |
-
|
1680 |
-
|
1681 |
-
|
1682 |
-
|
1683 |
-
|
1684 |
-
|
1685 |
-
|
1686 |
-
|
1687 |
-
|
1688 |
-
|
1689 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1690 |
Facebook Product Catalog is no longer valid. This may happen if it was
|
1691 |
deleted, or this may be a transient error.
|
1692 |
If this error persists please remove your settings via
|
1693 |
"Advanced Options > Advanced Settings > Remove"
|
1694 |
-
and try setup again'
|
1695 |
-
|
1696 |
-
|
1697 |
-
|
1698 |
-
|
1699 |
-
|
1700 |
-
|
1701 |
-
|
1702 |
-
|
1703 |
-
|
1704 |
-
|
1705 |
-
|
1706 |
-
|
1707 |
-
|
1708 |
-
|
1709 |
-
|
1710 |
-
|
1711 |
-
|
1712 |
-
|
1713 |
-
|
1714 |
-
|
1715 |
-
|
1716 |
-
|
1717 |
-
|
1718 |
-
|
1719 |
-
|
1720 |
-
|
1721 |
-
|
1722 |
-
|
1723 |
-
|
1724 |
-
|
1725 |
-
|
1726 |
-
|
1727 |
-
|
1728 |
-
|
1729 |
-
|
1730 |
-
|
1731 |
-
|
1732 |
-
|
1733 |
-
|
1734 |
-
|
1735 |
-
|
1736 |
-
|
1737 |
-
|
1738 |
-
|
1739 |
-
|
1740 |
-
|
1741 |
-
|
1742 |
-
|
1743 |
-
|
1744 |
-
|
1745 |
-
|
1746 |
-
|
1747 |
-
|
1748 |
-
|
1749 |
-
|
1750 |
-
|
1751 |
-
|
1752 |
-
|
1753 |
-
|
1754 |
-
|
1755 |
-
|
1756 |
-
|
1757 |
-
|
1758 |
-
|
1759 |
-
|
1760 |
-
|
1761 |
-
|
1762 |
-
|
1763 |
-
|
1764 |
-
|
1765 |
-
|
1766 |
-
|
1767 |
-
|
1768 |
-
|
1769 |
-
|
1770 |
-
|
1771 |
-
|
1772 |
-
|
1773 |
-
|
1774 |
-
|
1775 |
-
|
1776 |
-
|
1777 |
-
|
1778 |
-
|
1779 |
-
|
1780 |
-
|
1781 |
-
|
1782 |
-
|
1783 |
-
|
1784 |
-
|
1785 |
-
|
1786 |
-
|
1787 |
-
|
1788 |
-
|
1789 |
-
|
1790 |
-
|
1791 |
-
|
1792 |
-
|
1793 |
-
|
1794 |
-
|
1795 |
-
|
1796 |
-
|
1797 |
-
|
1798 |
-
|
1799 |
-
|
1800 |
-
|
1801 |
-
|
1802 |
-
|
1803 |
-
|
1804 |
-
|
1805 |
-
|
1806 |
-
|
1807 |
-
|
1808 |
-
|
1809 |
-
|
1810 |
-
|
1811 |
-
|
1812 |
-
|
1813 |
-
|
1814 |
-
|
1815 |
-
|
1816 |
-
|
1817 |
-
|
1818 |
-
|
1819 |
-
|
1820 |
-
|
1821 |
-
|
1822 |
-
|
1823 |
-
|
1824 |
-
|
1825 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1826 |
Facebook Product Catalog is no longer valid. This may happen if it was
|
1827 |
deleted, or this may be a transient error.
|
1828 |
If this error persists please remove your settings via
|
1829 |
"Advanced Options > Advanced Settings > Remove"
|
1830 |
-
and try setup again'
|
1831 |
-
|
1832 |
-
|
1833 |
-
|
1834 |
-
|
1835 |
-
|
1836 |
-
|
1837 |
-
|
1838 |
-
|
1839 |
-
|
1840 |
-
|
1841 |
-
|
1842 |
-
|
1843 |
-
|
1844 |
-
|
1845 |
-
|
1846 |
-
|
1847 |
-
|
1848 |
-
|
1849 |
-
|
1850 |
-
|
1851 |
-
|
1852 |
-
|
1853 |
-
|
1854 |
-
|
1855 |
-
|
1856 |
-
|
1857 |
-
|
1858 |
-
|
1859 |
-
|
1860 |
-
|
1861 |
-
|
1862 |
-
|
1863 |
-
|
1864 |
-
|
1865 |
-
|
1866 |
-
|
1867 |
-
|
1868 |
-
|
1869 |
-
|
1870 |
-
|
1871 |
-
|
1872 |
-
|
1873 |
-
|
1874 |
-
|
1875 |
-
|
1876 |
-
|
1877 |
-
|
1878 |
-
|
1879 |
-
|
1880 |
-
|
1881 |
-
|
1882 |
-
|
1883 |
-
|
1884 |
-
|
1885 |
-
|
1886 |
-
|
1887 |
-
|
1888 |
-
|
1889 |
-
|
1890 |
-
|
1891 |
-
|
1892 |
-
|
1893 |
-
|
1894 |
-
|
1895 |
-
|
1896 |
-
|
1897 |
-
|
1898 |
-
|
1899 |
-
|
1900 |
-
|
1901 |
-
|
1902 |
-
|
1903 |
-
|
1904 |
-
|
1905 |
-
|
1906 |
-
|
1907 |
-
|
1908 |
-
|
1909 |
-
|
1910 |
-
|
1911 |
-
|
1912 |
-
|
1913 |
-
|
1914 |
-
|
1915 |
-
|
1916 |
-
|
1917 |
-
|
1918 |
-
|
1919 |
-
|
1920 |
-
|
1921 |
-
|
1922 |
-
|
1923 |
-
|
1924 |
-
|
1925 |
-
|
1926 |
-
|
1927 |
-
|
1928 |
-
|
1929 |
-
|
1930 |
-
|
1931 |
-
|
1932 |
-
|
1933 |
-
|
1934 |
-
|
1935 |
-
|
1936 |
-
|
1937 |
-
|
1938 |
-
|
1939 |
-
|
1940 |
-
|
1941 |
-
|
1942 |
-
|
1943 |
-
|
1944 |
-
|
1945 |
-
|
1946 |
-
|
1947 |
-
|
1948 |
-
|
1949 |
-
|
1950 |
-
|
1951 |
-
|
1952 |
-
|
1953 |
-
|
1954 |
-
|
1955 |
-
|
1956 |
-
|
1957 |
-
|
1958 |
-
|
1959 |
-
|
1960 |
-
|
1961 |
-
|
1962 |
-
|
1963 |
-
|
1964 |
-
|
1965 |
-
|
1966 |
-
|
1967 |
-
|
1968 |
-
|
1969 |
-
|
1970 |
-
|
1971 |
-
|
1972 |
-
|
1973 |
-
|
1974 |
-
|
1975 |
-
|
1976 |
-
|
1977 |
-
|
1978 |
-
|
1979 |
-
|
1980 |
-
|
1981 |
-
|
1982 |
-
|
1983 |
-
|
1984 |
-
|
1985 |
-
|
1986 |
-
|
1987 |
-
|
1988 |
-
|
1989 |
-
|
1990 |
-
|
1991 |
-
|
1992 |
-
|
1993 |
-
|
1994 |
-
|
1995 |
-
|
1996 |
-
|
1997 |
-
|
1998 |
-
|
1999 |
-
|
2000 |
-
|
2001 |
-
|
2002 |
-
|
2003 |
-
|
2004 |
-
|
2005 |
-
|
2006 |
-
|
2007 |
-
|
2008 |
-
|
2009 |
-
|
2010 |
-
|
2011 |
-
|
2012 |
-
|
2013 |
-
|
2014 |
-
|
2015 |
-
|
2016 |
-
|
2017 |
-
|
2018 |
-
|
2019 |
-
|
2020 |
-
|
2021 |
-
|
2022 |
-
|
2023 |
-
|
2024 |
-
|
2025 |
-
|
2026 |
-
|
2027 |
-
|
2028 |
-
|
2029 |
-
|
2030 |
-
|
2031 |
-
|
2032 |
-
|
2033 |
-
|
2034 |
-
|
2035 |
-
|
2036 |
-
|
2037 |
-
|
2038 |
-
|
2039 |
-
|
2040 |
-
|
2041 |
-
|
2042 |
-
|
2043 |
-
|
2044 |
-
|
2045 |
-
|
2046 |
-
|
2047 |
-
|
2048 |
-
|
2049 |
-
|
2050 |
-
|
2051 |
-
|
2052 |
-
|
2053 |
-
|
2054 |
-
|
2055 |
-
|
2056 |
-
|
2057 |
-
|
2058 |
-
|
2059 |
-
|
2060 |
-
|
2061 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2062 |
<div class="nux-message-text">%s</div>
|
2063 |
<div class="nux-message-arrow"></div>
|
2064 |
<i class="nux-message-close-btn">x</i>
|
2065 |
</div>
|
2066 |
<script>(function() { fbe_init_nux_messages(); })();</script>',
|
2067 |
-
|
2068 |
-
|
2069 |
-
|
2070 |
-
|
2071 |
-
|
2072 |
-
|
2073 |
-
|
2074 |
-
|
2075 |
-
|
2076 |
-
|
2077 |
-
|
2078 |
-
|
2079 |
-
|
2080 |
-
|
2081 |
-
|
2082 |
-
|
2083 |
-
|
2084 |
-
empty($this->settings['
|
2085 |
-
|
2086 |
-
|
2087 |
-
|
2088 |
-
|
2089 |
-
|
2090 |
-
|
2091 |
-
|
2092 |
-
|
|
|
|
|
|
|
2093 |
incompatibilities with our extension. Please disable it, or select the
|
2094 |
-
"Ignore external links" option on the Remove HTTP settings page.'
|
2095 |
-
|
2096 |
-
|
2097 |
-
|
2098 |
-
|
2099 |
-
|
2100 |
-
|
2101 |
-
|
2102 |
-
|
2103 |
-
|
2104 |
-
|
2105 |
-
|
2106 |
-
|
2107 |
-
|
2108 |
-
|
2109 |
-
|
2110 |
-
|
2111 |
-
|
2112 |
-
|
2113 |
-
|
2114 |
-
|
2115 |
-
|
2116 |
-
|
2117 |
-
|
2118 |
-
|
2119 |
-
|
2120 |
-
|
2121 |
-
|
2122 |
-
|
2123 |
-
|
2124 |
-
|
2125 |
-
|
2126 |
-
|
2127 |
-
|
2128 |
-
|
2129 |
-
|
2130 |
-
|
2131 |
-
|
2132 |
-
|
2133 |
-
|
2134 |
-
|
2135 |
-
|
2136 |
-
|
2137 |
-
|
2138 |
-
|
2139 |
-
|
2140 |
-
|
2141 |
-
|
2142 |
-
|
2143 |
-
|
2144 |
-
|
2145 |
-
|
2146 |
-
|
2147 |
-
|
2148 |
-
|
2149 |
-
|
2150 |
-
|
2151 |
-
|
2152 |
-
|
2153 |
-
|
2154 |
-
|
2155 |
-
|
2156 |
-
|
2157 |
-
|
2158 |
-
|
2159 |
-
|
2160 |
-
|
2161 |
-
|
2162 |
-
|
2163 |
-
|
2164 |
-
|
2165 |
-
|
2166 |
-
|
2167 |
-
|
2168 |
-
|
2169 |
-
|
2170 |
-
|
2171 |
-
|
2172 |
-
|
2173 |
-
|
2174 |
-
|
2175 |
-
'</a></span>'
|
2176 |
-
|
2177 |
-
|
2178 |
-
|
2179 |
-
|
2180 |
-
|
2181 |
-
|
2182 |
-
|
2183 |
-
|
2184 |
-
|
2185 |
-
|
2186 |
-
|
2187 |
-
|
2188 |
-
|
2189 |
-
|
2190 |
-
|
2191 |
-
|
2192 |
-
|
2193 |
-
|
2194 |
-
|
2195 |
-
|
2196 |
-
|
2197 |
-
|
2198 |
-
|
2199 |
-
|
2200 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2201 |
|
2202 |
<span><a href="#" class="btn small" onclick="facebookConfig()"
|
2203 |
-
id="setting_button">' . __('Settings', $domain) . '</a>
|
2204 |
</span>';
|
2205 |
-
|
2206 |
-
|
2207 |
-
|
2208 |
-
|
2209 |
-
'
|
2210 |
-
|
2211 |
-
|
2212 |
-
|
2213 |
-
|
2214 |
-
|
2215 |
-
|
2216 |
-
|
2217 |
-
|
2218 |
-
|
2219 |
-
|
2220 |
-
|
2221 |
-
|
2222 |
-
|
2223 |
-
|
2224 |
-
|
2225 |
-
|
2226 |
-
|
2227 |
-
|
2228 |
-
|
2229 |
-
|
2230 |
-
|
2231 |
-
|
2232 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2233 |
id="debug_info" style="display:none;" > More Info </a></span>',
|
2234 |
-
|
|
|
|
|
2235 |
<span><a href="#" class="btn small" onclick="facebookConfig()"
|
2236 |
id="setting_button"';
|
2237 |
|
2238 |
-
|
2239 |
-
|
2240 |
-
|
2241 |
-
|
2242 |
|
2243 |
<span><a href="#" class="btn small" onclick="sync_confirm()"
|
2244 |
id="resync_products"';
|
2245 |
|
2246 |
-
|
2247 |
-
|
2248 |
-
|
2249 |
-
|
2250 |
|
2251 |
<p id="sync_progress">';
|
2252 |
-
|
2253 |
-
|
2254 |
-
|
2255 |
-
|
2256 |
-
|
2257 |
-
|
2258 |
-
|
2259 |
-
|
2260 |
-
|
2261 |
-
|
2262 |
-
|
2263 |
-
|
2264 |
-
|
2265 |
-
|
2266 |
-
|
2267 |
-
|
2268 |
-
|
2269 |
-
|
2270 |
-
|
2271 |
-
|
2272 |
-
|
2273 |
-
|
2274 |
-
|
2275 |
-
|
2276 |
-
|
2277 |
-
|
2278 |
-
|
2279 |
-
|
2280 |
-
|
2281 |
-
|
2282 |
-
|
2283 |
-
|
2284 |
-
|
2285 |
-
|
2286 |
-
|
2287 |
-
|
2288 |
-
|
2289 |
-
|
2290 |
-
|
2291 |
-
|
2292 |
-
|
2293 |
-
|
2294 |
-
|
2295 |
-
|
2296 |
-
|
2297 |
-
|
2298 |
-
|
2299 |
-
|
2300 |
-
|
2301 |
-
|
2302 |
-
|
2303 |
-
|
2304 |
-
|
2305 |
-
|
2306 |
-
|
2307 |
-
|
2308 |
-
|
2309 |
-
|
2310 |
-
|
2311 |
-
|
2312 |
-
|
2313 |
-
|
2314 |
-
|
2315 |
-
|
2316 |
-
|
2317 |
-
|
2318 |
-
|
2319 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2320 |
extension. Note that this will reset your products and resync them
|
2321 |
to Facebook. Not recommended to use unless you are changing the
|
2322 |
-
extension code and want to test your changes.',
|
2323 |
-
|
2324 |
-
|
2325 |
-
|
2326 |
-
|
2327 |
-
|
2328 |
-
|
2329 |
-
|
2330 |
-
|
2331 |
-
|
2332 |
-
|
2333 |
-
|
2334 |
-
|
2335 |
-
|
2336 |
-
|
2337 |
-
|
2338 |
-
|
2339 |
-
|
2340 |
-
|
2341 |
-
|
2342 |
-
|
2343 |
-
|
2344 |
-
|
2345 |
-
|
2346 |
-
|
2347 |
-
|
2348 |
-
|
2349 |
-
|
2350 |
-
|
2351 |
-
|
2352 |
-
|
2353 |
-
|
2354 |
-
|
2355 |
-
|
2356 |
-
|
2357 |
-
|
2358 |
-
|
2359 |
-
|
2360 |
-
|
2361 |
-
|
2362 |
-
|
2363 |
-
|
2364 |
-
|
2365 |
-
|
2366 |
-
|
2367 |
-
|
2368 |
-
|
2369 |
-
|
2370 |
-
|
2371 |
-
|
2372 |
-
|
2373 |
-
|
2374 |
-
|
2375 |
-
|
2376 |
-
|
2377 |
-
|
2378 |
-
|
2379 |
-
|
2380 |
-
|
2381 |
-
|
2382 |
-
|
2383 |
-
|
2384 |
-
|
2385 |
-
|
2386 |
-
|
2387 |
-
|
2388 |
-
|
2389 |
-
|
2390 |
-
|
2391 |
-
|
2392 |
-
|
2393 |
-
|
2394 |
-
|
2395 |
-
|
2396 |
-
|
2397 |
-
|
2398 |
-
|
2399 |
-
|
2400 |
-
|
2401 |
-
|
2402 |
-
|
2403 |
-
|
2404 |
-
|
2405 |
-
|
2406 |
-
|
2407 |
-
|
2408 |
-
|
2409 |
-
|
2410 |
-
|
2411 |
-
|
2412 |
-
|
2413 |
-
|
2414 |
-
|
2415 |
-
|
2416 |
-
|
2417 |
-
|
2418 |
-
|
2419 |
-
|
2420 |
-
|
2421 |
-
|
2422 |
-
|
2423 |
-
|
2424 |
-
|
2425 |
-
|
2426 |
-
|
2427 |
-
|
2428 |
-
|
2429 |
-
|
2430 |
-
|
2431 |
-
|
2432 |
-
|
2433 |
-
|
2434 |
-
|
2435 |
-
|
2436 |
-
|
2437 |
-
|
2438 |
-
|
2439 |
-
|
2440 |
-
|
2441 |
-
|
2442 |
-
|
2443 |
-
|
2444 |
-
|
2445 |
-
|
2446 |
-
|
2447 |
-
|
2448 |
-
|
2449 |
-
|
2450 |
-
|
2451 |
-
|
2452 |
-
|
2453 |
-
|
2454 |
-
|
2455 |
-
|
2456 |
-
|
2457 |
-
|
2458 |
-
|
2459 |
-
|
2460 |
-
|
2461 |
-
|
2462 |
-
|
2463 |
-
|
2464 |
-
|
2465 |
-
|
2466 |
-
|
2467 |
-
|
2468 |
-
|
2469 |
-
|
2470 |
-
|
2471 |
-
|
2472 |
-
|
2473 |
-
|
2474 |
-
|
2475 |
-
|
2476 |
-
|
2477 |
-
|
2478 |
-
|
2479 |
-
|
2480 |
-
|
2481 |
-
|
2482 |
-
|
2483 |
-
|
2484 |
-
|
2485 |
-
|
2486 |
-
|
2487 |
-
|
2488 |
-
|
2489 |
-
|
2490 |
-
|
2491 |
-
|
2492 |
-
|
2493 |
-
|
2494 |
-
|
2495 |
-
|
2496 |
-
|
2497 |
-
|
2498 |
-
|
2499 |
-
|
2500 |
-
|
2501 |
-
|
2502 |
-
|
2503 |
-
|
2504 |
-
|
2505 |
-
|
2506 |
-
|
2507 |
-
|
2508 |
-
|
2509 |
-
|
2510 |
-
|
2511 |
-
|
2512 |
-
|
2513 |
-
|
2514 |
-
|
2515 |
-
|
2516 |
-
|
2517 |
-
|
2518 |
-
|
2519 |
-
|
2520 |
-
|
2521 |
-
|
2522 |
-
|
2523 |
-
|
2524 |
-
|
2525 |
-
|
2526 |
-
|
2527 |
-
|
2528 |
-
|
2529 |
-
|
2530 |
-
|
2531 |
-
|
2532 |
-
|
2533 |
-
|
2534 |
-
|
2535 |
-
|
2536 |
-
|
2537 |
-
|
2538 |
-
|
2539 |
-
|
2540 |
-
|
2541 |
-
|
2542 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2543 |
}
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
12 |
+
exit; // Exit if accessed directly
|
13 |
+
}
|
14 |
|
15 |
+
require_once 'facebook-config-warmer.php';
|
16 |
+
require_once 'includes/fbproduct.php';
|
17 |
+
require_once 'facebook-commerce-pixel-event.php';
|
18 |
|
19 |
class WC_Facebookcommerce_Integration extends WC_Integration {
|
20 |
|
21 |
+
const FB_PRODUCT_GROUP_ID = 'fb_product_group_id';
|
22 |
+
const FB_PRODUCT_ITEM_ID = 'fb_product_item_id';
|
23 |
+
const FB_PRODUCT_DESCRIPTION = 'fb_product_description';
|
24 |
+
|
25 |
+
const FB_VISIBILITY = 'fb_visibility';
|
26 |
+
|
27 |
+
const FB_CART_URL = 'fb_cart_url';
|
28 |
+
|
29 |
+
const FB_MESSAGE_DISPLAY_TIME = 180;
|
30 |
+
|
31 |
+
// Number of days to query tip.
|
32 |
+
const FB_TIP_QUERY = 1;
|
33 |
+
|
34 |
+
const FB_VARIANT_IMAGE = 'fb_image';
|
35 |
+
|
36 |
+
const FB_ADMIN_MESSAGE_PREPEND = '<b>Facebook for WooCommerce</b><br/>';
|
37 |
+
|
38 |
+
const FB_SYNC_IN_PROGRESS = 'fb_sync_in_progress';
|
39 |
+
const FB_SYNC_REMAINING = 'fb_sync_remaining';
|
40 |
+
const FB_SYNC_TIMEOUT = 30;
|
41 |
+
const FB_PRIORITY_MID = 9;
|
42 |
+
|
43 |
+
private $test_mode = false;
|
44 |
+
|
45 |
+
public function init_settings() {
|
46 |
+
parent::init_settings();
|
47 |
+
}
|
48 |
+
|
49 |
+
public function init_pixel() {
|
50 |
+
WC_Facebookcommerce_Pixel::initialize();
|
51 |
+
|
52 |
+
// Migrate WC customer pixel_id from WC settings to WP options.
|
53 |
+
// This is part of a larger effort to consolidate all the FB-specific
|
54 |
+
// settings for all plugin integrations.
|
55 |
+
if ( is_admin() ) {
|
56 |
+
$pixel_id = WC_Facebookcommerce_Pixel::get_pixel_id();
|
57 |
+
$settings_pixel_id = isset( $this->settings['fb_pixel_id'] ) ?
|
58 |
+
(string) $this->settings['fb_pixel_id'] : null;
|
59 |
+
if (
|
60 |
+
WC_Facebookcommerce_Utils::is_valid_id( $settings_pixel_id ) &&
|
61 |
+
( ! WC_Facebookcommerce_Utils::is_valid_id( $pixel_id ) ||
|
62 |
+
$pixel_id != $settings_pixel_id
|
63 |
+
)
|
64 |
+
) {
|
65 |
+
WC_Facebookcommerce_Pixel::set_pixel_id( $settings_pixel_id );
|
66 |
+
}
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Init and hook in the integration.
|
72 |
+
*
|
73 |
+
* @access public
|
74 |
+
* @return void
|
75 |
+
*/
|
76 |
+
public function __construct() {
|
77 |
+
if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) {
|
78 |
+
include_once 'facebook-commerce-events-tracker.php';
|
79 |
+
}
|
80 |
+
|
81 |
+
$this->id = 'facebookcommerce';
|
82 |
+
$this->method_title = __(
|
83 |
+
'Facebook for WooCommerce',
|
84 |
+
'facebook-for-commerce'
|
85 |
+
);
|
86 |
+
$this->method_description = __(
|
87 |
+
'Facebook Commerce and Dynamic Ads (Pixel) Extension',
|
88 |
+
'facebook-for-commerce'
|
89 |
+
);
|
90 |
+
|
91 |
+
// Load the settings.
|
92 |
+
$this->init_settings();
|
93 |
+
|
94 |
+
$this->page_id = isset( $this->settings['fb_page_id'] )
|
95 |
+
? $this->settings['fb_page_id']
|
96 |
+
: '';
|
97 |
+
|
98 |
+
$this->api_key = isset( $this->settings['fb_api_key'] )
|
99 |
+
? $this->settings['fb_api_key']
|
100 |
+
: '';
|
101 |
+
|
102 |
+
$pixel_id = WC_Facebookcommerce_Pixel::get_pixel_id();
|
103 |
+
if ( ! $pixel_id ) {
|
104 |
+
$pixel_id = isset( $this->settings['fb_pixel_id'] ) ?
|
105 |
+
$this->settings['fb_pixel_id'] : '';
|
106 |
+
}
|
107 |
+
$this->pixel_id = isset( $pixel_id )
|
108 |
+
? $pixel_id
|
109 |
+
: '';
|
110 |
+
|
111 |
+
$this->pixel_install_time = isset( $this->settings['pixel_install_time'] )
|
112 |
+
? $this->settings['pixel_install_time']
|
113 |
+
: '';
|
114 |
+
|
115 |
+
$this->use_pii = isset( $this->settings['fb_pixel_use_pii'] )
|
116 |
+
&& $this->settings['fb_pixel_use_pii'] === 'yes'
|
117 |
+
? true
|
118 |
+
: false;
|
119 |
+
|
120 |
+
$this->product_catalog_id = isset( $this->settings['fb_product_catalog_id'] )
|
121 |
+
? $this->settings['fb_product_catalog_id']
|
122 |
+
: '';
|
123 |
+
|
124 |
+
$this->external_merchant_settings_id =
|
125 |
+
isset( $this->settings['fb_external_merchant_settings_id'] )
|
126 |
+
? $this->settings['fb_external_merchant_settings_id']
|
127 |
+
: '';
|
128 |
+
|
129 |
+
if ( ! class_exists( 'WC_Facebookcommerce_Utils' ) ) {
|
130 |
+
include_once 'includes/fbutils.php';
|
131 |
+
}
|
132 |
+
|
133 |
+
WC_Facebookcommerce_Utils::$ems = $this->external_merchant_settings_id;
|
134 |
+
|
135 |
+
if ( ! class_exists( 'WC_Facebookcommerce_Graph_API' ) ) {
|
136 |
+
include_once 'includes/fbgraph.php';
|
137 |
+
$this->fbgraph = new WC_Facebookcommerce_Graph_API( $this->api_key );
|
138 |
+
}
|
139 |
+
|
140 |
+
WC_Facebookcommerce_Utils::$fbgraph = $this->fbgraph;
|
141 |
+
$this->feed_id = isset( $this->settings['fb_feed_id'] )
|
142 |
+
? $this->settings['fb_feed_id']
|
143 |
+
: '';
|
144 |
+
|
145 |
+
// Hooks
|
146 |
+
if ( is_admin() ) {
|
147 |
+
$this->init_pixel();
|
148 |
+
$this->init_form_fields();
|
149 |
+
// Display an info banner for eligible pixel and user.
|
150 |
+
if ( $this->external_merchant_settings_id
|
151 |
+
&& $this->pixel_id
|
152 |
+
&& $this->pixel_install_time ) {
|
153 |
+
$should_query_tip =
|
154 |
+
WC_Facebookcommerce_Utils::check_time_cap(
|
155 |
+
get_option( 'fb_info_banner_last_query_time', '' ),
|
156 |
+
self::FB_TIP_QUERY
|
157 |
+
);
|
158 |
+
$last_tip_info = WC_Facebookcommerce_Utils::get_cached_best_tip();
|
159 |
+
|
160 |
+
if ( $should_query_tip || $last_tip_info ) {
|
161 |
+
if ( ! class_exists( 'WC_Facebookcommerce_Info_Banner' ) ) {
|
162 |
+
include_once 'includes/fbinfobanner.php';
|
163 |
+
}
|
164 |
+
WC_Facebookcommerce_Info_Banner::get_instance(
|
165 |
+
$this->external_merchant_settings_id,
|
166 |
+
$this->fbgraph,
|
167 |
+
$should_query_tip
|
168 |
+
);
|
169 |
+
}
|
170 |
+
}
|
171 |
+
|
172 |
+
if ( ! class_exists( 'WC_Facebook_Integration_Test' ) ) {
|
173 |
+
include_once 'includes/test/facebook-integration-test.php';
|
174 |
+
}
|
175 |
+
$integration_test = WC_Facebook_Integration_Test::get_instance( $this );
|
176 |
+
$integration_test::$fbgraph = $this->fbgraph;
|
177 |
+
|
178 |
+
if ( ! $this->pixel_install_time && $this->pixel_id ) {
|
179 |
+
$this->pixel_install_time = current_time( 'mysql' );
|
180 |
+
$this->settings['pixel_install_time'] = $this->pixel_install_time;
|
181 |
+
update_option(
|
182 |
+
$this->get_option_key(),
|
183 |
+
apply_filters(
|
184 |
+
'woocommerce_settings_api_sanitized_fields_' . $this->id,
|
185 |
+
$this->settings
|
186 |
+
)
|
187 |
+
);
|
188 |
+
}
|
189 |
+
add_action( 'admin_notices', array( $this, 'checks' ) );
|
190 |
+
add_action(
|
191 |
+
'woocommerce_update_options_integration_facebookcommerce',
|
192 |
+
array( $this, 'process_admin_options' )
|
193 |
+
);
|
194 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'load_assets' ) );
|
195 |
+
|
196 |
+
add_action(
|
197 |
+
'wp_ajax_ajax_save_fb_settings',
|
198 |
+
array( $this, 'ajax_save_fb_settings' ),
|
199 |
+
self::FB_PRIORITY_MID
|
200 |
+
);
|
201 |
+
|
202 |
+
add_action(
|
203 |
+
'wp_ajax_ajax_delete_fb_settings',
|
204 |
+
array( $this, 'ajax_delete_fb_settings' ),
|
205 |
+
self::FB_PRIORITY_MID
|
206 |
+
);
|
207 |
+
|
208 |
+
add_action(
|
209 |
+
'wp_ajax_ajax_sync_all_fb_products',
|
210 |
+
array( $this, 'ajax_sync_all_fb_products' ),
|
211 |
+
self::FB_PRIORITY_MID
|
212 |
+
);
|
213 |
+
|
214 |
+
add_action(
|
215 |
+
'wp_ajax_ajax_sync_all_fb_products_using_feed',
|
216 |
+
array( $this, 'ajax_sync_all_fb_products_using_feed' ),
|
217 |
+
self::FB_PRIORITY_MID
|
218 |
+
);
|
219 |
+
|
220 |
+
add_action(
|
221 |
+
'wp_ajax_ajax_check_feed_upload_status',
|
222 |
+
array( $this, 'ajax_check_feed_upload_status' ),
|
223 |
+
self::FB_PRIORITY_MID
|
224 |
+
);
|
225 |
+
|
226 |
+
add_action(
|
227 |
+
'wp_ajax_ajax_reset_all_fb_products',
|
228 |
+
array( $this, 'ajax_reset_all_fb_products' ),
|
229 |
+
self::FB_PRIORITY_MID
|
230 |
+
);
|
231 |
+
add_action(
|
232 |
+
'wp_ajax_ajax_display_test_result',
|
233 |
+
array( $this, 'ajax_display_test_result' )
|
234 |
+
);
|
235 |
+
|
236 |
+
add_action(
|
237 |
+
'wp_ajax_ajax_schedule_force_resync',
|
238 |
+
array( $this, 'ajax_schedule_force_resync' ),
|
239 |
+
self::FB_PRIORITY_MID
|
240 |
+
);
|
241 |
+
|
242 |
+
add_action(
|
243 |
+
'wp_ajax_ajax_update_fb_option',
|
244 |
+
array( $this, 'ajax_update_fb_option' ),
|
245 |
+
self::FB_PRIORITY_MID
|
246 |
+
);
|
247 |
+
|
248 |
+
// Only load product processing hooks if we have completed setup.
|
249 |
+
if ( $this->api_key && $this->product_catalog_id ) {
|
250 |
+
add_action(
|
251 |
+
'woocommerce_process_product_meta_simple',
|
252 |
+
array( $this, 'on_simple_product_publish' ),
|
253 |
+
10, // Action priority
|
254 |
+
1 // Args passed to on_product_publish (should be 'id')
|
255 |
+
);
|
256 |
+
|
257 |
+
add_action(
|
258 |
+
'woocommerce_process_product_meta_variable',
|
259 |
+
array( $this, 'on_variable_product_publish' ),
|
260 |
+
10, // Action priority
|
261 |
+
1 // Args passed to on_product_publish (should be 'id')
|
262 |
+
);
|
263 |
+
|
264 |
+
add_action(
|
265 |
+
'woocommerce_process_product_meta_booking',
|
266 |
+
array( $this, 'on_simple_product_publish' ),
|
267 |
+
10, // Action priority
|
268 |
+
1 // Args passed to on_product_publish (should be 'id')
|
269 |
+
);
|
270 |
+
|
271 |
+
add_action(
|
272 |
+
'woocommerce_process_product_meta_external',
|
273 |
+
array( $this, 'on_simple_product_publish' ),
|
274 |
+
10, // Action priority
|
275 |
+
1 // Args passed to on_product_publish (should be 'id')
|
276 |
+
);
|
277 |
+
|
278 |
+
add_action(
|
279 |
+
'woocommerce_process_product_meta_subscription',
|
280 |
+
array( $this, 'on_product_publish' ),
|
281 |
+
10, // Action priority
|
282 |
+
1 // Args passed to on_product_publish (should be 'id')
|
283 |
+
);
|
284 |
+
|
285 |
+
add_action(
|
286 |
+
'woocommerce_process_product_meta_variable-subscription',
|
287 |
+
array( $this, 'on_product_publish' ),
|
288 |
+
10, // Action priority
|
289 |
+
1 // Args passed to on_product_publish (should be 'id')
|
290 |
+
);
|
291 |
+
|
292 |
+
add_action(
|
293 |
+
'woocommerce_process_product_meta_bundle',
|
294 |
+
array( $this, 'on_product_publish' ),
|
295 |
+
10, // Action priority
|
296 |
+
1 // Args passed to on_product_publish (should be 'id')
|
297 |
+
);
|
298 |
+
|
299 |
+
add_action(
|
300 |
+
'woocommerce_product_quick_edit_save',
|
301 |
+
array( $this, 'on_quick_and_bulk_edit_save' ),
|
302 |
+
10, // Action priority
|
303 |
+
1 // Args passed to on_quick_and_bulk_edit_save ('product')
|
304 |
+
);
|
305 |
+
|
306 |
+
add_action(
|
307 |
+
'woocommerce_product_bulk_edit_save',
|
308 |
+
array( $this, 'on_quick_and_bulk_edit_save' ),
|
309 |
+
10, // Action priority
|
310 |
+
1 // Args passed to on_quick_and_bulk_edit_save ('product')
|
311 |
+
);
|
312 |
+
|
313 |
+
add_action(
|
314 |
+
'before_delete_post',
|
315 |
+
array( $this, 'on_product_delete' ),
|
316 |
+
10,
|
317 |
+
1
|
318 |
+
);
|
319 |
+
|
320 |
+
add_action( 'add_meta_boxes', array( $this, 'fb_product_metabox' ), 10, 1 );
|
321 |
+
|
322 |
+
add_filter(
|
323 |
+
'manage_product_posts_columns',
|
324 |
+
array( $this, 'fb_product_columns' )
|
325 |
+
);
|
326 |
+
add_action(
|
327 |
+
'manage_product_posts_custom_column',
|
328 |
+
array( $this, 'fb_render_product_columns' ),
|
329 |
+
2
|
330 |
+
);
|
331 |
+
add_action(
|
332 |
+
'transition_post_status',
|
333 |
+
array( $this, 'fb_change_product_published_status' ),
|
334 |
+
10,
|
335 |
+
3
|
336 |
+
);
|
337 |
+
|
338 |
+
// Product data tab
|
339 |
+
add_filter(
|
340 |
+
'woocommerce_product_data_tabs',
|
341 |
+
array( $this, 'fb_new_product_tab' )
|
342 |
+
);
|
343 |
+
|
344 |
+
add_action(
|
345 |
+
'woocommerce_product_data_panels',
|
346 |
+
array( $this, 'fb_new_product_tab_content' )
|
347 |
+
);
|
348 |
+
|
349 |
+
add_action(
|
350 |
+
'wp_ajax_ajax_fb_toggle_visibility',
|
351 |
+
array( $this, 'ajax_fb_toggle_visibility' )
|
352 |
+
);
|
353 |
+
|
354 |
+
add_action(
|
355 |
+
'wp_ajax_ajax_reset_single_fb_product',
|
356 |
+
array( $this, 'ajax_reset_single_fb_product' )
|
357 |
+
);
|
358 |
+
|
359 |
+
add_action(
|
360 |
+
'wp_ajax_ajax_delete_fb_product',
|
361 |
+
array( $this, 'ajax_delete_fb_product' )
|
362 |
+
);
|
363 |
+
|
364 |
+
add_filter(
|
365 |
+
'woocommerce_duplicate_product_exclude_meta',
|
366 |
+
array( $this, 'fb_duplicate_product_reset_meta' )
|
367 |
+
);
|
368 |
+
|
369 |
+
add_action(
|
370 |
+
'pmxi_after_xml_import',
|
371 |
+
array( $this, 'wp_all_import_compat' )
|
372 |
+
);
|
373 |
+
|
374 |
+
add_action(
|
375 |
+
'wp_ajax_wpmelon_adv_bulk_edit',
|
376 |
+
array( $this, 'ajax_woo_adv_bulk_edit_compat' ),
|
377 |
+
self::FB_PRIORITY_MID
|
378 |
+
);
|
379 |
+
|
380 |
+
// Used to remove the 'you need to resync' message.
|
381 |
+
if ( isset( $_GET['remove_sticky'] ) ) {
|
382 |
+
$this->remove_sticky_message();
|
383 |
+
}
|
384 |
+
|
385 |
+
if ( defined( 'ICL_LANGUAGE_CODE' ) ) {
|
386 |
+
include_once 'includes/fbwpml.php';
|
387 |
+
new WC_Facebook_WPML_Injector();
|
388 |
+
}
|
389 |
+
}
|
390 |
+
$this->load_background_sync_process();
|
391 |
+
}
|
392 |
+
// Must be outside of admin for cron to schedule correctly.
|
393 |
+
add_action(
|
394 |
+
'sync_all_fb_products_using_feed',
|
395 |
+
array( $this, 'sync_all_fb_products_using_feed' ),
|
396 |
+
self::FB_PRIORITY_MID
|
397 |
+
);
|
398 |
+
|
399 |
+
if ( $this->pixel_id ) {
|
400 |
+
$user_info = WC_Facebookcommerce_Utils::get_user_info( $this->use_pii );
|
401 |
+
$this->events_tracker = new WC_Facebookcommerce_EventsTracker( $user_info );
|
402 |
+
}
|
403 |
+
|
404 |
+
if ( isset( $this->settings['is_messenger_chat_plugin_enabled'] ) &&
|
405 |
+
$this->settings['is_messenger_chat_plugin_enabled'] === 'yes' ) {
|
406 |
+
if ( ! class_exists( 'WC_Facebookcommerce_MessengerChat' ) ) {
|
407 |
+
include_once 'facebook-commerce-messenger-chat.php';
|
408 |
+
}
|
409 |
+
$this->messenger_chat = new WC_Facebookcommerce_MessengerChat( $this->settings );
|
410 |
+
}
|
411 |
+
}
|
412 |
+
|
413 |
+
public function load_background_sync_process() {
|
414 |
+
// Attempt to load background processing (Woo 3.x.x only)
|
415 |
+
include_once 'includes/fbbackground.php';
|
416 |
+
if ( class_exists( 'WC_Facebookcommerce_Background_Process' ) ) {
|
417 |
+
if ( ! isset( $this->background_processor ) ) {
|
418 |
+
$this->background_processor =
|
419 |
+
new WC_Facebookcommerce_Background_Process( $this );
|
420 |
+
}
|
421 |
+
}
|
422 |
+
add_action(
|
423 |
+
'wp_ajax_ajax_fb_background_check_queue',
|
424 |
+
array( $this, 'ajax_fb_background_check_queue' )
|
425 |
+
);
|
426 |
+
}
|
427 |
+
|
428 |
+
public function ajax_fb_background_check_queue() {
|
429 |
+
WC_Facebookcommerce_Utils::check_woo_ajax_permissions( 'background check queue', true );
|
430 |
+
check_ajax_referer( 'wc_facebook_settings_jsx' );
|
431 |
+
$request_time = null;
|
432 |
+
if ( isset( $_POST['request_time'] ) ) {
|
433 |
+
$request_time = esc_js( sanitize_text_field( $_POST['request_time'] ) );
|
434 |
+
}
|
435 |
+
if ( $this->settings['fb_api_key'] ) {
|
436 |
+
if ( isset( $this->background_processor ) ) {
|
437 |
+
$is_processing = $this->background_processor->handle_cron_healthcheck();
|
438 |
+
$remaining = $this->background_processor->get_item_count();
|
439 |
+
$response = array(
|
440 |
+
'connected' => true,
|
441 |
+
'background' => true,
|
442 |
+
'processing' => $is_processing,
|
443 |
+
'remaining' => $remaining,
|
444 |
+
'request_time' => $request_time,
|
445 |
+
);
|
446 |
+
} else {
|
447 |
+
$response = array(
|
448 |
+
'connected' => true,
|
449 |
+
'background' => false,
|
450 |
+
);
|
451 |
+
}
|
452 |
+
} else {
|
453 |
+
$response = array(
|
454 |
+
'connected' => false,
|
455 |
+
'background' => false,
|
456 |
+
);
|
457 |
+
}
|
458 |
+
printf( json_encode( $response ) );
|
459 |
+
wp_die();
|
460 |
+
}
|
461 |
+
|
462 |
+
public function fb_new_product_tab( $tabs ) {
|
463 |
+
$tabs['fb_commerce_tab'] = array(
|
464 |
+
'label' => __( 'Facebook', 'facebook-for-woocommerce' ),
|
465 |
+
'target' => 'facebook_options',
|
466 |
+
'class' => array( 'show_if_simple', 'show_if_variable' ),
|
467 |
+
);
|
468 |
+
return $tabs;
|
469 |
+
}
|
470 |
+
|
471 |
+
public function fb_new_product_tab_content() {
|
472 |
+
global $post;
|
473 |
+
$woo_product = new WC_Facebook_Product( $post->ID );
|
474 |
+
$description = get_post_meta(
|
475 |
+
$post->ID,
|
476 |
+
self::FB_PRODUCT_DESCRIPTION,
|
477 |
+
true
|
478 |
+
);
|
479 |
+
|
480 |
+
$price = get_post_meta(
|
481 |
+
$post->ID,
|
482 |
+
WC_Facebook_Product::FB_PRODUCT_PRICE,
|
483 |
+
true
|
484 |
+
);
|
485 |
+
|
486 |
+
$image = get_post_meta(
|
487 |
+
$post->ID,
|
488 |
+
WC_Facebook_Product::FB_PRODUCT_IMAGE,
|
489 |
+
true
|
490 |
+
);
|
491 |
+
|
492 |
+
$image_setting = null;
|
493 |
+
if ( WC_Facebookcommerce_Utils::is_variable_type( $woo_product->get_type() ) ) {
|
494 |
+
$image_setting = $woo_product->get_use_parent_image();
|
495 |
+
}
|
496 |
+
|
497 |
+
// 'id' attribute needs to match the 'target' parameter set above
|
498 |
+
?><div id='facebook_options' class='panel woocommerce_options_panel'><div class='options_group'>
|
499 |
+
<?php
|
500 |
+
woocommerce_wp_textarea_input(
|
501 |
+
array(
|
502 |
+
'id' => self::FB_PRODUCT_DESCRIPTION,
|
503 |
+
'label' => __( 'Facebook Description', 'facebook-for-woocommerce' ),
|
504 |
+
'desc_tip' => 'true',
|
505 |
+
'description' => __(
|
506 |
+
'Custom (plain-text only) description for product on Facebook. ' .
|
507 |
+
'If blank, product description will be used. ' .
|
508 |
+
'If product description is blank, shortname will be used.',
|
509 |
+
'facebook-for-woocommerce'
|
510 |
+
),
|
511 |
+
'cols' => 40,
|
512 |
+
'rows' => 20,
|
513 |
+
'value' => $description,
|
514 |
+
)
|
515 |
+
);
|
516 |
+
woocommerce_wp_textarea_input(
|
517 |
+
array(
|
518 |
+
'id' => WC_Facebook_Product::FB_PRODUCT_IMAGE,
|
519 |
+
'label' => __( 'Facebook Product Image', 'facebook-for-woocommerce' ),
|
520 |
+
'desc_tip' => 'true',
|
521 |
+
'description' => __(
|
522 |
+
'Image URL for product on Facebook. Must be an absolute URL ' .
|
523 |
+
'e.g. https://...' .
|
524 |
+
'This can be used to override the primary image that will be ' .
|
525 |
+
'used on Facebook for this product. If blank, the primary ' .
|
526 |
+
'product image in Woo will be used as the primary image on FB.',
|
527 |
+
'facebook-for-woocommerce'
|
528 |
+
),
|
529 |
+
'cols' => 40,
|
530 |
+
'rows' => 10,
|
531 |
+
'value' => $image,
|
532 |
+
)
|
533 |
+
);
|
534 |
+
woocommerce_wp_text_input(
|
535 |
+
array(
|
536 |
+
'id' => WC_Facebook_Product::FB_PRODUCT_PRICE,
|
537 |
+
'label' => __(
|
538 |
+
'Facebook Price (' .
|
539 |
+
get_woocommerce_currency_symbol() . ')',
|
540 |
+
'facebook-for-woocommerce'
|
541 |
+
),
|
542 |
+
'desc_tip' => 'true',
|
543 |
+
'description' => __(
|
544 |
+
'Custom price for product on Facebook. ' .
|
545 |
+
'Please enter in monetary decimal (.) format without thousand ' .
|
546 |
+
'separators and currency symbols. ' .
|
547 |
+
'If blank, product price will be used. ',
|
548 |
+
'facebook-for-woocommerce'
|
549 |
+
),
|
550 |
+
'cols' => 40,
|
551 |
+
'rows' => 60,
|
552 |
+
'value' => $price,
|
553 |
+
)
|
554 |
+
);
|
555 |
+
if ( $image_setting !== null ) {
|
556 |
+
woocommerce_wp_checkbox(
|
557 |
+
array(
|
558 |
+
'id' => self::FB_VARIANT_IMAGE,
|
559 |
+
'label' => __( 'Use Parent Image', 'facebook-for-woocommerce' ),
|
560 |
+
'required' => false,
|
561 |
+
'desc_tip' => 'true',
|
562 |
+
'description' => __(
|
563 |
+
' By default, the primary image uploaded to Facebook is the image' .
|
564 |
+
' specified in each variant, if provided. ' .
|
565 |
+
' However, if you enable this setting, the ' .
|
566 |
+
' image of the parent will be used as the primary image' .
|
567 |
+
' for this product and all its variants instead.'
|
568 |
+
),
|
569 |
+
'value' => $image_setting ? 'yes' : 'no',
|
570 |
+
)
|
571 |
+
);
|
572 |
+
}
|
573 |
+
?>
|
574 |
+
</div>
|
575 |
+
</div>
|
576 |
+
<?php
|
577 |
+
}
|
578 |
+
|
579 |
+
public function fb_product_columns( $existing_columns ) {
|
580 |
+
if ( empty( $existing_columns ) && ! is_array( $existing_columns ) ) {
|
581 |
+
$existing_columns = array();
|
582 |
+
}
|
583 |
+
|
584 |
+
$columns = array();
|
585 |
+
$columns['fb'] = __( 'FB Shop', 'facebook-for-woocommerce' );
|
586 |
+
|
587 |
+
// Verify that cart URL hasn't changed. We do it here because this page
|
588 |
+
// is most likely to be visited (so it's a handy place to make the check)
|
589 |
+
$cart_url = get_option( self::FB_CART_URL );
|
590 |
+
if ( ! empty( $cart_url ) && ( wc_get_cart_url() !== $cart_url ) ) {
|
591 |
+
$this->display_warning_message(
|
592 |
+
'One or more of your products is using a
|
593 |
checkout URL that may be different than your shop checkout URL.
|
594 |
<a href="' . WOOCOMMERCE_FACEBOOK_PLUGIN_SETTINGS_URL . '">
|
595 |
+
Re-sync your products to update checkout URLs on Facebook.</a>'
|
596 |
+
);
|
597 |
+
}
|
598 |
+
|
599 |
+
return array_merge( $columns, $existing_columns );
|
600 |
+
}
|
601 |
+
|
602 |
+
public function fb_render_product_columns( $column ) {
|
603 |
+
global $post, $the_product;
|
604 |
+
$ajax_data = array(
|
605 |
+
'nonce' => wp_create_nonce( 'wc_facebook_product_jsx' ),
|
606 |
+
);
|
607 |
+
wp_enqueue_script(
|
608 |
+
'wc_facebook_product_jsx',
|
609 |
+
plugins_url(
|
610 |
+
'/assets/js/facebook-products.js?ts=' . time(),
|
611 |
+
__FILE__
|
612 |
+
)
|
613 |
+
);
|
614 |
+
wp_localize_script(
|
615 |
+
'wc_facebook_product_jsx',
|
616 |
+
'wc_facebook_product_jsx',
|
617 |
+
$ajax_data
|
618 |
+
);
|
619 |
+
|
620 |
+
if ( empty( $the_product ) || $the_product->get_id() != $post->ID ) {
|
621 |
+
$the_product = new WC_Facebook_Product( $post );
|
622 |
+
}
|
623 |
+
|
624 |
+
if ( $column === 'fb' ) {
|
625 |
+
$fb_product_group_id = $this->get_product_fbid(
|
626 |
+
self::FB_PRODUCT_GROUP_ID,
|
627 |
+
$post->ID,
|
628 |
+
$the_product
|
629 |
+
);
|
630 |
+
if ( ! $fb_product_group_id ) {
|
631 |
+
printf( '<span>Not Synced</span>' );
|
632 |
+
} else {
|
633 |
+
$viz_value = get_post_meta( $post->ID, self::FB_VISIBILITY, true );
|
634 |
+
$data_tip = $viz_value === '' ?
|
635 |
+
'Product is synced but not marked as published (visible)
|
636 |
on Facebook.' :
|
637 |
+
'Product is synced and published (visible) on Facebook.';
|
638 |
|
639 |
+
printf(
|
640 |
+
'<span class="tips" id="tip_%1$s" data-tip="%2$s">',
|
641 |
+
$post->ID,
|
642 |
+
$data_tip
|
643 |
+
);
|
644 |
|
645 |
+
if ( $viz_value === '' ) {
|
646 |
+
printf(
|
647 |
+
'<a id="viz_%1$s" class="button button-primary button-large"
|
648 |
href="javascript:;" onclick="fb_toggle_visibility(%1$s, true)">Show</a>',
|
649 |
+
$post->ID
|
650 |
+
);
|
651 |
+
} else {
|
652 |
+
printf(
|
653 |
+
'<a id="viz_%1$s" class="button" href="javascript:;"
|
654 |
onclick="fb_toggle_visibility(%1$s, false)">Hide</a>',
|
655 |
+
$post->ID
|
656 |
+
);
|
657 |
+
}
|
658 |
+
}
|
659 |
+
}
|
660 |
+
}
|
661 |
+
|
662 |
+
public function fb_product_metabox() {
|
663 |
+
$ajax_data = array(
|
664 |
+
'nonce' => wp_create_nonce( 'wc_facebook_metabox_jsx' ),
|
|
|
|
|
|
|
|
|
|
|
|
|
665 |
);
|
666 |
+
wp_enqueue_script(
|
667 |
+
'wc_facebook_metabox_jsx',
|
668 |
+
plugins_url(
|
669 |
+
'/assets/js/facebook-metabox.js?ts=' . time(),
|
670 |
+
__FILE__
|
671 |
+
)
|
672 |
+
);
|
673 |
+
wp_localize_script(
|
674 |
+
'wc_facebook_metabox_jsx',
|
675 |
+
'wc_facebook_metabox_jsx',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
676 |
$ajax_data
|
677 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
678 |
|
679 |
+
add_meta_box(
|
680 |
+
'facebook_metabox', // Meta box ID
|
681 |
+
'Facebook', // Meta box Title
|
682 |
+
array( $this, 'fb_product_meta_box_html' ), // Callback
|
683 |
+
'product', // Screen to which to add the meta box
|
684 |
+
'side' // Context
|
685 |
+
);
|
686 |
+
}
|
687 |
+
|
688 |
+
public function fb_product_meta_box_html() {
|
689 |
+
global $post;
|
690 |
+
$woo_product = new WC_Facebook_Product( $post->ID );
|
691 |
+
$fb_product_group_id = $this->get_product_fbid(
|
692 |
+
self::FB_PRODUCT_GROUP_ID,
|
693 |
+
$post->ID,
|
694 |
+
$woo_product
|
695 |
+
);
|
696 |
+
printf( '<span id="fb_metadata">' );
|
697 |
+
if ( $fb_product_group_id ) {
|
698 |
+
printf(
|
699 |
+
'Facebook ID: <a href="https://facebook.com/' .
|
700 |
+
$fb_product_group_id . '" target="_blank">' .
|
701 |
+
$fb_product_group_id . '</a><p/>'
|
702 |
+
);
|
703 |
+
if ( WC_Facebookcommerce_Utils::is_variable_type( $woo_product->get_type() ) ) {
|
704 |
+
printf( '<p>Variant IDs:<br/>' );
|
705 |
+
$children = $woo_product->get_children();
|
706 |
+
foreach ( $children as $child_id ) {
|
707 |
+
$fb_product_item_id = $this->get_product_fbid(
|
708 |
+
self::FB_PRODUCT_ITEM_ID,
|
709 |
+
$child_id
|
710 |
+
);
|
711 |
+
printf(
|
712 |
+
$child_id . ' : <a href="https://facebook.com/' .
|
713 |
+
$fb_product_item_id . '" target="_blank">' .
|
714 |
+
$fb_product_item_id . '</a><br/>'
|
715 |
+
);
|
716 |
+
}
|
717 |
+
printf( '</p>' );
|
718 |
+
}
|
719 |
+
|
720 |
+
$checkbox_value = get_post_meta( $post->ID, self::FB_VISIBILITY, true );
|
721 |
+
|
722 |
+
printf(
|
723 |
+
'Visible: <input name="%1$s" type="checkbox" value="1" %2$s/>',
|
724 |
+
self::FB_VISIBILITY,
|
725 |
+
$checkbox_value === '' ? '' : 'checked'
|
726 |
+
);
|
727 |
+
printf( '<p/><input name="is_product_page" type="hidden" value="1"' );
|
728 |
+
|
729 |
+
printf(
|
730 |
+
'<p/><a href="#" onclick="fb_reset_product(%1$s)">
|
731 |
+
Reset Facebook metadata</a>',
|
732 |
+
$post->ID
|
733 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
734 |
|
735 |
+
printf(
|
736 |
+
'<p/><a href="#" onclick="fb_delete_product(%1$s)">
|
737 |
+
Delete product(s) on Facebook</a>',
|
738 |
+
$post->ID
|
739 |
+
);
|
740 |
+
} else {
|
741 |
+
printf( '<b>This product is not yet synced to Facebook.</b>' );
|
742 |
+
}
|
743 |
+
printf( '</span>' );
|
744 |
+
}
|
745 |
+
|
746 |
+
private function get_product_count() {
|
747 |
+
$args = array(
|
748 |
+
'post_type' => 'product',
|
749 |
+
'post_status' => 'publish',
|
750 |
+
'posts_per_page' => -1,
|
751 |
+
'fields' => 'ids',
|
752 |
+
);
|
753 |
+
$products = new WP_Query( $args );
|
754 |
+
|
755 |
+
wp_reset_postdata();
|
756 |
+
|
757 |
+
echo $products->found_posts;
|
758 |
+
}
|
759 |
+
|
760 |
+
/**
|
761 |
+
* Load DIA specific JS Data
|
762 |
+
*/
|
763 |
+
public function load_assets() {
|
764 |
+
$screen = get_current_screen();
|
765 |
+
$ajax_data = array(
|
766 |
+
'nonce' => wp_create_nonce( 'wc_facebook_infobanner_jsx' ),
|
767 |
+
);
|
768 |
+
// load banner assets
|
769 |
+
wp_enqueue_script(
|
770 |
+
'wc_facebook_infobanner_jsx',
|
771 |
+
plugins_url(
|
772 |
+
'/assets/js/facebook-infobanner.js?ts=' . time(),
|
773 |
+
__FILE__
|
774 |
+
)
|
775 |
+
);
|
776 |
+
wp_localize_script(
|
777 |
+
'wc_facebook_infobanner_jsx',
|
778 |
+
'wc_facebook_infobanner_jsx',
|
779 |
+
$ajax_data
|
780 |
+
);
|
781 |
+
|
782 |
+
wp_enqueue_style(
|
783 |
+
'wc_facebook_infobanner_css',
|
784 |
+
plugins_url(
|
785 |
+
'/assets/css/facebook-infobanner.css',
|
786 |
+
__FILE__
|
787 |
+
)
|
788 |
+
);
|
789 |
+
|
790 |
+
if ( strpos( $screen->id, 'page_wc-settings' ) == 0 ) {
|
791 |
+
return;
|
792 |
+
}
|
793 |
+
|
794 |
+
if ( empty( $_GET['tab'] ) ) {
|
795 |
+
return;
|
796 |
+
}
|
797 |
+
|
798 |
+
if ( 'integration' !== $_GET['tab'] ) {
|
799 |
+
return;
|
800 |
+
}
|
801 |
+
|
802 |
+
?>
|
803 |
+
<script>
|
804 |
+
window.facebookAdsToolboxConfig = {
|
805 |
+
hasGzipSupport:
|
806 |
+
'<?php echo extension_loaded( 'zlib' ) ? 'true' : 'false'; ?>'
|
807 |
+
,enabledPlugins: ['MESSENGER_CHAT','INSTAGRAM_SHOP', 'PAGE_SHOP']
|
808 |
+
,enableSubscription: '<?php echo class_exists( 'WC_Subscriptions' ) ? 'true' : 'false'; ?>'
|
809 |
+
,popupOrigin: '<?php echo isset( $_GET['url'] ) ? esc_js( $_GET['url'] ) : 'https://www.facebook.com/'; ?>'
|
810 |
+
,feedWasDisabled: 'true'
|
811 |
+
,platform: 'WooCommerce'
|
812 |
+
,pixel: {
|
813 |
+
pixelId: '<?php echo $this->pixel_id ?: ''; ?>'
|
814 |
+
,advanced_matching_supported: true
|
815 |
+
}
|
816 |
+
,diaSettingId: '<?php echo $this->external_merchant_settings_id ?: ''; ?>'
|
817 |
+
,store: {
|
818 |
+
baseUrl: window.location.protocol + '//' + window.location.host
|
819 |
+
,baseCurrency:'<?php echo esc_js( WC_Admin_Settings::get_option( 'woocommerce_currency' ) ); ?>'
|
820 |
+
,timezoneId: '<?php echo date( 'Z' ); ?>'
|
821 |
+
,storeName: '<?php echo esc_js( WC_Facebookcommerce_Utils::get_store_name() ); ?>'
|
822 |
+
,version: '<?php echo WC()->version; ?>'
|
823 |
+
,php_version: '<?php echo PHP_VERSION; ?>'
|
824 |
+
,plugin_version: '<?php echo WC_Facebookcommerce_Utils::PLUGIN_VERSION; ?>'
|
825 |
+
}
|
826 |
+
,feed: {
|
827 |
+
totalVisibleProducts: '<?php echo $this->get_product_count(); ?>'
|
828 |
+
,hasClientSideFeedUpload: '<?php echo ! ! $this->feed_id; ?>'
|
829 |
+
}
|
830 |
+
,feedPrepared: {
|
831 |
+
feedUrl: ''
|
832 |
+
,feedPingUrl: ''
|
833 |
+
,samples: <?php echo $this->get_sample_product_feed(); ?>
|
834 |
+
}
|
835 |
+
,tokenExpired: '<?php echo $this->settings['fb_api_key'] && ! $this->get_page_name(); ?>'
|
836 |
+
};
|
837 |
+
</script>
|
838 |
+
<?php
|
839 |
+
$ajax_data = array(
|
840 |
+
'nonce' => wp_create_nonce( 'wc_facebook_settings_jsx' ),
|
841 |
+
);
|
842 |
+
wp_enqueue_script(
|
843 |
+
'wc_facebook_settings_jsx',
|
844 |
+
plugins_url(
|
845 |
+
'/assets/js/facebook-settings.js?ts=' . time(),
|
846 |
+
__FILE__
|
847 |
+
)
|
848 |
+
);
|
849 |
+
wp_localize_script(
|
850 |
+
'wc_facebook_settings_jsx',
|
851 |
+
'wc_facebook_settings_jsx',
|
852 |
+
$ajax_data
|
853 |
+
);
|
854 |
+
wp_enqueue_style(
|
855 |
+
'wc_facebook_css',
|
856 |
+
plugins_url(
|
857 |
+
'/assets/css/facebook.css',
|
858 |
+
__FILE__
|
859 |
+
)
|
860 |
+
);
|
861 |
+
}
|
862 |
+
|
863 |
+
function on_product_delete( $wp_id ) {
|
864 |
+
$woo_product = new WC_Facebook_Product( $wp_id );
|
865 |
+
if ( ! $woo_product->exists() ) {
|
866 |
+
// This happens when the wp_id is not a product or it's already
|
867 |
+
// been deleted.
|
868 |
+
return;
|
869 |
+
}
|
870 |
+
$fb_product_group_id = $this->get_product_fbid(
|
871 |
+
self::FB_PRODUCT_GROUP_ID,
|
872 |
+
$wp_id,
|
873 |
+
$woo_product
|
874 |
+
);
|
875 |
+
$fb_product_item_id = $this->get_product_fbid(
|
876 |
+
self::FB_PRODUCT_ITEM_ID,
|
877 |
+
$wp_id,
|
878 |
+
$woo_product
|
879 |
+
);
|
880 |
+
if ( ! ( $fb_product_group_id || $fb_product_item_id ) ) {
|
881 |
+
return; // No synced product, no-op.
|
882 |
+
}
|
883 |
+
$products = array( $wp_id );
|
884 |
+
if ( WC_Facebookcommerce_Utils::is_variable_type( $woo_product->get_type() ) ) {
|
885 |
+
$children = $woo_product->get_children();
|
886 |
+
$products = array_merge( $products, $children );
|
887 |
+
}
|
888 |
+
foreach ( $products as $item_id ) {
|
889 |
+
$this->delete_product_item( $item_id );
|
890 |
+
}
|
891 |
+
if ( $fb_product_group_id ) {
|
892 |
+
$pg_result = $this->fbgraph->delete_product_group( $fb_product_group_id );
|
893 |
+
WC_Facebookcommerce_Utils::log( $pg_result );
|
894 |
+
}
|
895 |
+
}
|
896 |
+
|
897 |
+
/**
|
898 |
+
* Update FB visibility for trashing and restore.
|
899 |
+
*/
|
900 |
+
function fb_change_product_published_status( $new_status, $old_status, $post ) {
|
901 |
+
global $post;
|
902 |
+
$visibility = $new_status == 'publish' ? 'published' : 'staging';
|
903 |
+
|
904 |
+
// change from publish status -> unpublish status, e.g. trash, draft, etc.
|
905 |
+
// change from trash status -> publish status
|
906 |
+
// no need to update for change from trash <-> unpublish status
|
907 |
+
if ( ( $old_status == 'publish' && $new_status != 'publish' ) ||
|
908 |
+
( $old_status == 'trash' && $new_status == 'publish' ) ) {
|
909 |
+
$this->update_fb_visibility( $post->ID, $visibility );
|
910 |
+
}
|
911 |
+
}
|
912 |
+
|
913 |
+
/**
|
914 |
+
* Generic function for use with any product publishing.
|
915 |
+
* Will determine product type (simple or variable) and delegate to
|
916 |
+
* appropriate handler.
|
917 |
+
*/
|
918 |
+
function on_product_publish( $wp_id ) {
|
919 |
+
if ( get_post_status( $wp_id ) != 'publish' ) {
|
920 |
+
return;
|
921 |
+
}
|
922 |
+
|
923 |
+
$woo_product = new WC_Facebook_Product( $wp_id );
|
924 |
+
$product_type = $woo_product->get_type();
|
925 |
+
if ( WC_Facebookcommerce_Utils::is_variable_type( $woo_product->get_type() ) ) {
|
926 |
+
$this->on_variable_product_publish( $wp_id, $woo_product );
|
927 |
+
} else {
|
928 |
+
$this->on_simple_product_publish( $wp_id, $woo_product );
|
929 |
+
}
|
930 |
+
}
|
931 |
+
|
932 |
+
/**
|
933 |
+
* If the user has opt-in to remove products that are out of stock,
|
934 |
+
* this function will delete the product from FB Page as well.
|
935 |
+
*/
|
936 |
+
function delete_on_out_of_stock( $wp_id, $woo_product ) {
|
937 |
+
if ( get_option( 'woocommerce_hide_out_of_stock_items' ) === 'yes' &&
|
938 |
+
! $woo_product->is_in_stock() ) {
|
939 |
+
$this->delete_product_item( $wp_id );
|
940 |
+
return true;
|
941 |
+
}
|
942 |
+
return false;
|
943 |
+
}
|
944 |
+
|
945 |
+
function on_variable_product_publish( $wp_id, $woo_product = null ) {
|
946 |
+
if ( get_option( 'fb_disable_sync_on_dev_environment', false ) ) {
|
947 |
+
return;
|
948 |
+
}
|
949 |
+
|
950 |
+
if ( get_post_status( $wp_id ) != 'publish' ) {
|
951 |
+
return;
|
952 |
+
}
|
953 |
+
// Check if product group has been published to FB. If not, it's new.
|
954 |
+
// If yes, loop through variants and see if product items are published.
|
955 |
+
if ( ! $woo_product ) {
|
956 |
+
$woo_product = new WC_Facebook_Product( $wp_id );
|
957 |
+
}
|
958 |
+
|
959 |
+
if ( $this->delete_on_out_of_stock( $wp_id, $woo_product ) ) {
|
960 |
+
return;
|
961 |
+
}
|
962 |
+
|
963 |
+
if ( isset( $_POST[ self::FB_PRODUCT_DESCRIPTION ] ) ) {
|
964 |
+
$woo_product->set_description( $_POST[ self::FB_PRODUCT_DESCRIPTION ] );
|
965 |
+
}
|
966 |
+
if ( isset( $_POST[ WC_Facebook_Product::FB_PRODUCT_PRICE ] ) ) {
|
967 |
+
$woo_product->set_price( $_POST[ WC_Facebook_Product::FB_PRODUCT_PRICE ] );
|
968 |
+
}
|
969 |
+
if ( isset( $_POST[ WC_Facebook_Product::FB_PRODUCT_IMAGE ] ) ) {
|
970 |
+
$woo_product->set_product_image( $_POST[ WC_Facebook_Product::FB_PRODUCT_IMAGE ] );
|
971 |
+
}
|
972 |
+
|
973 |
+
$woo_product->set_use_parent_image(
|
974 |
+
( isset( $_POST[ self::FB_VARIANT_IMAGE ] ) ) ?
|
975 |
+
$_POST[ self::FB_VARIANT_IMAGE ] :
|
976 |
+
null
|
977 |
+
);
|
978 |
+
$fb_product_group_id = $this->get_product_fbid(
|
979 |
+
self::FB_PRODUCT_GROUP_ID,
|
980 |
+
$wp_id,
|
981 |
+
$woo_product
|
982 |
+
);
|
983 |
+
|
984 |
+
if ( $fb_product_group_id ) {
|
985 |
+
$woo_product->update_visibility(
|
986 |
+
isset( $_POST['is_product_page'] ),
|
987 |
+
isset( $_POST[ self::FB_VISIBILITY ] )
|
988 |
+
);
|
989 |
+
$this->update_product_group( $woo_product );
|
990 |
+
$child_products = $woo_product->get_children();
|
991 |
+
$variation_id = $woo_product->find_matching_product_variation();
|
992 |
+
// check if item_id is default variation. If yes, update in the end.
|
993 |
+
// If default variation value is to update, delete old fb_product_item_id
|
994 |
+
// and create new one in order to make it order correctly.
|
995 |
+
foreach ( $child_products as $item_id ) {
|
996 |
+
$fb_product_item_id =
|
997 |
+
$this->on_simple_product_publish( $item_id, null, $woo_product );
|
998 |
+
if ( $item_id == $variation_id && $fb_product_item_id ) {
|
999 |
+
$this->set_default_variant( $fb_product_group_id, $fb_product_item_id );
|
1000 |
+
}
|
1001 |
+
}
|
1002 |
+
} else {
|
1003 |
+
$this->create_product_variable( $woo_product );
|
1004 |
+
}
|
1005 |
+
}
|
1006 |
+
|
1007 |
+
function on_simple_product_publish(
|
1008 |
+
$wp_id,
|
1009 |
+
$woo_product = null,
|
1010 |
+
&$parent_product = null ) {
|
1011 |
+
if ( get_option( 'fb_disable_sync_on_dev_environment', false ) ) {
|
1012 |
+
return;
|
1013 |
+
}
|
1014 |
+
|
1015 |
+
if ( get_post_status( $wp_id ) != 'publish' ) {
|
1016 |
+
return;
|
1017 |
+
}
|
1018 |
+
|
1019 |
+
if ( ! $woo_product ) {
|
1020 |
+
$woo_product = new WC_Facebook_Product( $wp_id, $parent_product );
|
1021 |
+
}
|
1022 |
+
|
1023 |
+
if ( $this->delete_on_out_of_stock( $wp_id, $woo_product ) ) {
|
1024 |
+
return;
|
1025 |
+
}
|
1026 |
+
|
1027 |
+
if ( isset( $_POST[ self::FB_PRODUCT_DESCRIPTION ] ) ) {
|
1028 |
+
$woo_product->set_description( $_POST[ self::FB_PRODUCT_DESCRIPTION ] );
|
1029 |
+
}
|
1030 |
+
|
1031 |
+
if ( isset( $_POST[ WC_Facebook_Product::FB_PRODUCT_PRICE ] ) ) {
|
1032 |
+
$woo_product->set_price( $_POST[ WC_Facebook_Product::FB_PRODUCT_PRICE ] );
|
1033 |
+
}
|
1034 |
+
|
1035 |
+
if ( isset( $_POST[ WC_Facebook_Product::FB_PRODUCT_IMAGE ] ) ) {
|
1036 |
+
$woo_product->set_product_image( $_POST[ WC_Facebook_Product::FB_PRODUCT_IMAGE ] );
|
1037 |
+
}
|
1038 |
+
|
1039 |
+
// Check if this product has already been published to FB.
|
1040 |
+
// If not, it's new!
|
1041 |
+
$fb_product_item_id = $this->get_product_fbid(
|
1042 |
+
self::FB_PRODUCT_ITEM_ID,
|
1043 |
+
$wp_id,
|
1044 |
+
$woo_product
|
1045 |
+
);
|
1046 |
+
|
1047 |
+
if ( $fb_product_item_id ) {
|
1048 |
+
$woo_product->update_visibility(
|
1049 |
+
isset( $_POST['is_product_page'] ),
|
1050 |
+
isset( $_POST[ self::FB_VISIBILITY ] )
|
1051 |
+
);
|
1052 |
+
$this->update_product_item( $woo_product, $fb_product_item_id );
|
1053 |
+
return $fb_product_item_id;
|
1054 |
+
} else {
|
1055 |
+
// Check if this is a new product item for an existing product group
|
1056 |
+
if ( $woo_product->get_parent_id() ) {
|
1057 |
+
$fb_product_group_id = $this->get_product_fbid(
|
1058 |
+
self::FB_PRODUCT_GROUP_ID,
|
1059 |
+
$woo_product->get_parent_id(),
|
1060 |
+
$woo_product
|
1061 |
+
);
|
1062 |
+
|
1063 |
+
// New variant added
|
1064 |
+
if ( $fb_product_group_id ) {
|
1065 |
+
return $this->create_product_simple( $woo_product, $fb_product_group_id );
|
1066 |
+
} else {
|
1067 |
+
WC_Facebookcommerce_Utils::fblog(
|
1068 |
+
'Wrong! simple_product_publish called without group ID for
|
1069 |
+
a variable product!',
|
1070 |
+
array(),
|
1071 |
+
true
|
1072 |
+
);
|
1073 |
+
}
|
1074 |
+
} else {
|
1075 |
+
return $this->create_product_simple( $woo_product ); // new product
|
1076 |
+
}
|
1077 |
+
}
|
1078 |
+
}
|
1079 |
+
|
1080 |
+
function create_product_variable( $woo_product ) {
|
1081 |
+
$retailer_id = WC_Facebookcommerce_Utils::get_fb_retailer_id( $woo_product );
|
1082 |
+
|
1083 |
+
$fb_product_group_id = $this->create_product_group(
|
1084 |
+
$woo_product,
|
1085 |
+
$retailer_id,
|
1086 |
+
true
|
1087 |
+
);
|
1088 |
+
|
1089 |
+
if ( $fb_product_group_id ) {
|
1090 |
+
$child_products = $woo_product->get_children();
|
1091 |
+
$variation_id = $woo_product->find_matching_product_variation();
|
1092 |
+
foreach ( $child_products as $item_id ) {
|
1093 |
+
$child_product = new WC_Facebook_Product( $item_id, $woo_product );
|
1094 |
+
$retailer_id =
|
1095 |
+
WC_Facebookcommerce_Utils::get_fb_retailer_id( $child_product );
|
1096 |
+
$fb_product_item_id = $this->create_product_item(
|
1097 |
+
$child_product,
|
1098 |
+
$retailer_id,
|
1099 |
+
$fb_product_group_id
|
1100 |
+
);
|
1101 |
+
if ( $item_id == $variation_id && $fb_product_item_id ) {
|
1102 |
+
$this->set_default_variant( $fb_product_group_id, $fb_product_item_id );
|
1103 |
+
}
|
1104 |
+
}
|
1105 |
+
}
|
1106 |
+
}
|
1107 |
+
|
1108 |
+
/**
|
1109 |
+
* Create product group and product, store fb-specific info
|
1110 |
+
**/
|
1111 |
+
function create_product_simple( $woo_product, $fb_product_group_id = null ) {
|
1112 |
+
$retailer_id = WC_Facebookcommerce_Utils::get_fb_retailer_id( $woo_product );
|
1113 |
+
|
1114 |
+
if ( ! $fb_product_group_id ) {
|
1115 |
+
$fb_product_group_id = $this->create_product_group(
|
1116 |
+
$woo_product,
|
1117 |
+
$retailer_id
|
1118 |
+
);
|
1119 |
+
}
|
1120 |
+
|
1121 |
+
if ( $fb_product_group_id ) {
|
1122 |
+
$fb_product_item_id = $this->create_product_item(
|
1123 |
+
$woo_product,
|
1124 |
+
$retailer_id,
|
1125 |
+
$fb_product_group_id
|
1126 |
+
);
|
1127 |
+
return $fb_product_item_id;
|
1128 |
+
}
|
1129 |
+
}
|
1130 |
+
|
1131 |
+
function create_product_group( $woo_product, $retailer_id, $variants = false ) {
|
1132 |
+
|
1133 |
+
$product_group_data = array(
|
1134 |
+
'retailer_id' => $retailer_id,
|
1135 |
+
);
|
1136 |
+
|
1137 |
+
// Default visibility on create = published
|
1138 |
+
$woo_product->fb_visibility = true;
|
1139 |
+
update_post_meta( $woo_product->get_id(), self::FB_VISIBILITY, true );
|
1140 |
+
|
1141 |
+
if ( $variants ) {
|
1142 |
+
$product_group_data['variants'] =
|
1143 |
+
$woo_product->prepare_variants_for_group();
|
1144 |
+
}
|
1145 |
+
|
1146 |
+
$create_product_group_result = $this->check_api_result(
|
1147 |
+
$this->fbgraph->create_product_group(
|
1148 |
+
$this->product_catalog_id,
|
1149 |
+
$product_group_data
|
1150 |
+
),
|
1151 |
+
$product_group_data,
|
1152 |
+
$woo_product->get_id()
|
1153 |
+
);
|
1154 |
+
|
1155 |
+
// New variant added
|
1156 |
+
if ( $create_product_group_result ) {
|
1157 |
+
$decode_result = WC_Facebookcommerce_Utils::decode_json( $create_product_group_result['body'] );
|
1158 |
+
$fb_product_group_id = $decode_result->id;
|
1159 |
+
// update_post_meta is actually more of a create_or_update
|
1160 |
+
update_post_meta(
|
1161 |
+
$woo_product->get_id(),
|
1162 |
+
self::FB_PRODUCT_GROUP_ID,
|
1163 |
+
$fb_product_group_id
|
1164 |
+
);
|
1165 |
+
|
1166 |
+
$this->display_success_message(
|
1167 |
+
'Created product group <a href="https://facebook.com/' .
|
1168 |
+
$fb_product_group_id . '" target="_blank">' .
|
1169 |
+
$fb_product_group_id . '</a> on Facebook.'
|
1170 |
+
);
|
1171 |
+
|
1172 |
+
return $fb_product_group_id;
|
1173 |
+
}
|
1174 |
+
}
|
1175 |
+
|
1176 |
+
function create_product_item( $woo_product, $retailer_id, $product_group_id ) {
|
1177 |
+
// Default visibility on create = published
|
1178 |
+
$woo_product->fb_visibility = true;
|
1179 |
+
$product_data = $woo_product->prepare_product( $retailer_id );
|
1180 |
+
if ( ! $product_data['price'] ) {
|
1181 |
+
return 0;
|
1182 |
+
}
|
1183 |
+
|
1184 |
+
update_post_meta( $woo_product->get_id(), self::FB_VISIBILITY, true );
|
1185 |
+
|
1186 |
+
$product_result = $this->check_api_result(
|
1187 |
+
$this->fbgraph->create_product_item(
|
1188 |
+
$product_group_id,
|
1189 |
+
$product_data
|
1190 |
+
),
|
1191 |
+
$product_data,
|
1192 |
+
$woo_product->get_id()
|
1193 |
+
);
|
1194 |
+
|
1195 |
+
if ( $product_result ) {
|
1196 |
+
$decode_result = WC_Facebookcommerce_Utils::decode_json( $product_result['body'] );
|
1197 |
+
$fb_product_item_id = $decode_result->id;
|
1198 |
+
|
1199 |
+
update_post_meta(
|
1200 |
+
$woo_product->get_id(),
|
1201 |
+
self::FB_PRODUCT_ITEM_ID,
|
1202 |
+
$fb_product_item_id
|
1203 |
+
);
|
1204 |
+
|
1205 |
+
$this->display_success_message(
|
1206 |
+
'Created product item <a href="https://facebook.com/' .
|
1207 |
+
$fb_product_item_id . '" target="_blank">' .
|
1208 |
+
$fb_product_item_id . '</a> on Facebook.'
|
1209 |
+
);
|
1210 |
+
|
1211 |
+
return $fb_product_item_id;
|
1212 |
+
}
|
1213 |
+
}
|
1214 |
+
|
1215 |
+
|
1216 |
+
/**
|
1217 |
+
* Update existing product group (variant data only)
|
1218 |
+
**/
|
1219 |
+
function update_product_group( $woo_product ) {
|
1220 |
+
$fb_product_group_id = $this->get_product_fbid(
|
1221 |
+
self::FB_PRODUCT_GROUP_ID,
|
1222 |
+
$woo_product->get_id(),
|
1223 |
+
$woo_product
|
1224 |
+
);
|
1225 |
+
|
1226 |
+
if ( ! $fb_product_group_id ) {
|
1227 |
+
return;
|
1228 |
+
}
|
1229 |
+
|
1230 |
+
$variants = $woo_product->prepare_variants_for_group();
|
1231 |
+
|
1232 |
+
if ( ! $variants ) {
|
1233 |
+
WC_Facebookcommerce_Utils::log(
|
1234 |
+
sprintf(
|
1235 |
+
__(
|
1236 |
+
'Nothing to update for product group for %1$s',
|
1237 |
+
'facebook-for-woocommerce'
|
1238 |
+
),
|
1239 |
+
$fb_product_group_id
|
1240 |
+
)
|
1241 |
+
);
|
1242 |
+
return;
|
1243 |
+
}
|
1244 |
+
|
1245 |
+
$product_group_data = array(
|
1246 |
+
'variants' => $variants,
|
1247 |
+
);
|
1248 |
+
|
1249 |
+
$result = $this->check_api_result(
|
1250 |
+
$this->fbgraph->update_product_group(
|
1251 |
+
$fb_product_group_id,
|
1252 |
+
$product_group_data
|
1253 |
+
)
|
1254 |
+
);
|
1255 |
+
|
1256 |
+
if ( $result ) {
|
1257 |
+
$this->display_success_message(
|
1258 |
+
'Updated product group <a href="https://facebook.com/' .
|
1259 |
+
$fb_product_group_id . '" target="_blank">' . $fb_product_group_id .
|
1260 |
+
'</a> on Facebook.'
|
1261 |
+
);
|
1262 |
+
}
|
1263 |
+
}
|
1264 |
+
|
1265 |
+
/**
|
1266 |
+
* Update existing product
|
1267 |
+
**/
|
1268 |
+
function update_product_item( $woo_product, $fb_product_item_id ) {
|
1269 |
+
$product_data = $woo_product->prepare_product();
|
1270 |
+
|
1271 |
+
$result = $this->check_api_result(
|
1272 |
+
$this->fbgraph->update_product_item(
|
1273 |
+
$fb_product_item_id,
|
1274 |
+
$product_data
|
1275 |
+
)
|
1276 |
+
);
|
1277 |
+
|
1278 |
+
if ( $result ) {
|
1279 |
+
$this->display_success_message(
|
1280 |
+
'Updated product <a href="https://facebook.com/' . $fb_product_item_id .
|
1281 |
+
'" target="_blank">' . $fb_product_item_id . '</a> on Facebook.'
|
1282 |
+
);
|
1283 |
+
}
|
1284 |
+
}
|
1285 |
+
|
1286 |
+
/**
|
1287 |
+
* Save settings via AJAX (to preserve window context for onboarding)
|
1288 |
+
**/
|
1289 |
+
function ajax_save_fb_settings() {
|
1290 |
+
WC_Facebookcommerce_Utils::check_woo_ajax_permissions( 'save settings', true );
|
1291 |
+
check_ajax_referer( 'wc_facebook_settings_jsx' );
|
1292 |
+
|
1293 |
+
if ( isset( $_REQUEST ) ) {
|
1294 |
+
if ( ! isset( $_REQUEST['facebook_for_woocommerce'] ) ) {
|
1295 |
+
// This is not a request from our plugin,
|
1296 |
+
// some other handler or plugin probably
|
1297 |
+
// wants to handle it and wp_die() after.
|
1298 |
+
return;
|
1299 |
+
}
|
1300 |
+
|
1301 |
+
if ( isset( $_REQUEST['api_key'] ) && ctype_alnum( $_REQUEST['api_key'] ) ) {
|
1302 |
+
$this->settings['fb_api_key'] = $_REQUEST['api_key'];
|
1303 |
+
}
|
1304 |
+
if ( isset( $_REQUEST['product_catalog_id'] ) &&
|
1305 |
+
ctype_digit( $_REQUEST['product_catalog_id'] ) ) {
|
1306 |
+
|
1307 |
+
if ( $this->product_catalog_id != '' &&
|
1308 |
+
$this->product_catalog_id != $_REQUEST['product_catalog_id'] ) {
|
1309 |
+
$this->reset_all_products();
|
1310 |
+
}
|
1311 |
+
$this->settings['fb_product_catalog_id'] =
|
1312 |
+
$_REQUEST['product_catalog_id'];
|
1313 |
+
}
|
1314 |
+
if ( isset( $_REQUEST['pixel_id'] ) && ctype_digit( $_REQUEST['pixel_id'] ) ) {
|
1315 |
+
// To prevent race conditions with pixel-only settings,
|
1316 |
+
// only save a pixel if we already have an API key.
|
1317 |
+
if ( $this->settings['fb_api_key'] ) {
|
1318 |
+
$this->settings['fb_pixel_id'] = $_REQUEST['pixel_id'];
|
1319 |
+
if ( $this->pixel_id != $_REQUEST['pixel_id'] ) {
|
1320 |
+
$this->settings['pixel_install_time'] = current_time( 'mysql' );
|
1321 |
+
}
|
1322 |
+
} else {
|
1323 |
+
WC_Facebookcommerce_Utils::log(
|
1324 |
+
'Got pixel-only settings, doing nothing'
|
1325 |
+
);
|
1326 |
+
echo 'Not saving pixel-only settings';
|
1327 |
+
wp_die();
|
1328 |
+
}
|
1329 |
+
}
|
1330 |
+
if ( isset( $_REQUEST['pixel_use_pii'] ) ) {
|
1331 |
+
$this->settings['fb_pixel_use_pii'] =
|
1332 |
+
( $_REQUEST['pixel_use_pii'] === 'true' ||
|
1333 |
+
$_REQUEST['pixel_use_pii'] === true ) ? 'yes' : 'no';
|
1334 |
+
}
|
1335 |
+
if ( isset( $_REQUEST['page_id'] ) &&
|
1336 |
+
ctype_digit( $_REQUEST['page_id'] ) ) {
|
1337 |
+
$this->settings['fb_page_id'] = $_REQUEST['page_id'];
|
1338 |
+
}
|
1339 |
+
if ( isset( $_REQUEST['external_merchant_settings_id'] ) &&
|
1340 |
+
ctype_digit( $_REQUEST['external_merchant_settings_id'] ) ) {
|
1341 |
+
$this->settings['fb_external_merchant_settings_id'] =
|
1342 |
+
$_REQUEST['external_merchant_settings_id'];
|
1343 |
+
}
|
1344 |
+
if ( isset( $_REQUEST['is_messenger_chat_plugin_enabled'] ) ) {
|
1345 |
+
$this->settings['is_messenger_chat_plugin_enabled'] =
|
1346 |
+
( $_REQUEST['is_messenger_chat_plugin_enabled'] === 'true' ||
|
1347 |
+
$_REQUEST['is_messenger_chat_plugin_enabled'] === true ) ? 'yes' : 'no';
|
1348 |
+
}
|
1349 |
+
if ( isset( $_REQUEST['facebook_jssdk_version'] ) ) {
|
1350 |
+
$this->settings['facebook_jssdk_version'] =
|
1351 |
+
sanitize_text_field( $_REQUEST['facebook_jssdk_version'] );
|
1352 |
+
}
|
1353 |
+
if ( isset( $_REQUEST['msger_chat_customization_greeting_text_code'] )
|
1354 |
+
&& ctype_digit( $_REQUEST['msger_chat_customization_greeting_text_code'] ) ) {
|
1355 |
+
$this->settings['msger_chat_customization_greeting_text_code'] =
|
1356 |
+
$_REQUEST['msger_chat_customization_greeting_text_code'];
|
1357 |
+
}
|
1358 |
+
if ( isset( $_REQUEST['msger_chat_customization_locale'] ) ) {
|
1359 |
+
$this->settings['msger_chat_customization_locale'] =
|
1360 |
+
sanitize_text_field( $_REQUEST['msger_chat_customization_locale'] );
|
1361 |
+
}
|
1362 |
+
if ( isset( $_REQUEST['msger_chat_customization_theme_color_code'] ) &&
|
1363 |
+
ctype_digit( $_REQUEST['msger_chat_customization_theme_color_code'] ) ) {
|
1364 |
+
$this->settings['msger_chat_customization_theme_color_code'] =
|
1365 |
+
$_REQUEST['msger_chat_customization_theme_color_code'];
|
1366 |
+
}
|
1367 |
+
|
1368 |
+
update_option(
|
1369 |
+
$this->get_option_key(),
|
1370 |
+
apply_filters(
|
1371 |
+
'woocommerce_settings_api_sanitized_fields_' . $this->id,
|
1372 |
+
$this->settings
|
1373 |
+
)
|
1374 |
+
);
|
1375 |
+
|
1376 |
+
WC_Facebookcommerce_Utils::log( 'Settings saved!' );
|
1377 |
+
echo 'settings_saved';
|
1378 |
+
} else {
|
1379 |
+
echo 'No Request';
|
1380 |
+
}
|
1381 |
+
|
1382 |
+
wp_die();
|
1383 |
+
}
|
1384 |
+
|
1385 |
+
/**
|
1386 |
+
* Delete all settings via AJAX
|
1387 |
+
**/
|
1388 |
+
function ajax_delete_fb_settings() {
|
1389 |
+
check_ajax_referer( 'wc_facebook_settings_jsx' );
|
1390 |
+
if ( ! WC_Facebookcommerce_Utils::check_woo_ajax_permissions( 'delete settings', false ) ) {
|
1391 |
+
return;
|
1392 |
+
}
|
1393 |
+
|
1394 |
+
// Do not allow reset in the middle of product sync
|
1395 |
+
$currently_syncing = get_transient( self::FB_SYNC_IN_PROGRESS );
|
1396 |
+
if ( $currently_syncing ) {
|
1397 |
+
wp_send_json(
|
1398 |
+
'A Facebook product sync is currently in progress.
|
1399 |
+
Deleting settings during product sync may cause errors.'
|
1400 |
+
);
|
1401 |
+
return;
|
1402 |
+
}
|
1403 |
+
|
1404 |
+
if ( isset( $_REQUEST ) ) {
|
1405 |
+
$ems = $this->settings['fb_external_merchant_settings_id'];
|
1406 |
+
if ( $ems ) {
|
1407 |
+
WC_Facebookcommerce_Utils::fblog(
|
1408 |
+
'Deleted all settings!',
|
1409 |
+
array(),
|
1410 |
+
false,
|
1411 |
+
$ems
|
1412 |
+
);
|
1413 |
+
}
|
1414 |
+
|
1415 |
+
$this->init_settings();
|
1416 |
+
$this->settings['fb_api_key'] = '';
|
1417 |
+
$this->settings['fb_product_catalog_id'] = '';
|
1418 |
+
|
1419 |
+
$this->settings['fb_pixel_id'] = '';
|
1420 |
+
$this->settings['fb_pixel_use_pii'] = 'no';
|
1421 |
+
|
1422 |
+
$this->settings['fb_page_id'] = '';
|
1423 |
+
$this->settings['fb_external_merchant_settings_id'] = '';
|
1424 |
+
$this->settings['pixel_install_time'] = '';
|
1425 |
+
$this->settings['fb_feed_id'] = '';
|
1426 |
+
$this->settings['fb_upload_id'] = '';
|
1427 |
+
$this->settings['upload_end_time'] = '';
|
1428 |
+
|
1429 |
+
WC_Facebookcommerce_Pixel::set_pixel_id( 0 );
|
1430 |
+
|
1431 |
+
update_option(
|
1432 |
+
$this->get_option_key(),
|
1433 |
+
apply_filters(
|
1434 |
+
'woocommerce_settings_api_sanitized_fields_' . $this->id,
|
1435 |
+
$this->settings
|
1436 |
+
)
|
1437 |
+
);
|
1438 |
+
|
1439 |
+
// Clean up old messages
|
1440 |
+
delete_transient( 'facebook_plugin_api_error' );
|
1441 |
+
delete_transient( 'facebook_plugin_api_success' );
|
1442 |
+
delete_transient( 'facebook_plugin_api_warning' );
|
1443 |
+
delete_transient( 'facebook_plugin_api_info' );
|
1444 |
+
delete_transient( 'facebook_plugin_api_sticky' );
|
1445 |
+
|
1446 |
+
$this->reset_all_products();
|
1447 |
+
|
1448 |
+
WC_Facebookcommerce_Utils::log( 'Settings deleted' );
|
1449 |
+
echo 'Settings Deleted';
|
1450 |
+
|
1451 |
+
}
|
1452 |
+
|
1453 |
+
wp_die();
|
1454 |
+
}
|
1455 |
+
|
1456 |
+
/**
|
1457 |
+
* Check Feed Upload Status
|
1458 |
+
**/
|
1459 |
+
function ajax_check_feed_upload_status() {
|
1460 |
+
WC_Facebookcommerce_Utils::check_woo_ajax_permissions( 'check feed upload status', true );
|
1461 |
+
check_ajax_referer( 'wc_facebook_settings_jsx' );
|
1462 |
+
if ( $this->settings['fb_api_key'] ) {
|
1463 |
+
$response = array(
|
1464 |
+
'connected' => true,
|
1465 |
+
'status' => 'in progress',
|
1466 |
+
);
|
1467 |
+
if ( $this->settings['fb_upload_id'] ) {
|
1468 |
+
if ( ! isset( $this->fbproductfeed ) ) {
|
1469 |
+
if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) {
|
1470 |
+
include_once 'includes/fbproductfeed.php';
|
1471 |
+
}
|
1472 |
+
$this->fbproductfeed = new WC_Facebook_Product_Feed(
|
1473 |
+
$this->product_catalog_id,
|
1474 |
+
$this->fbgraph
|
1475 |
+
);
|
1476 |
+
}
|
1477 |
+
$status = $this->fbproductfeed->is_upload_complete( $this->settings );
|
1478 |
+
|
1479 |
+
$response['status'] = $status;
|
1480 |
+
} else {
|
1481 |
+
$response = array(
|
1482 |
+
'connected' => true,
|
1483 |
+
'status' => 'error',
|
1484 |
+
);
|
1485 |
+
}
|
1486 |
+
if ( $response['status'] == 'complete' ) {
|
1487 |
+
update_option(
|
1488 |
+
$this->get_option_key(),
|
1489 |
+
apply_filters(
|
1490 |
+
'woocommerce_settings_api_sanitized_fields_' . $this->id,
|
1491 |
+
$this->settings
|
1492 |
+
)
|
1493 |
+
);
|
1494 |
+
}
|
1495 |
+
} else {
|
1496 |
+
$response = array(
|
1497 |
+
'connected' => false,
|
1498 |
+
);
|
1499 |
+
}
|
1500 |
+
printf( json_encode( $response ) );
|
1501 |
+
wp_die();
|
1502 |
+
}
|
1503 |
+
|
1504 |
+
/**
|
1505 |
+
* Display custom success message (sugar)
|
1506 |
+
**/
|
1507 |
+
function display_success_message( $msg ) {
|
1508 |
+
$msg = self::FB_ADMIN_MESSAGE_PREPEND . $msg;
|
1509 |
+
set_transient(
|
1510 |
+
'facebook_plugin_api_success',
|
1511 |
+
$msg,
|
1512 |
+
self::FB_MESSAGE_DISPLAY_TIME
|
1513 |
+
);
|
1514 |
+
}
|
1515 |
+
|
1516 |
+
/**
|
1517 |
+
* Display custom warning message (sugar)
|
1518 |
+
**/
|
1519 |
+
function display_warning_message( $msg ) {
|
1520 |
+
$msg = self::FB_ADMIN_MESSAGE_PREPEND . $msg;
|
1521 |
+
set_transient(
|
1522 |
+
'facebook_plugin_api_warning',
|
1523 |
+
$msg,
|
1524 |
+
self::FB_MESSAGE_DISPLAY_TIME
|
1525 |
+
);
|
1526 |
+
}
|
1527 |
+
|
1528 |
+
/**
|
1529 |
+
* Display custom info message (sugar)
|
1530 |
+
**/
|
1531 |
+
function display_info_message( $msg ) {
|
1532 |
+
$msg = self::FB_ADMIN_MESSAGE_PREPEND . $msg;
|
1533 |
+
set_transient(
|
1534 |
+
'facebook_plugin_api_info',
|
1535 |
+
$msg,
|
1536 |
+
self::FB_MESSAGE_DISPLAY_TIME
|
1537 |
+
);
|
1538 |
+
}
|
1539 |
+
|
1540 |
+
/**
|
1541 |
+
* Display custom "sticky" info message.
|
1542 |
+
* Call remove_sticky_message or wait for time out.
|
1543 |
+
**/
|
1544 |
+
function display_sticky_message( $msg ) {
|
1545 |
+
$msg = self::FB_ADMIN_MESSAGE_PREPEND . $msg;
|
1546 |
+
set_transient(
|
1547 |
+
'facebook_plugin_api_sticky',
|
1548 |
+
$msg,
|
1549 |
+
self::FB_MESSAGE_DISPLAY_TIME
|
1550 |
+
);
|
1551 |
+
}
|
1552 |
+
|
1553 |
+
/**
|
1554 |
+
* Remove custom "sticky" info message
|
1555 |
+
**/
|
1556 |
+
function remove_sticky_message() {
|
1557 |
+
delete_transient( 'facebook_plugin_api_sticky' );
|
1558 |
+
}
|
1559 |
+
|
1560 |
+
function remove_resync_message() {
|
1561 |
+
$msg = get_transient( 'facebook_plugin_api_sticky' );
|
1562 |
+
if ( $msg && strpos( $msg, 'Sync' ) !== false ) {
|
1563 |
+
delete_transient( 'facebook_plugin_resync_sticky' );
|
1564 |
+
}
|
1565 |
+
}
|
1566 |
+
|
1567 |
+
/**
|
1568 |
+
* Display custom error message (sugar)
|
1569 |
+
**/
|
1570 |
+
function display_error_message( $msg ) {
|
1571 |
+
$msg = self::FB_ADMIN_MESSAGE_PREPEND . $msg;
|
1572 |
+
WC_Facebookcommerce_Utils::log( $msg );
|
1573 |
+
set_transient(
|
1574 |
+
'facebook_plugin_api_error',
|
1575 |
+
$msg,
|
1576 |
+
self::FB_MESSAGE_DISPLAY_TIME
|
1577 |
+
);
|
1578 |
+
}
|
1579 |
+
|
1580 |
+
/**
|
1581 |
+
* Display error message from API result (sugar)
|
1582 |
+
**/
|
1583 |
+
function display_error_message_from_result( $result ) {
|
1584 |
+
$msg = json_decode( $result['body'] )->error->message;
|
1585 |
+
$this->display_error_message( $msg );
|
1586 |
+
}
|
1587 |
+
|
1588 |
+
/**
|
1589 |
+
* Deal with FB API responses, display error if FB API returns error
|
1590 |
+
*
|
1591 |
+
* @return result if response is 200, null otherwise
|
1592 |
+
**/
|
1593 |
+
function check_api_result( $result, $logdata = null, $wpid = null ) {
|
1594 |
+
if ( is_wp_error( $result ) ) {
|
1595 |
+
WC_Facebookcommerce_Utils::log( $result->get_error_message() );
|
1596 |
+
$this->display_error_message(
|
1597 |
+
'There was an issue connecting to the Facebook API: ' .
|
1598 |
+
$result->get_error_message()
|
1599 |
+
);
|
1600 |
+
return;
|
1601 |
+
}
|
1602 |
+
if ( $result['response']['code'] != '200' ) {
|
1603 |
+
// Catch 10800 fb error code ("Duplicate retailer ID") and capture FBID
|
1604 |
+
// if possible, otherwise let user know we found dupe SKUs
|
1605 |
+
$body = WC_Facebookcommerce_Utils::decode_json( $result['body'] );
|
1606 |
+
if ( $body && $body->error->code == '10800' ) {
|
1607 |
+
$error_data = $body->error->error_data; // error_data may contain FBIDs
|
1608 |
+
if ( $error_data && $wpid ) {
|
1609 |
+
$existing_id = $this->get_existing_fbid( $error_data, $wpid );
|
1610 |
+
if ( $existing_id ) {
|
1611 |
+
// Add "existing_id" ID to result
|
1612 |
+
$body->id = $existing_id;
|
1613 |
+
$result['body'] = json_encode( $body );
|
1614 |
+
return $result;
|
1615 |
+
}
|
1616 |
+
}
|
1617 |
+
} else {
|
1618 |
+
$this->display_error_message_from_result( $result );
|
1619 |
+
}
|
1620 |
+
|
1621 |
+
WC_Facebookcommerce_Utils::log( $result );
|
1622 |
+
$data = array(
|
1623 |
+
'result' => $result,
|
1624 |
+
'data' => $logdata,
|
1625 |
+
);
|
1626 |
+
WC_Facebookcommerce_Utils::fblog(
|
1627 |
+
'Non-200 error code from FB',
|
1628 |
+
$data,
|
1629 |
+
true
|
1630 |
+
);
|
1631 |
+
return null;
|
1632 |
+
}
|
1633 |
+
return $result;
|
1634 |
+
}
|
1635 |
+
|
1636 |
+
function ajax_woo_adv_bulk_edit_compat( $import_id ) {
|
1637 |
+
if ( ! WC_Facebookcommerce_Utils::check_woo_ajax_permissions( 'adv bulk edit', false ) ) {
|
1638 |
+
return;
|
1639 |
+
}
|
1640 |
+
$type = isset( $_POST['type'] ) ? $_POST['type'] : '';
|
1641 |
+
if ( strpos( $type, 'product' ) !== false && strpos( $type, 'load' ) === false ) {
|
1642 |
+
$this->display_out_of_sync_message( 'advanced bulk edit' );
|
1643 |
+
}
|
1644 |
+
}
|
1645 |
+
|
1646 |
+
function wp_all_import_compat( $import_id ) {
|
1647 |
+
$import = new PMXI_Import_Record();
|
1648 |
+
$import->getById( $import_id );
|
1649 |
+
if ( ! $import->isEmpty() && in_array( $import->options['custom_type'], array( 'product', 'product_variation' ) ) ) {
|
1650 |
+
$this->display_out_of_sync_message( 'import' );
|
1651 |
+
}
|
1652 |
+
}
|
1653 |
+
|
1654 |
+
function display_out_of_sync_message( $action_name ) {
|
1655 |
+
$this->display_sticky_message(
|
1656 |
+
sprintf(
|
1657 |
+
'Products may be out of Sync with Facebook due to your recent ' . $action_name . '.' .
|
1658 |
+
' <a href="%s&fb_force_resync=true&remove_sticky=true">Re-Sync them with FB.</a>',
|
1659 |
+
WOOCOMMERCE_FACEBOOK_PLUGIN_SETTINGS_URL
|
1660 |
+
)
|
1661 |
+
);
|
1662 |
+
}
|
1663 |
+
|
1664 |
+
/**
|
1665 |
+
* If we get a product group ID or product item ID back for a dupe retailer
|
1666 |
+
* id error, update existing ID.
|
1667 |
+
*
|
1668 |
+
* @return null
|
1669 |
+
**/
|
1670 |
+
function get_existing_fbid( $error_data, $wpid ) {
|
1671 |
+
if ( isset( $error_data->product_group_id ) ) {
|
1672 |
+
update_post_meta(
|
1673 |
+
$wpid,
|
1674 |
+
self::FB_PRODUCT_GROUP_ID,
|
1675 |
+
(string) $error_data->product_group_id
|
1676 |
+
);
|
1677 |
+
return $error_data->product_group_id;
|
1678 |
+
} elseif ( isset( $error_data->product_item_id ) ) {
|
1679 |
+
update_post_meta(
|
1680 |
+
$wpid,
|
1681 |
+
self::FB_PRODUCT_ITEM_ID,
|
1682 |
+
(string) $error_data->product_item_id
|
1683 |
+
);
|
1684 |
+
return $error_data->product_item_id;
|
1685 |
+
} else {
|
1686 |
+
return;
|
1687 |
+
}
|
1688 |
+
}
|
1689 |
+
|
1690 |
+
/**
|
1691 |
+
* Check for api key and any other API errors
|
1692 |
+
**/
|
1693 |
+
function checks() {
|
1694 |
+
// Check required fields
|
1695 |
+
|
1696 |
+
if ( ! $this->api_key || ! $this->product_catalog_id ) {
|
1697 |
+
echo $this->get_message_html(
|
1698 |
+
sprintf(
|
1699 |
+
__(
|
1700 |
+
'%1$sFacebook for WooCommerce
|
1701 |
is almost ready.%2$s To complete your configuration, %3$scomplete the
|
1702 |
setup steps%4$s.',
|
1703 |
+
'facebook-for-woocommerce'
|
1704 |
+
),
|
1705 |
+
'<strong>',
|
1706 |
+
'</strong>',
|
1707 |
+
'<a href="' . esc_url( WOOCOMMERCE_FACEBOOK_PLUGIN_SETTINGS_URL ) . '">',
|
1708 |
+
'</a>'
|
1709 |
+
),
|
1710 |
+
'info'
|
1711 |
+
);
|
1712 |
+
}
|
1713 |
+
|
1714 |
+
// WooCommerce 2.x upgrade nag
|
1715 |
+
if ( $this->api_key && ( ! isset( $this->background_processor ) ) ) {
|
1716 |
+
echo $this->get_message_html(
|
1717 |
+
sprintf(
|
1718 |
+
__(
|
1719 |
+
'Facebook product sync may not work correctly in WooCommerce version
|
1720 |
%1$s. Please upgrade to WooCommerce 3.',
|
1721 |
+
'facebook-for-woocommerce'
|
1722 |
+
),
|
1723 |
+
WC()->version
|
1724 |
+
),
|
1725 |
+
'warning'
|
1726 |
+
);
|
1727 |
+
}
|
1728 |
+
|
1729 |
+
$this->maybe_display_facebook_api_messages();
|
1730 |
+
}
|
1731 |
+
|
1732 |
+
function get_sample_product_feed() {
|
1733 |
+
ob_start();
|
1734 |
+
|
1735 |
+
// Get up to 12 published posts that are products
|
1736 |
+
$args = array(
|
1737 |
+
'post_type' => 'product',
|
1738 |
+
'post_status' => 'publish',
|
1739 |
+
'posts_per_page' => 12,
|
1740 |
+
'fields' => 'ids',
|
1741 |
+
);
|
1742 |
+
|
1743 |
+
$post_ids = get_posts( $args );
|
1744 |
+
$items = array();
|
1745 |
+
|
1746 |
+
foreach ( $post_ids as $post_id ) {
|
1747 |
+
|
1748 |
+
$woo_product = new WC_Facebook_Product( $post_id );
|
1749 |
+
$product_data = $woo_product->prepare_product();
|
1750 |
+
|
1751 |
+
$feed_item = array(
|
1752 |
+
'title' => strip_tags( $product_data['name'] ),
|
1753 |
+
'availability' => $woo_product->is_in_stock() ? 'in stock' :
|
1754 |
+
'out of stock',
|
1755 |
+
'description' => strip_tags( $product_data['description'] ),
|
1756 |
+
'id' => $product_data['retailer_id'],
|
1757 |
+
'image_link' => $product_data['image_url'],
|
1758 |
+
'brand' => strip_tags( WC_Facebookcommerce_Utils::get_store_name() ),
|
1759 |
+
'link' => $product_data['url'],
|
1760 |
+
'price' => $product_data['price'] . ' ' . get_woocommerce_currency(),
|
1761 |
+
);
|
1762 |
+
|
1763 |
+
array_push( $items, $feed_item );
|
1764 |
+
}
|
1765 |
+
// https://codex.wordpress.org/Function_Reference/wp_reset_postdata
|
1766 |
+
wp_reset_postdata();
|
1767 |
+
ob_end_clean();
|
1768 |
+
return json_encode( array( $items ) );
|
1769 |
+
}
|
1770 |
+
|
1771 |
+
/**
|
1772 |
+
* Loop through array of WPIDs to remove metadata.
|
1773 |
+
**/
|
1774 |
+
function delete_post_meta_loop( $products ) {
|
1775 |
+
foreach ( $products as $product_id ) {
|
1776 |
+
delete_post_meta( $product_id, self::FB_PRODUCT_GROUP_ID );
|
1777 |
+
delete_post_meta( $product_id, self::FB_PRODUCT_ITEM_ID );
|
1778 |
+
delete_post_meta( $product_id, self::FB_VISIBILITY );
|
1779 |
+
}
|
1780 |
+
}
|
1781 |
+
|
1782 |
+
/**
|
1783 |
+
* Remove FBIDs from all products when resetting store.
|
1784 |
+
**/
|
1785 |
+
function reset_all_products() {
|
1786 |
+
if ( ! is_admin() ) {
|
1787 |
+
WC_Facebookcommerce_Utils::log(
|
1788 |
+
'Not resetting any FBIDs from products,
|
1789 |
+
must call reset from admin context.'
|
1790 |
+
);
|
1791 |
+
return false;
|
1792 |
+
}
|
1793 |
+
|
1794 |
+
$test_instance = WC_Facebook_Integration_Test::get_instance( $this );
|
1795 |
+
$this->test_mode = $test_instance::$test_mode;
|
1796 |
+
|
1797 |
+
// Include draft products (omit 'post_status' => 'publish')
|
1798 |
+
WC_Facebookcommerce_Utils::log( 'Removing FBIDs from all products' );
|
1799 |
+
|
1800 |
+
$post_ids = get_posts(
|
1801 |
+
array(
|
1802 |
+
'post_type' => 'product',
|
1803 |
+
'posts_per_page' => -1,
|
1804 |
+
'fields' => 'ids',
|
1805 |
+
)
|
1806 |
+
);
|
1807 |
+
|
1808 |
+
$children = array();
|
1809 |
+
foreach ( $post_ids as $post_id ) {
|
1810 |
+
$children = array_merge(
|
1811 |
+
get_posts(
|
1812 |
+
array(
|
1813 |
+
'post_type' => 'product_variation',
|
1814 |
+
'posts_per_page' => -1,
|
1815 |
+
'post_parent' => $post_id,
|
1816 |
+
'fields' => 'ids',
|
1817 |
+
)
|
1818 |
+
),
|
1819 |
+
$children
|
1820 |
+
);
|
1821 |
+
}
|
1822 |
+
$post_ids = array_merge( $post_ids, $children );
|
1823 |
+
$this->delete_post_meta_loop( $post_ids );
|
1824 |
+
|
1825 |
+
WC_Facebookcommerce_Utils::log( 'Product FBIDs deleted' );
|
1826 |
+
return true;
|
1827 |
+
}
|
1828 |
+
|
1829 |
+
/**
|
1830 |
+
* Remove FBIDs from a single WC product
|
1831 |
+
**/
|
1832 |
+
function reset_single_product( $wp_id ) {
|
1833 |
+
$woo_product = new WC_Facebook_Product( $wp_id );
|
1834 |
+
$products = array( $woo_product->get_id() );
|
1835 |
+
if ( WC_Facebookcommerce_Utils::is_variable_type( $woo_product->get_type() ) ) {
|
1836 |
+
$products = array_merge( $products, $woo_product->get_children() );
|
1837 |
+
}
|
1838 |
+
|
1839 |
+
$this->delete_post_meta_loop( $products );
|
1840 |
+
|
1841 |
+
WC_Facebookcommerce_Utils::log( 'Deleted FB Metadata for product ' . $wp_id );
|
1842 |
+
}
|
1843 |
+
|
1844 |
+
function ajax_reset_all_fb_products() {
|
1845 |
+
WC_Facebookcommerce_Utils::check_woo_ajax_permissions( 'reset products', true );
|
1846 |
+
check_ajax_referer( 'wc_facebook_settings_jsx' );
|
1847 |
+
$this->reset_all_products();
|
1848 |
+
wp_reset_postdata();
|
1849 |
+
wp_die();
|
1850 |
+
}
|
1851 |
+
|
1852 |
+
function ajax_reset_single_fb_product() {
|
1853 |
+
WC_Facebookcommerce_Utils::check_woo_ajax_permissions( 'reset single product', true );
|
1854 |
+
check_ajax_referer( 'wc_facebook_metabox_jsx' );
|
1855 |
+
if ( ! isset( $_POST['wp_id'] ) ) {
|
1856 |
+
wp_die();
|
1857 |
+
}
|
1858 |
+
|
1859 |
+
$wp_id = sanitize_text_field( $_POST['wp_id'] );
|
1860 |
+
$woo_product = new WC_Facebook_Product( $wp_id );
|
1861 |
+
if ( $woo_product ) {
|
1862 |
+
$this->reset_single_product( $wp_id );
|
1863 |
+
}
|
1864 |
+
|
1865 |
+
wp_reset_postdata();
|
1866 |
+
wp_die();
|
1867 |
+
}
|
1868 |
+
|
1869 |
+
function ajax_delete_fb_product() {
|
1870 |
+
WC_Facebookcommerce_Utils::check_woo_ajax_permissions( 'delete single product', true );
|
1871 |
+
check_ajax_referer( 'wc_facebook_metabox_jsx' );
|
1872 |
+
if ( ! isset( $_POST['wp_id'] ) ) {
|
1873 |
+
wp_die();
|
1874 |
+
}
|
1875 |
+
|
1876 |
+
$wp_id = sanitize_text_field( $_POST['wp_id'] );
|
1877 |
+
$this->on_product_delete( $wp_id );
|
1878 |
+
$this->reset_single_product( $wp_id );
|
1879 |
+
wp_reset_postdata();
|
1880 |
+
wp_die();
|
1881 |
+
}
|
1882 |
+
|
1883 |
+
/**
|
1884 |
+
* Special function to run all visible products through on_product_publish
|
1885 |
+
**/
|
1886 |
+
function ajax_sync_all_fb_products() {
|
1887 |
+
WC_Facebookcommerce_Utils::check_woo_ajax_permissions( 'syncall products', true );
|
1888 |
+
check_ajax_referer( 'wc_facebook_settings_jsx' );
|
1889 |
+
if ( get_option( 'fb_disable_sync_on_dev_environment', false ) ) {
|
1890 |
+
WC_Facebookcommerce_Utils::log(
|
1891 |
+
'Sync to FB Page is not allowed in Dev Environment'
|
1892 |
+
);
|
1893 |
+
wp_die();
|
1894 |
+
return;
|
1895 |
+
}
|
1896 |
+
|
1897 |
+
if ( ! $this->api_key || ! $this->product_catalog_id ) {
|
1898 |
+
WC_Facebookcommerce_Utils::log(
|
1899 |
+
'No API key or catalog ID: ' .
|
1900 |
+
$this->api_key . ' and ' . $this->product_catalog_id
|
1901 |
+
);
|
1902 |
+
wp_die();
|
1903 |
+
return;
|
1904 |
+
}
|
1905 |
+
$this->remove_resync_message();
|
1906 |
+
|
1907 |
+
$currently_syncing = get_transient( self::FB_SYNC_IN_PROGRESS );
|
1908 |
+
|
1909 |
+
if ( isset( $this->background_processor ) ) {
|
1910 |
+
if ( $this->background_processor->is_updating() ) {
|
1911 |
+
$this->background_processor->handle_cron_healthcheck();
|
1912 |
+
$currently_syncing = 1;
|
1913 |
+
}
|
1914 |
+
}
|
1915 |
+
|
1916 |
+
if ( $currently_syncing ) {
|
1917 |
+
WC_Facebookcommerce_Utils::log( 'Not syncing, sync in progress' );
|
1918 |
+
WC_Facebookcommerce_Utils::fblog(
|
1919 |
+
'Tried to sync during an in-progress sync!',
|
1920 |
+
array(),
|
1921 |
+
true
|
1922 |
+
);
|
1923 |
+
$this->display_warning_message(
|
1924 |
+
'A product sync is in progress.
|
1925 |
+
Please wait until the sync finishes before starting a new one.'
|
1926 |
+
);
|
1927 |
+
wp_die();
|
1928 |
+
return;
|
1929 |
+
}
|
1930 |
+
|
1931 |
+
$is_valid_product_catalog =
|
1932 |
+
$this->fbgraph->validate_product_catalog( $this->product_catalog_id );
|
1933 |
+
|
1934 |
+
if ( ! $is_valid_product_catalog ) {
|
1935 |
+
WC_Facebookcommerce_Utils::log( 'Not syncing, invalid product catalog!' );
|
1936 |
+
WC_Facebookcommerce_Utils::fblog(
|
1937 |
+
'Tried to sync with an invalid product catalog!',
|
1938 |
+
array(),
|
1939 |
+
true
|
1940 |
+
);
|
1941 |
+
$this->display_warning_message(
|
1942 |
+
'We\'ve detected that your
|
1943 |
Facebook Product Catalog is no longer valid. This may happen if it was
|
1944 |
deleted, or this may be a transient error.
|
1945 |
If this error persists please remove your settings via
|
1946 |
"Advanced Options > Advanced Settings > Remove"
|
1947 |
+
and try setup again'
|
1948 |
+
);
|
1949 |
+
wp_die();
|
1950 |
+
return;
|
1951 |
+
}
|
1952 |
+
|
1953 |
+
// Cache the cart URL to display a warning in case it changes later
|
1954 |
+
$cart_url = get_option( self::FB_CART_URL );
|
1955 |
+
if ( $cart_url != wc_get_cart_url() ) {
|
1956 |
+
update_option( self::FB_CART_URL, wc_get_cart_url() );
|
1957 |
+
}
|
1958 |
+
|
1959 |
+
$sanitized_settings = $this->settings;
|
1960 |
+
unset( $sanitized_settings['fb_api_key'] );
|
1961 |
+
|
1962 |
+
// Get all published posts. First unsynced then already-synced.
|
1963 |
+
$post_ids_new = WC_Facebookcommerce_Utils::get_wp_posts(
|
1964 |
+
self::FB_PRODUCT_GROUP_ID,
|
1965 |
+
'NOT EXISTS'
|
1966 |
+
);
|
1967 |
+
$post_ids_old = WC_Facebookcommerce_Utils::get_wp_posts(
|
1968 |
+
self::FB_PRODUCT_GROUP_ID,
|
1969 |
+
'EXISTS'
|
1970 |
+
);
|
1971 |
+
|
1972 |
+
$total_new = count( $post_ids_new );
|
1973 |
+
$total_old = count( $post_ids_old );
|
1974 |
+
$post_ids = array_merge( $post_ids_new, $post_ids_old );
|
1975 |
+
$total = count( $post_ids );
|
1976 |
+
|
1977 |
+
WC_Facebookcommerce_Utils::fblog(
|
1978 |
+
'Attempting to sync ' . $total . ' ( ' .
|
1979 |
+
$total_new . ' new) products with settings: ',
|
1980 |
+
$sanitized_settings,
|
1981 |
+
false
|
1982 |
+
);
|
1983 |
+
|
1984 |
+
// Check for background processing (Woo 3.x.x)
|
1985 |
+
if ( isset( $this->background_processor ) ) {
|
1986 |
+
$starting_message = sprintf(
|
1987 |
+
'Starting background sync to Facebook: %d products...',
|
1988 |
+
$total
|
1989 |
+
);
|
1990 |
+
|
1991 |
+
set_transient(
|
1992 |
+
self::FB_SYNC_IN_PROGRESS,
|
1993 |
+
true,
|
1994 |
+
self::FB_SYNC_TIMEOUT
|
1995 |
+
);
|
1996 |
+
|
1997 |
+
set_transient(
|
1998 |
+
self::FB_SYNC_REMAINING,
|
1999 |
+
(int) $total
|
2000 |
+
);
|
2001 |
+
|
2002 |
+
$this->display_info_message( $starting_message );
|
2003 |
+
WC_Facebookcommerce_Utils::log( $starting_message );
|
2004 |
+
|
2005 |
+
foreach ( $post_ids as $post_id ) {
|
2006 |
+
WC_Facebookcommerce_Utils::log( 'Pushing post to queue: ' . $post_id );
|
2007 |
+
$this->background_processor->push_to_queue( $post_id );
|
2008 |
+
}
|
2009 |
+
|
2010 |
+
$this->background_processor->save()->dispatch();
|
2011 |
+
// reset FB_SYNC_REMAINING to avoid race condition
|
2012 |
+
set_transient(
|
2013 |
+
self::FB_SYNC_REMAINING,
|
2014 |
+
(int) $total
|
2015 |
+
);
|
2016 |
+
// handle_cron_healthcheck must be called
|
2017 |
+
// https://github.com/A5hleyRich/wp-background-processing/issues/34
|
2018 |
+
$this->background_processor->handle_cron_healthcheck();
|
2019 |
+
} else {
|
2020 |
+
// Oldschool sync for WooCommerce 2.x
|
2021 |
+
$count = ( $total_old === $total ) ? 0 : $total_old;
|
2022 |
+
foreach ( $post_ids as $post_id ) {
|
2023 |
+
// Repeatedly overwrite sync total while in actual sync loop
|
2024 |
+
set_transient(
|
2025 |
+
self::FB_SYNC_IN_PROGRESS,
|
2026 |
+
true,
|
2027 |
+
self::FB_SYNC_TIMEOUT
|
2028 |
+
);
|
2029 |
+
|
2030 |
+
$this->display_sticky_message(
|
2031 |
+
sprintf(
|
2032 |
+
'Syncing products to Facebook: %d out of %d...',
|
2033 |
+
// Display different # when resuming to avoid confusion.
|
2034 |
+
min( $count, $total ),
|
2035 |
+
$total
|
2036 |
+
),
|
2037 |
+
true
|
2038 |
+
);
|
2039 |
+
|
2040 |
+
$this->on_product_publish( $post_id );
|
2041 |
+
$count++;
|
2042 |
+
}
|
2043 |
+
WC_Facebookcommerce_Utils::log( 'Synced ' . $count . ' products' );
|
2044 |
+
$this->remove_sticky_message();
|
2045 |
+
$this->display_info_message( 'Facebook product sync complete!' );
|
2046 |
+
delete_transient( self::FB_SYNC_IN_PROGRESS );
|
2047 |
+
WC_Facebookcommerce_Utils::fblog(
|
2048 |
+
'Product sync complete. Total products synced: ' . $count
|
2049 |
+
);
|
2050 |
+
}
|
2051 |
+
|
2052 |
+
// https://codex.wordpress.org/Function_Reference/wp_reset_postdata
|
2053 |
+
wp_reset_postdata();
|
2054 |
+
|
2055 |
+
// This is important, for some reason.
|
2056 |
+
// See https://codex.wordpress.org/AJAX_in_Plugins
|
2057 |
+
wp_die();
|
2058 |
+
}
|
2059 |
+
|
2060 |
+
/**
|
2061 |
+
* Special function to run all visible products by uploading feed.
|
2062 |
+
**/
|
2063 |
+
function ajax_sync_all_fb_products_using_feed() {
|
2064 |
+
WC_Facebookcommerce_Utils::check_woo_ajax_permissions(
|
2065 |
+
'syncall products using feed',
|
2066 |
+
! $this->test_mode
|
2067 |
+
);
|
2068 |
+
check_ajax_referer( 'wc_facebook_settings_jsx' );
|
2069 |
+
return $this->sync_all_fb_products_using_feed();
|
2070 |
+
}
|
2071 |
+
|
2072 |
+
// Separate entry point that bypasses permission check for use in cron.
|
2073 |
+
function sync_all_fb_products_using_feed() {
|
2074 |
+
if ( get_option( 'fb_disable_sync_on_dev_environment', false ) ) {
|
2075 |
+
WC_Facebookcommerce_Utils::log(
|
2076 |
+
'Sync to FB Page is not allowed in Dev Environment'
|
2077 |
+
);
|
2078 |
+
$this->fb_wp_die();
|
2079 |
+
return false;
|
2080 |
+
}
|
2081 |
+
|
2082 |
+
if ( ! $this->api_key || ! $this->product_catalog_id ) {
|
2083 |
+
self::log(
|
2084 |
+
'No API key or catalog ID: ' . $this->api_key .
|
2085 |
+
' and ' . $this->product_catalog_id
|
2086 |
+
);
|
2087 |
+
$this->fb_wp_die();
|
2088 |
+
return false;
|
2089 |
+
}
|
2090 |
+
$this->remove_resync_message();
|
2091 |
+
$is_valid_product_catalog =
|
2092 |
+
$this->fbgraph->validate_product_catalog( $this->product_catalog_id );
|
2093 |
+
|
2094 |
+
if ( ! $is_valid_product_catalog ) {
|
2095 |
+
WC_Facebookcommerce_Utils::log( 'Not syncing, invalid product catalog!' );
|
2096 |
+
WC_Facebookcommerce_Utils::fblog(
|
2097 |
+
'Tried to sync with an invalid product catalog!',
|
2098 |
+
array(),
|
2099 |
+
true
|
2100 |
+
);
|
2101 |
+
$this->display_warning_message(
|
2102 |
+
'We\'ve detected that your
|
2103 |
Facebook Product Catalog is no longer valid. This may happen if it was
|
2104 |
deleted, or this may be a transient error.
|
2105 |
If this error persists please remove your settings via
|
2106 |
"Advanced Options > Advanced Settings > Remove"
|
2107 |
+
and try setup again'
|
2108 |
+
);
|
2109 |
+
$this->fb_wp_die();
|
2110 |
+
return false;
|
2111 |
+
}
|
2112 |
+
|
2113 |
+
// Cache the cart URL to display a warning in case it changes later
|
2114 |
+
$cart_url = get_option( self::FB_CART_URL );
|
2115 |
+
if ( $cart_url != wc_get_cart_url() ) {
|
2116 |
+
update_option( self::FB_CART_URL, wc_get_cart_url() );
|
2117 |
+
}
|
2118 |
+
|
2119 |
+
if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) {
|
2120 |
+
include_once 'includes/fbproductfeed.php';
|
2121 |
+
}
|
2122 |
+
if ( $this->test_mode ) {
|
2123 |
+
$this->fbproductfeed = new WC_Facebook_Product_Feed_Test_Mock(
|
2124 |
+
$this->product_catalog_id,
|
2125 |
+
$this->fbgraph,
|
2126 |
+
$this->feed_id
|
2127 |
+
);
|
2128 |
+
} else {
|
2129 |
+
$this->fbproductfeed = new WC_Facebook_Product_Feed(
|
2130 |
+
$this->product_catalog_id,
|
2131 |
+
$this->fbgraph,
|
2132 |
+
$this->feed_id
|
2133 |
+
);
|
2134 |
+
}
|
2135 |
+
|
2136 |
+
$upload_success = $this->fbproductfeed->sync_all_products_using_feed();
|
2137 |
+
if ( $upload_success ) {
|
2138 |
+
$this->settings['fb_feed_id'] = $this->fbproductfeed->feed_id;
|
2139 |
+
$this->settings['fb_upload_id'] = $this->fbproductfeed->upload_id;
|
2140 |
+
update_option(
|
2141 |
+
$this->get_option_key(),
|
2142 |
+
apply_filters(
|
2143 |
+
'woocommerce_settings_api_sanitized_fields_' .
|
2144 |
+
$this->id,
|
2145 |
+
$this->settings
|
2146 |
+
)
|
2147 |
+
);
|
2148 |
+
wp_reset_postdata();
|
2149 |
+
$this->fb_wp_die();
|
2150 |
+
return true;
|
2151 |
+
}
|
2152 |
+
WC_Facebookcommerce_Utils::fblog(
|
2153 |
+
'Sync all products using feed, curl failed',
|
2154 |
+
array(),
|
2155 |
+
true
|
2156 |
+
);
|
2157 |
+
return false;
|
2158 |
+
}
|
2159 |
+
|
2160 |
+
/**
|
2161 |
+
* Toggles product visibility via AJAX (checks current viz and flips it)
|
2162 |
+
**/
|
2163 |
+
function ajax_fb_toggle_visibility() {
|
2164 |
+
WC_Facebookcommerce_Utils::check_woo_ajax_permissions( 'toggle visibility', true );
|
2165 |
+
check_ajax_referer( 'wc_facebook_product_jsx' );
|
2166 |
+
if ( ! isset( $_POST['wp_id'] ) || ! isset( $_POST['published'] ) ) {
|
2167 |
+
wp_die();
|
2168 |
+
}
|
2169 |
+
|
2170 |
+
$wp_id = sanitize_text_field( $_POST['wp_id'] );
|
2171 |
+
$published = ( $_POST['published'] ) === 'true' ? true : false;
|
2172 |
+
|
2173 |
+
$woo_product = new WC_Facebook_Product( $wp_id );
|
2174 |
+
$products = WC_Facebookcommerce_Utils::get_product_array( $woo_product );
|
2175 |
+
|
2176 |
+
// Loop through product items and flip visibility
|
2177 |
+
foreach ( $products as $item_id ) {
|
2178 |
+
$fb_product_item_id = $this->get_product_fbid(
|
2179 |
+
self::FB_PRODUCT_ITEM_ID,
|
2180 |
+
$item_id
|
2181 |
+
);
|
2182 |
+
$data = array(
|
2183 |
+
'visibility' => $published ? 'published' : 'staging',
|
2184 |
+
);
|
2185 |
+
|
2186 |
+
$result = $this->check_api_result(
|
2187 |
+
$this->fbgraph->update_product_item(
|
2188 |
+
$fb_product_item_id,
|
2189 |
+
$data
|
2190 |
+
)
|
2191 |
+
);
|
2192 |
+
|
2193 |
+
if ( $result ) {
|
2194 |
+
update_post_meta( $item_id, self::FB_VISIBILITY, $published );
|
2195 |
+
update_post_meta( $wp_id, self::FB_VISIBILITY, $published );
|
2196 |
+
}
|
2197 |
+
}
|
2198 |
+
wp_die();
|
2199 |
+
}
|
2200 |
+
|
2201 |
+
/**
|
2202 |
+
* Initialize Settings Form Fields
|
2203 |
+
*
|
2204 |
+
* @access public
|
2205 |
+
* @return void
|
2206 |
+
*/
|
2207 |
+
function init_form_fields() {
|
2208 |
+
$this->form_fields = array(
|
2209 |
+
'fb_settings_heading' => array(
|
2210 |
+
'title' => __( 'Debug Mode', 'facebook-for-woocommerce' ),
|
2211 |
+
'type' => 'title',
|
2212 |
+
'description' => '',
|
2213 |
+
'default' => '',
|
2214 |
+
),
|
2215 |
+
'fb_page_id' => array(
|
2216 |
+
'title' => __( 'Facebook Page ID', 'facebook-for-woocommerce' ),
|
2217 |
+
'type' => 'text',
|
2218 |
+
'description' => __(
|
2219 |
+
'The unique identifier for your Facebook page.',
|
2220 |
+
'facebook-for-woocommerce'
|
2221 |
+
),
|
2222 |
+
'default' => '',
|
2223 |
+
),
|
2224 |
+
'fb_product_catalog_id' => array(
|
2225 |
+
'title' => __( 'Product Catalog ID', 'facebook-for-woocommerce' ),
|
2226 |
+
'type' => 'text',
|
2227 |
+
'description' => __(
|
2228 |
+
'The unique identifier for your product catalog,
|
2229 |
+
on Facebook.',
|
2230 |
+
'facebook-for-woocommerce'
|
2231 |
+
),
|
2232 |
+
'default' => '',
|
2233 |
+
),
|
2234 |
+
'fb_pixel_id' => array(
|
2235 |
+
'title' => __( 'Pixel ID', 'facebook-for-woocommerce' ),
|
2236 |
+
'type' => 'text',
|
2237 |
+
'description' => __(
|
2238 |
+
'The unique identifier for your Facebook pixel',
|
2239 |
+
'facebook-for-woocommerce'
|
2240 |
+
),
|
2241 |
+
'default' => '',
|
2242 |
+
),
|
2243 |
+
'fb_pixel_use_pii' => array(
|
2244 |
+
'title' => __(
|
2245 |
+
'Use Advanced Matching on pixel?',
|
2246 |
+
'facebook-for-woocommerce'
|
2247 |
+
),
|
2248 |
+
'type' => 'checkbox',
|
2249 |
+
'description' => __(
|
2250 |
+
'Enabling Advanced Matching
|
2251 |
+
improves audience building.',
|
2252 |
+
'facebook-for-woocommerce'
|
2253 |
+
),
|
2254 |
+
'default' => 'yes',
|
2255 |
+
),
|
2256 |
+
'fb_external_merchant_settings_id' => array(
|
2257 |
+
'title' => __(
|
2258 |
+
'External Merchant Settings ID',
|
2259 |
+
'facebook-for-woocommerce'
|
2260 |
+
),
|
2261 |
+
'type' => 'text',
|
2262 |
+
'description' => __(
|
2263 |
+
'The unique identifier for your external merchant
|
2264 |
+
settings, on Facebook.',
|
2265 |
+
'facebook-for-woocommerce'
|
2266 |
+
),
|
2267 |
+
'default' => '',
|
2268 |
+
),
|
2269 |
+
'fb_api_key' => array(
|
2270 |
+
'title' => __( 'API Key', 'facebook-for-woocommerce' ),
|
2271 |
+
'type' => 'text',
|
2272 |
+
'description' => sprintf(
|
2273 |
+
__(
|
2274 |
+
'A non-expiring Page Token with
|
2275 |
+
%1$smanage_pages%2$s permissions.',
|
2276 |
+
'facebook-for-woocommerce'
|
2277 |
+
),
|
2278 |
+
'<code>',
|
2279 |
+
'</code>'
|
2280 |
+
),
|
2281 |
+
'default' => '',
|
2282 |
+
),
|
2283 |
+
);
|
2284 |
+
|
2285 |
+
if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) {
|
2286 |
+
include_once 'includes/fbutils.php';
|
2287 |
+
}
|
2288 |
+
} // End init_form_fields()
|
2289 |
+
|
2290 |
+
|
2291 |
+
/**
|
2292 |
+
* Get message
|
2293 |
+
*
|
2294 |
+
* @return string Error
|
2295 |
+
*/
|
2296 |
+
private function get_message_html( $message, $type = 'error' ) {
|
2297 |
+
ob_start();
|
2298 |
+
|
2299 |
+
?>
|
2300 |
+
<div class="notice is-dismissible notice-<?php echo $type; ?>">
|
2301 |
+
<p><?php echo $message; ?></p>
|
2302 |
+
</div>
|
2303 |
+
<?php
|
2304 |
+
return ob_get_clean();
|
2305 |
+
}
|
2306 |
+
|
2307 |
+
/**
|
2308 |
+
* Display relevant messages to user from transients, clear once displayed
|
2309 |
+
*
|
2310 |
+
* @param void
|
2311 |
+
*/
|
2312 |
+
public function maybe_display_facebook_api_messages() {
|
2313 |
+
$error_msg = get_transient( 'facebook_plugin_api_error' );
|
2314 |
+
|
2315 |
+
if ( $error_msg ) {
|
2316 |
+
echo $this->get_message_html(
|
2317 |
+
sprintf(
|
2318 |
+
__(
|
2319 |
+
'Facebook extension error: %s ',
|
2320 |
+
'facebook-for-woocommerce'
|
2321 |
+
),
|
2322 |
+
$error_msg
|
2323 |
+
)
|
2324 |
+
);
|
2325 |
+
delete_transient( 'facebook_plugin_api_error' );
|
2326 |
+
|
2327 |
+
WC_Facebookcommerce_Utils::fblog(
|
2328 |
+
$error_msg,
|
2329 |
+
array(),
|
2330 |
+
true
|
2331 |
+
);
|
2332 |
+
}
|
2333 |
+
|
2334 |
+
$warning_msg = get_transient( 'facebook_plugin_api_warning' );
|
2335 |
+
|
2336 |
+
if ( $warning_msg ) {
|
2337 |
+
echo $this->get_message_html(
|
2338 |
+
__( $warning_msg, 'facebook-for-woocommerce' ),
|
2339 |
+
'warning'
|
2340 |
+
);
|
2341 |
+
delete_transient( 'facebook_plugin_api_warning' );
|
2342 |
+
}
|
2343 |
+
|
2344 |
+
$success_msg = get_transient( 'facebook_plugin_api_success' );
|
2345 |
+
|
2346 |
+
if ( $success_msg ) {
|
2347 |
+
echo $this->get_message_html(
|
2348 |
+
__( $success_msg, 'facebook-for-woocommerce' ),
|
2349 |
+
'success'
|
2350 |
+
);
|
2351 |
+
delete_transient( 'facebook_plugin_api_success' );
|
2352 |
+
}
|
2353 |
+
|
2354 |
+
$info_msg = get_transient( 'facebook_plugin_api_info' );
|
2355 |
+
|
2356 |
+
if ( $info_msg ) {
|
2357 |
+
echo $this->get_message_html(
|
2358 |
+
__( $info_msg, 'facebook-for-woocommerce' ),
|
2359 |
+
'info'
|
2360 |
+
);
|
2361 |
+
delete_transient( 'facebook_plugin_api_info' );
|
2362 |
+
}
|
2363 |
+
|
2364 |
+
$sticky_msg = get_transient( 'facebook_plugin_api_sticky' );
|
2365 |
+
|
2366 |
+
if ( $sticky_msg ) {
|
2367 |
+
echo $this->get_message_html(
|
2368 |
+
__( $sticky_msg, 'facebook-for-woocommerce' ),
|
2369 |
+
'info'
|
2370 |
+
);
|
2371 |
+
// Transient must be deleted elsewhere, or wait for timeout
|
2372 |
+
}
|
2373 |
+
|
2374 |
+
}
|
2375 |
+
|
2376 |
+
function get_page_name() {
|
2377 |
+
$page_name = '';
|
2378 |
+
if ( ! empty( $this->settings['fb_page_id'] ) &&
|
2379 |
+
! empty( $this->settings['fb_api_key'] ) ) {
|
2380 |
+
|
2381 |
+
$page_name = $this->fbgraph->get_page_name(
|
2382 |
+
$this->settings['fb_page_id'],
|
2383 |
+
$this->settings['fb_api_key']
|
2384 |
+
);
|
2385 |
+
}
|
2386 |
+
return $page_name;
|
2387 |
+
}
|
2388 |
+
|
2389 |
+
function get_nux_message_ifexist() {
|
2390 |
+
$nux_type_to_elemid_map = array(
|
2391 |
+
'messenger_chat' => 'connect_button',
|
2392 |
+
'instagram_shopping' => 'connect_button',
|
2393 |
+
);
|
2394 |
+
$nux_type_to_message_map = array(
|
2395 |
+
'messenger_chat' => __( 'Get started with Messenger Customer Chat' ),
|
2396 |
+
'instagram_shopping' => __( 'Get started with Instagram Shopping' ),
|
2397 |
+
);
|
2398 |
+
if ( isset( $_GET['nux'] ) ) {
|
2399 |
+
return sprintf(
|
2400 |
+
'<div class="nux-message" style="display: none;" data-target="%s">
|
2401 |
<div class="nux-message-text">%s</div>
|
2402 |
<div class="nux-message-arrow"></div>
|
2403 |
<i class="nux-message-close-btn">x</i>
|
2404 |
</div>
|
2405 |
<script>(function() { fbe_init_nux_messages(); })();</script>',
|
2406 |
+
$nux_type_to_elemid_map[ sanitize_text_field( $_GET['nux'] ) ],
|
2407 |
+
$nux_type_to_message_map[ sanitize_text_field( $_GET['nux'] ) ]
|
2408 |
+
);
|
2409 |
+
} else {
|
2410 |
+
return '';
|
2411 |
+
}
|
2412 |
+
}
|
2413 |
+
|
2414 |
+
/**
|
2415 |
+
* Admin Panel Options
|
2416 |
+
*/
|
2417 |
+
function admin_options() {
|
2418 |
+
$domain = 'facebook-for-woocommerce';
|
2419 |
+
$cta_button_text = __( 'Get Started', $domain );
|
2420 |
+
$page_name = $this->get_page_name();
|
2421 |
+
|
2422 |
+
$can_manage = current_user_can( 'manage_woocommerce' );
|
2423 |
+
$pre_setup = empty( $this->settings['fb_page_id'] ) ||
|
2424 |
+
empty( $this->settings['fb_api_key'] );
|
2425 |
+
$apikey_invalid = ! $pre_setup && $this->settings['fb_api_key'] && ! $page_name;
|
2426 |
+
|
2427 |
+
$redirect_uri = '';
|
2428 |
+
$remove_http_active = is_plugin_active( 'remove-http/remove-http.php' );
|
2429 |
+
$https_will_be_stripped = $remove_http_active &&
|
2430 |
+
! get_option( 'factmaven_rhttp' )['external'];
|
2431 |
+
if ( $https_will_be_stripped ) {
|
2432 |
+
$this->display_sticky_message(
|
2433 |
+
__(
|
2434 |
+
'You\'re using Remove HTTP which has
|
2435 |
incompatibilities with our extension. Please disable it, or select the
|
2436 |
+
"Ignore external links" option on the Remove HTTP settings page.'
|
2437 |
+
)
|
2438 |
+
);
|
2439 |
+
}
|
2440 |
+
|
2441 |
+
if ( ! $pre_setup ) {
|
2442 |
+
$cta_button_text = __( 'Create Ad', $domain );
|
2443 |
+
$redirect_uri = 'https://www.facebook.com/ads/dia/redirect/?settings_id='
|
2444 |
+
. $this->external_merchant_settings_id . '&version=2' .
|
2445 |
+
'&entry_point=admin_panel';
|
2446 |
+
}
|
2447 |
+
$currently_syncing = get_transient( self::FB_SYNC_IN_PROGRESS );
|
2448 |
+
$connected = ( $page_name != '' );
|
2449 |
+
$hide_test = ( $connected && $currently_syncing ) || ! defined( 'WP_DEBUG' ) ||
|
2450 |
+
WP_DEBUG !== true;
|
2451 |
+
$nux_message = $this->get_nux_message_ifexist();
|
2452 |
+
?>
|
2453 |
+
<h2><?php _e( 'Facebook', $domain ); ?></h2>
|
2454 |
+
<p>
|
2455 |
+
<?php
|
2456 |
+
_e(
|
2457 |
+
'Control how WooCommerce integrates with your Facebook store.',
|
2458 |
+
$domain
|
2459 |
+
);
|
2460 |
+
?>
|
2461 |
+
</p>
|
2462 |
+
<hr/>
|
2463 |
+
|
2464 |
+
<div id="fbsetup">
|
2465 |
+
<div class="wrapper">
|
2466 |
+
<header>
|
2467 |
+
<div class="help-center">
|
2468 |
+
<a href="https://www.facebook.com/business/help/900699293402826" target="_blank">Help Center <i class="help-center-icon"></i></a>
|
2469 |
+
</div>
|
2470 |
+
</header>
|
2471 |
+
<div class="content">
|
2472 |
+
<h1 id="setup_h1">
|
2473 |
+
<?php
|
2474 |
+
$pre_setup
|
2475 |
+
? _e( 'Grow your business on Facebook', $domain )
|
2476 |
+
: _e( 'Reach The Right People and Sell More Online', $domain );
|
2477 |
+
?>
|
2478 |
+
</h1>
|
2479 |
+
<h2>
|
2480 |
+
<?php
|
2481 |
+
_e(
|
2482 |
+
'Use this WooCommerce and Facebook integration to:',
|
2483 |
+
$domain
|
2484 |
+
);
|
2485 |
+
?>
|
2486 |
+
</h2>
|
2487 |
+
<ul>
|
2488 |
+
<li id="setup_l1">
|
2489 |
+
<?php
|
2490 |
+
$pre_setup
|
2491 |
+
? _e( 'Easily install a tracking pixel', $domain )
|
2492 |
+
: _e( 'Create an ad in a few steps', $domain );
|
2493 |
+
?>
|
2494 |
+
</li>
|
2495 |
+
<li id="setup_l2">
|
2496 |
+
<?php
|
2497 |
+
$pre_setup
|
2498 |
+
? _e( 'Upload your products and create a shop', $domain )
|
2499 |
+
: _e( 'Use built-in best practices for online sales', $domain );
|
2500 |
+
?>
|
2501 |
+
</li>
|
2502 |
+
<li id="setup_l3">
|
2503 |
+
<?php
|
2504 |
+
$pre_setup
|
2505 |
+
? _e( 'Create dynamic ads with your products and pixel', $domain )
|
2506 |
+
: _e( 'Get reporting on sales and revenue', $domain );
|
2507 |
+
?>
|
2508 |
+
</li>
|
2509 |
+
</ul>
|
2510 |
+
<span
|
2511 |
+
<?php
|
2512 |
+
if ( $pre_setup ) {
|
2513 |
+
if ( ! $can_manage ) {
|
2514 |
+
echo ' style="pointer-events: none;"';
|
2515 |
+
}
|
2516 |
+
echo '><a href="#" class="btn pre-setup" onclick="facebookConfig()"
|
2517 |
+
id="cta_button">' . esc_html( $cta_button_text ) . '</a></span>';
|
2518 |
+
} else {
|
2519 |
+
if ( ! $can_manage || $apikey_invalid ||
|
2520 |
+
! isset( $this->external_merchant_settings_id ) ) {
|
2521 |
+
echo ' style="pointer-events: none;"';
|
2522 |
+
}
|
2523 |
+
echo (
|
2524 |
+
'><a href=' . $redirect_uri . ' class="btn" id="cta_button">' .
|
2525 |
+
esc_html( $cta_button_text ) . '</a>' .
|
2526 |
+
'<a href="https://www.facebook.com/business/m/drive-more-online-sales"
|
2527 |
+
class="btn grey" id="learnmore_button">' . __( 'Learn More' ) .
|
2528 |
+
'</a></span>'
|
2529 |
+
);
|
2530 |
+
}
|
2531 |
+
?>
|
2532 |
+
<hr />
|
2533 |
+
<div class="settings-container">
|
2534 |
+
<div id="plugins" class="settings-section"
|
2535 |
+
<?php echo ( $pre_setup && $can_manage ) ? ' style="display:none;"' : ''; ?>
|
2536 |
+
>
|
2537 |
+
<h1><?php echo __( 'Add Ways for People to Shop' ); ?></h1>
|
2538 |
+
<h2><?php echo __( 'Connect your business with features such as Messenger and more.' ); ?></h2>
|
2539 |
+
<a href="#" class="btn small" onclick="facebookConfig()" id="connect_button">
|
2540 |
+
<?php echo __( 'Add Features' ); ?>
|
2541 |
+
</a>
|
2542 |
+
</div>
|
2543 |
+
<div id="settings" class="settings-section"
|
2544 |
+
<?php
|
2545 |
+
if ( $pre_setup && $can_manage ) {
|
2546 |
+
echo ' style="display:none;"';
|
2547 |
+
}
|
2548 |
+
echo '><h1>' . esc_html__( 'Settings', $domain ) . '</h1>';
|
2549 |
+
if ( $apikey_invalid ) {
|
2550 |
+
// API key is set, but no page name.
|
2551 |
+
echo '<h2 id="token_text" style="color:red;">' .
|
2552 |
+
__(
|
2553 |
+
'Your API key is no longer valid. Please click "Settings >
|
2554 |
+
Advanced Options > Update Token".',
|
2555 |
+
$domain
|
2556 |
+
) . '</h2>
|
2557 |
|
2558 |
<span><a href="#" class="btn small" onclick="facebookConfig()"
|
2559 |
+
id="setting_button">' . __( 'Settings', $domain ) . '</a>
|
2560 |
</span>';
|
2561 |
+
} else {
|
2562 |
+
if ( ! $can_manage ) {
|
2563 |
+
echo '<h2 style="color:red;">' . __(
|
2564 |
+
'You must have
|
2565 |
+
"manage_woocommerce" permissions to use this plugin.',
|
2566 |
+
$domain
|
2567 |
+
) .
|
2568 |
+
'</h2>';
|
2569 |
+
} else {
|
2570 |
+
echo '<h2><span id="connection_status"';
|
2571 |
+
if ( ! $connected ) {
|
2572 |
+
echo ' style="display: none;"';
|
2573 |
+
}
|
2574 |
+
echo '>';
|
2575 |
+
echo __( 'Your WooCommerce store is connected to ', $domain ) .
|
2576 |
+
( ( $page_name != '' )
|
2577 |
+
? sprintf(
|
2578 |
+
__( 'the Facebook page <a target="_blank" href="https://www.facebook.com/%1$s">%2$s</a></span>', $domain ),
|
2579 |
+
$this->settings['fb_page_id'],
|
2580 |
+
esc_html( $page_name )
|
2581 |
+
)
|
2582 |
+
: sprintf(
|
2583 |
+
__( '<a target="_blank" href="https://www.facebook.com/%1$s">your Facebook page</a></span>', $domain ),
|
2584 |
+
$this->settings['fb_page_id']
|
2585 |
+
)
|
2586 |
+
) .
|
2587 |
+
'.<span id="sync_complete" style="margin-left: 5px;';
|
2588 |
+
if ( ! $connected || $currently_syncing ) {
|
2589 |
+
echo ' display: none;';
|
2590 |
+
}
|
2591 |
+
echo '">' . __( 'Status', $domain ) . ': '
|
2592 |
+
. __( 'Products are synced to Facebook.', $domain ) . '</span>' .
|
2593 |
+
sprintf(
|
2594 |
+
__(
|
2595 |
+
'<span><a href="#" onclick="show_debug_info()"
|
2596 |
id="debug_info" style="display:none;" > More Info </a></span>',
|
2597 |
+
$domain
|
2598 |
+
)
|
2599 |
+
) . '</span></h2>
|
2600 |
<span><a href="#" class="btn small" onclick="facebookConfig()"
|
2601 |
id="setting_button"';
|
2602 |
|
2603 |
+
if ( $currently_syncing ) {
|
2604 |
+
echo ' style="pointer-events: none;" ';
|
2605 |
+
}
|
2606 |
+
echo '>' . __( 'Manage Settings', $domain ) . '</a></span>
|
2607 |
|
2608 |
<span><a href="#" class="btn small" onclick="sync_confirm()"
|
2609 |
id="resync_products"';
|
2610 |
|
2611 |
+
if ( $connected && $currently_syncing ) {
|
2612 |
+
echo ' style="pointer-events: none;" ';
|
2613 |
+
}
|
2614 |
+
echo '>' . __( 'Sync Products', $domain ) . '</a></span>
|
2615 |
|
2616 |
<p id="sync_progress">';
|
2617 |
+
if ( $connected && $currently_syncing ) {
|
2618 |
+
echo '<hr/>';
|
2619 |
+
echo __( 'Syncing... Keep this browser open', $domain );
|
2620 |
+
echo '<br/>';
|
2621 |
+
echo __( 'Until sync is complete', $domain );
|
2622 |
+
}
|
2623 |
+
echo '</p>';
|
2624 |
+
}
|
2625 |
+
}
|
2626 |
+
?>
|
2627 |
+
</div>
|
2628 |
+
<hr />
|
2629 |
+
</div>
|
2630 |
+
<?php echo $nux_message; ?>
|
2631 |
+
|
2632 |
+
<div>
|
2633 |
+
<div id='fbAdvancedOptionsText' onclick="toggleAdvancedOptions();">
|
2634 |
+
Show Advanced Settings
|
2635 |
+
</div>
|
2636 |
+
<div id='fbAdvancedOptions'>
|
2637 |
+
<div class='autosync' title="This experimental feature will call force resync at the specified time using WordPress cron scheduling.">
|
2638 |
+
<input type="checkbox"
|
2639 |
+
onclick="saveAutoSyncSchedule()"
|
2640 |
+
class="autosyncCheck"
|
2641 |
+
<?php echo get_option( 'woocommerce_fb_autosync_time', false ) ? 'checked' : 'unchecked'; ?>>
|
2642 |
+
Automatically Force Resync of Products At
|
2643 |
+
|
2644 |
+
<input
|
2645 |
+
type="time"
|
2646 |
+
value="<?php echo get_option( 'woocommerce_fb_autosync_time', '23:00' ); ?>"
|
2647 |
+
class="autosyncTime"
|
2648 |
+
onfocusout="saveAutoSyncSchedule()"
|
2649 |
+
<?php echo get_option( 'woocommerce_fb_autosync_time', 0 ) ? '' : 'disabled'; ?> />
|
2650 |
+
Every Day.
|
2651 |
+
<span class="autosyncSavedNotice" disabled> Saved </span>
|
2652 |
+
</div>
|
2653 |
+
<div title="This option is meant for development and testing environments.">
|
2654 |
+
<input type="checkbox"
|
2655 |
+
onclick="onSetDisableSyncOnDevEnvironment()"
|
2656 |
+
class="disableOnDevEnvironment"
|
2657 |
+
<?php
|
2658 |
+
echo get_option( 'fb_disable_sync_on_dev_environment', false )
|
2659 |
+
? 'checked'
|
2660 |
+
: 'unchecked';
|
2661 |
+
?>
|
2662 |
+
/>
|
2663 |
+
Disable Product Sync with FB
|
2664 |
+
</div>
|
2665 |
+
<div class='shortdescr' title="This experimental feature will import short description instead of description for all products.">
|
2666 |
+
<input type="checkbox"
|
2667 |
+
onclick="syncShortDescription()"
|
2668 |
+
class="syncShortDescription"
|
2669 |
+
<?php
|
2670 |
+
echo get_option( 'fb_sync_short_description', false )
|
2671 |
+
? 'checked'
|
2672 |
+
: 'unchecked';
|
2673 |
+
?>
|
2674 |
+
/>
|
2675 |
+
Sync Short Description Instead of Description
|
2676 |
+
</div>
|
2677 |
+
</div>
|
2678 |
+
</div>
|
2679 |
+
</div>
|
2680 |
+
</div>
|
2681 |
+
<div <?php echo ( $hide_test ) ? ' style="display:none;" ' : ''; ?> >
|
2682 |
+
<p class="tooltip" id="test_product_sync">
|
2683 |
+
<?php
|
2684 |
+
// WP_DEBUG mode: button to launch test
|
2685 |
+
echo sprintf(
|
2686 |
+
__( '<a href="%s&fb_test_product_sync=true"', $domain ),
|
2687 |
+
WOOCOMMERCE_FACEBOOK_PLUGIN_SETTINGS_URL
|
2688 |
+
);
|
2689 |
+
echo '>' . esc_html__( 'Launch Test', $domain );
|
2690 |
+
?>
|
2691 |
+
<span class='tooltiptext'>
|
2692 |
+
<?php
|
2693 |
+
_e(
|
2694 |
+
'This button will run an integration test suite verifying the
|
2695 |
extension. Note that this will reset your products and resync them
|
2696 |
to Facebook. Not recommended to use unless you are changing the
|
2697 |
+
extension code and want to test your changes.',
|
2698 |
+
$domain
|
2699 |
+
);
|
2700 |
+
?>
|
2701 |
+
</span>
|
2702 |
+
<?php
|
2703 |
+
echo '</a>';
|
2704 |
+
?>
|
2705 |
+
</p>
|
2706 |
+
<p id="stack_trace"></p>
|
2707 |
+
</div>
|
2708 |
+
<br/><hr/><br/>
|
2709 |
+
<?php
|
2710 |
+
|
2711 |
+
$GLOBALS['hide_save_button'] = true;
|
2712 |
+
if ( defined( 'WP_DEBUG' ) && true === WP_DEBUG ) {
|
2713 |
+
$GLOBALS['hide_save_button'] = false;
|
2714 |
+
?>
|
2715 |
+
<table class="form-table">
|
2716 |
+
<?php $this->generate_settings_html(); ?>
|
2717 |
+
</table><!--/.form-table-->
|
2718 |
+
<?php
|
2719 |
+
}
|
2720 |
+
}
|
2721 |
+
|
2722 |
+
function delete_product_item( $wp_id ) {
|
2723 |
+
$fb_product_item_id = $this->get_product_fbid(
|
2724 |
+
self::FB_PRODUCT_ITEM_ID,
|
2725 |
+
$wp_id
|
2726 |
+
);
|
2727 |
+
if ( $fb_product_item_id ) {
|
2728 |
+
$pi_result =
|
2729 |
+
$this->fbgraph->delete_product_item( $fb_product_item_id );
|
2730 |
+
WC_Facebookcommerce_Utils::log( $pi_result );
|
2731 |
+
}
|
2732 |
+
}
|
2733 |
+
|
2734 |
+
function fb_duplicate_product_reset_meta( $to_delete ) {
|
2735 |
+
array_push( $to_delete, self::FB_PRODUCT_ITEM_ID );
|
2736 |
+
array_push( $to_delete, self::FB_PRODUCT_GROUP_ID );
|
2737 |
+
return $to_delete;
|
2738 |
+
}
|
2739 |
+
|
2740 |
+
/**
|
2741 |
+
* Helper function to update FB visibility.
|
2742 |
+
*/
|
2743 |
+
function update_fb_visibility( $wp_id, $visibility ) {
|
2744 |
+
$woo_product = new WC_Facebook_Product( $wp_id );
|
2745 |
+
if ( ! $woo_product->exists() ) {
|
2746 |
+
// This function can be called for non-woo products.
|
2747 |
+
return;
|
2748 |
+
}
|
2749 |
+
|
2750 |
+
$products = WC_Facebookcommerce_Utils::get_product_array( $woo_product );
|
2751 |
+
foreach ( $products as $item_id ) {
|
2752 |
+
$fb_product_item_id = $this->get_product_fbid(
|
2753 |
+
self::FB_PRODUCT_ITEM_ID,
|
2754 |
+
$item_id
|
2755 |
+
);
|
2756 |
+
|
2757 |
+
if ( ! $fb_product_item_id ) {
|
2758 |
+
WC_Facebookcommerce_Utils::fblog(
|
2759 |
+
$fb_product_item_id . " doesn't exist but underwent a visibility transform.",
|
2760 |
+
array(),
|
2761 |
+
true
|
2762 |
+
);
|
2763 |
+
continue;
|
2764 |
+
}
|
2765 |
+
$result = $this->check_api_result(
|
2766 |
+
$this->fbgraph->update_product_item(
|
2767 |
+
$fb_product_item_id,
|
2768 |
+
array( 'visibility' => $visibility )
|
2769 |
+
)
|
2770 |
+
);
|
2771 |
+
if ( $result ) {
|
2772 |
+
update_post_meta( $item_id, self::FB_VISIBILITY, $visibility );
|
2773 |
+
update_post_meta( $wp_id, self::FB_VISIBILITY, $visibility );
|
2774 |
+
}
|
2775 |
+
}
|
2776 |
+
}
|
2777 |
+
|
2778 |
+
function on_quick_and_bulk_edit_save( $product ) {
|
2779 |
+
$wp_id = $product->get_id();
|
2780 |
+
$visibility = get_post_status( $wp_id ) == 'publish'
|
2781 |
+
? 'published'
|
2782 |
+
: 'staging';
|
2783 |
+
// case 1: new status is 'publish' regardless of old status, sync to FB
|
2784 |
+
if ( $visibility == 'published' ) {
|
2785 |
+
$this->on_product_publish( $wp_id );
|
2786 |
+
} else {
|
2787 |
+
// case 2: product never publish to FB, new status is not publish
|
2788 |
+
// case 3: product new status is not publish and published before
|
2789 |
+
$this->update_fb_visibility( $wp_id, $visibility );
|
2790 |
+
}
|
2791 |
+
}
|
2792 |
+
|
2793 |
+
private function get_product_fbid( $fbid_type, $wp_id, $woo_product = null ) {
|
2794 |
+
$fb_id = WC_Facebookcommerce_Utils::get_fbid_post_meta(
|
2795 |
+
$wp_id,
|
2796 |
+
$fbid_type
|
2797 |
+
);
|
2798 |
+
if ( $fb_id ) {
|
2799 |
+
return $fb_id;
|
2800 |
+
}
|
2801 |
+
if ( ! isset( $this->settings['upload_end_time'] ) ) {
|
2802 |
+
return null;
|
2803 |
+
}
|
2804 |
+
if ( ! $woo_product ) {
|
2805 |
+
$woo_product = new WC_Facebook_Product( $wp_id );
|
2806 |
+
}
|
2807 |
+
$products = WC_Facebookcommerce_Utils::get_product_array( $woo_product );
|
2808 |
+
$woo_product = new WC_Facebook_Product( current( $products ) );
|
2809 |
+
// This is a generalized function used elsewhere
|
2810 |
+
// Cannot call is_hidden for VC_Product_Variable Object
|
2811 |
+
if ( $woo_product->is_hidden() ) {
|
2812 |
+
return null;
|
2813 |
+
}
|
2814 |
+
$fb_retailer_id =
|
2815 |
+
WC_Facebookcommerce_Utils::get_fb_retailer_id( $woo_product );
|
2816 |
+
|
2817 |
+
$product_fbid_result = $this->fbgraph->get_facebook_id(
|
2818 |
+
$this->product_catalog_id,
|
2819 |
+
$fb_retailer_id
|
2820 |
+
);
|
2821 |
+
if ( is_wp_error( $product_fbid_result ) ) {
|
2822 |
+
WC_Facebookcommerce_Utils::log( $product_fbid_result->get_error_message() );
|
2823 |
+
$this->display_error_message(
|
2824 |
+
'There was an issue connecting to the Facebook API: ' .
|
2825 |
+
$product_fbid_result->get_error_message()
|
2826 |
+
);
|
2827 |
+
return;
|
2828 |
+
}
|
2829 |
+
|
2830 |
+
if ( $product_fbid_result && isset( $product_fbid_result['body'] ) ) {
|
2831 |
+
$body = WC_Facebookcommerce_Utils::decode_json( $product_fbid_result['body'] );
|
2832 |
+
if ( $body && $body->id ) {
|
2833 |
+
if ( $fbid_type == self::FB_PRODUCT_GROUP_ID ) {
|
2834 |
+
$fb_id = $body->product_group->id;
|
2835 |
+
} else {
|
2836 |
+
$fb_id = $body->id;
|
2837 |
+
}
|
2838 |
+
update_post_meta(
|
2839 |
+
$wp_id,
|
2840 |
+
$fbid_type,
|
2841 |
+
$fb_id
|
2842 |
+
);
|
2843 |
+
update_post_meta( $wp_id, self::FB_VISIBILITY, true );
|
2844 |
+
return $fb_id;
|
2845 |
+
}
|
2846 |
+
}
|
2847 |
+
return;
|
2848 |
+
}
|
2849 |
+
|
2850 |
+
private function set_default_variant( $product_group_id, $product_item_id ) {
|
2851 |
+
$result = $this->check_api_result(
|
2852 |
+
$this->fbgraph->set_default_variant(
|
2853 |
+
$product_group_id,
|
2854 |
+
array( 'default_product_id' => $product_item_id )
|
2855 |
+
)
|
2856 |
+
);
|
2857 |
+
if ( ! $result ) {
|
2858 |
+
WC_Facebookcommerce_Utils::fblog(
|
2859 |
+
'Fail to set default product item',
|
2860 |
+
array(),
|
2861 |
+
true
|
2862 |
+
);
|
2863 |
+
}
|
2864 |
+
}
|
2865 |
+
|
2866 |
+
private function fb_wp_die() {
|
2867 |
+
if ( ! $this->test_mode ) {
|
2868 |
+
wp_die();
|
2869 |
+
}
|
2870 |
+
}
|
2871 |
+
|
2872 |
+
/**
|
2873 |
+
* Display test result.
|
2874 |
+
**/
|
2875 |
+
function ajax_display_test_result() {
|
2876 |
+
WC_Facebookcommerce_Utils::check_woo_ajax_permissions( 'test result', true );
|
2877 |
+
check_ajax_referer( 'wc_facebook_settings_jsx' );
|
2878 |
+
$response = array(
|
2879 |
+
'pass' => 'true',
|
2880 |
+
);
|
2881 |
+
$test_pass = get_option( 'fb_test_pass', null );
|
2882 |
+
if ( ! isset( $test_pass ) ) {
|
2883 |
+
$response['pass'] = 'in progress';
|
2884 |
+
} elseif ( $test_pass == 0 ) {
|
2885 |
+
$response['pass'] = 'false';
|
2886 |
+
$response['debug_info'] = get_transient( 'facebook_plugin_test_fail' );
|
2887 |
+
$response['stack_trace'] =
|
2888 |
+
get_transient( 'facebook_plugin_test_stack_trace' );
|
2889 |
+
$response['stack_trace'] =
|
2890 |
+
preg_replace( "/\n/", '<br>', $response['stack_trace'] );
|
2891 |
+
delete_transient( 'facebook_plugin_test_fail' );
|
2892 |
+
delete_transient( 'facebook_plugin_test_stack_trace' );
|
2893 |
+
}
|
2894 |
+
delete_option( 'fb_test_pass' );
|
2895 |
+
printf( json_encode( $response ) );
|
2896 |
+
wp_die();
|
2897 |
+
}
|
2898 |
+
|
2899 |
+
/**
|
2900 |
+
* Schedule Force Resync
|
2901 |
+
*/
|
2902 |
+
function ajax_schedule_force_resync() {
|
2903 |
+
WC_Facebookcommerce_Utils::check_woo_ajax_permissions( 'resync schedule', true );
|
2904 |
+
check_ajax_referer( 'wc_facebook_settings_jsx' );
|
2905 |
+
if ( isset( $_POST ) && isset( $_POST['enabled'] ) ) {
|
2906 |
+
if ( isset( $_POST['time'] ) && $_POST['enabled'] ) { // Enabled
|
2907 |
+
$time = sanitize_text_field( $_POST['time'] );
|
2908 |
+
wp_clear_scheduled_hook( 'sync_all_fb_products_using_feed' );
|
2909 |
+
wp_schedule_event(
|
2910 |
+
strtotime( $time ),
|
2911 |
+
'daily',
|
2912 |
+
'sync_all_fb_products_using_feed'
|
2913 |
+
);
|
2914 |
+
WC_Facebookcommerce_Utils::fblog( 'Scheduled autosync for ' . $time );
|
2915 |
+
update_option( 'woocommerce_fb_autosync_time', $time );
|
2916 |
+
} elseif ( ! $_POST['enabled'] ) { // Disabled
|
2917 |
+
wp_clear_scheduled_hook( 'sync_all_fb_products_using_feed' );
|
2918 |
+
WC_Facebookcommerce_Utils::fblog( 'Autosync disabled' );
|
2919 |
+
delete_option( 'woocommerce_fb_autosync_time' );
|
2920 |
+
}
|
2921 |
+
} else {
|
2922 |
+
WC_Facebookcommerce_Utils::fblog( 'Autosync AJAX Problem', $_POST, true );
|
2923 |
+
}
|
2924 |
+
wp_die();
|
2925 |
+
}
|
2926 |
+
|
2927 |
+
function ajax_update_fb_option() {
|
2928 |
+
check_ajax_referer( 'wc_facebook_settings_jsx' );
|
2929 |
+
WC_Facebookcommerce_Utils::check_woo_ajax_permissions( 'update fb options', true );
|
2930 |
+
if ( isset( $_POST ) && stripos( $_POST['option'], 'fb_' ) === 0 ) {
|
2931 |
+
update_option( sanitize_text_field( $_POST['option'] ), sanitize_text_field( $_POST['option_value'] ) );
|
2932 |
+
}
|
2933 |
+
wp_die();
|
2934 |
+
}
|
2935 |
}
|
facebook-config-warmer.php
CHANGED
@@ -8,14 +8,16 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
-
if (!defined('ABSPATH'))
|
|
|
|
|
12 |
|
13 |
|
14 |
-
if (!class_exists('WC_Facebookcommerce_WarmConfig')) :
|
15 |
|
16 |
-
class WC_Facebookcommerce_WarmConfig {
|
17 |
-
|
18 |
-
|
19 |
-
}
|
20 |
|
21 |
endif;
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
12 |
+
exit; // Exit if accessed directly
|
13 |
+
}
|
14 |
|
15 |
|
16 |
+
if ( ! class_exists( 'WC_Facebookcommerce_WarmConfig' ) ) :
|
17 |
|
18 |
+
class WC_Facebookcommerce_WarmConfig {
|
19 |
+
static $fb_warm_pixel_id = null;
|
20 |
+
static $fb_warm_is_advanced_matching_enabled = null;
|
21 |
+
}
|
22 |
|
23 |
endif;
|
facebook-for-woocommerce.php
CHANGED
@@ -10,7 +10,7 @@
|
|
10 |
* Description: Grow your business on Facebook! Use this official plugin to help sell more of your products using Facebook. After completing the setup, you'll be ready to create ads that promote your products and you can also create a shop section on your Page where customers can browse your products on Facebook.
|
11 |
* Author: Facebook
|
12 |
* Author URI: https://www.facebook.com/
|
13 |
-
* Version: 1.9.
|
14 |
* Woo: 2127297:0ea4fe4c2d7ca6338f8a322fb3e4e187
|
15 |
* Text Domain: facebook-for-woocommerce
|
16 |
* WC requires at least: 3.0.0
|
@@ -20,86 +20,97 @@
|
|
20 |
*/
|
21 |
|
22 |
|
23 |
-
if (!class_exists('WC_Facebookcommerce')) :
|
24 |
-
include_once 'includes/fbutils.php';
|
25 |
|
26 |
-
class WC_Facebookcommerce {
|
27 |
|
28 |
-
|
29 |
-
|
30 |
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
|
|
|
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
|
|
56 |
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
|
|
|
|
|
|
64 |
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
|
|
74 |
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
|
|
|
|
81 |
please disable WP_DEBUG_DISPLAY in your wp-config.php file.
|
82 |
Contact your server administrator for more assistance.',
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
|
|
|
|
89 |
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
}
|
102 |
|
103 |
-
$WC_Facebookcommerce = new WC_Facebookcommerce(__FILE__);
|
104 |
|
105 |
endif;
|
10 |
* Description: Grow your business on Facebook! Use this official plugin to help sell more of your products using Facebook. After completing the setup, you'll be ready to create ads that promote your products and you can also create a shop section on your Page where customers can browse your products on Facebook.
|
11 |
* Author: Facebook
|
12 |
* Author URI: https://www.facebook.com/
|
13 |
+
* Version: 1.9.15
|
14 |
* Woo: 2127297:0ea4fe4c2d7ca6338f8a322fb3e4e187
|
15 |
* Text Domain: facebook-for-woocommerce
|
16 |
* WC requires at least: 3.0.0
|
20 |
*/
|
21 |
|
22 |
|
23 |
+
if ( ! class_exists( 'WC_Facebookcommerce' ) ) :
|
24 |
+
include_once 'includes/fbutils.php';
|
25 |
|
26 |
+
class WC_Facebookcommerce {
|
27 |
|
28 |
+
// Change it above as well
|
29 |
+
const PLUGIN_VERSION = WC_Facebookcommerce_Utils::PLUGIN_VERSION;
|
30 |
|
31 |
+
/**
|
32 |
+
* Construct the plugin.
|
33 |
+
*/
|
34 |
+
public function __construct() {
|
35 |
+
add_action( 'plugins_loaded', array( $this, 'init' ) );
|
36 |
+
}
|
37 |
|
38 |
+
/**
|
39 |
+
* Initialize the plugin.
|
40 |
+
*/
|
41 |
+
public function init() {
|
42 |
+
if ( is_admin() ) {
|
43 |
+
add_filter(
|
44 |
+
'plugin_action_links_' . plugin_basename( __FILE__ ),
|
45 |
+
array( $this, 'add_settings_link' )
|
46 |
+
);
|
47 |
+
}
|
48 |
|
49 |
+
if ( WC_Facebookcommerce_Utils::isWoocommerceIntegration() ) {
|
50 |
+
if ( ! defined( 'WOOCOMMERCE_FACEBOOK_PLUGIN_SETTINGS_URL' ) ) {
|
51 |
+
define(
|
52 |
+
'WOOCOMMERCE_FACEBOOK_PLUGIN_SETTINGS_URL',
|
53 |
+
get_admin_url()
|
54 |
+
. '/admin.php?page=wc-settings&tab=integration'
|
55 |
+
. '§ion=facebookcommerce'
|
56 |
+
);
|
57 |
+
}
|
58 |
+
include_once 'facebook-commerce.php';
|
59 |
|
60 |
+
// Register WooCommerce integration.
|
61 |
+
add_filter(
|
62 |
+
'woocommerce_integrations',
|
63 |
+
array(
|
64 |
+
$this,
|
65 |
+
'add_woocommerce_integration',
|
66 |
+
)
|
67 |
+
);
|
68 |
+
}
|
69 |
+
}
|
70 |
|
71 |
+
public function add_settings_link( $links ) {
|
72 |
+
$settings = array(
|
73 |
+
'settings' => sprintf(
|
74 |
+
'<a href="%s">%s</a>',
|
75 |
+
admin_url( 'admin.php?page=wc-settings&tab=integration§ion=facebookcommerce' ),
|
76 |
+
'Settings'
|
77 |
+
),
|
78 |
+
);
|
79 |
+
return array_merge( $settings, $links );
|
80 |
+
}
|
81 |
|
82 |
+
public function wp_debug_display_error() {
|
83 |
+
?>
|
84 |
+
<div class="error below-h3">
|
85 |
+
<p>
|
86 |
+
<?php
|
87 |
+
printf(
|
88 |
+
__(
|
89 |
+
'To use Facebook for WooCommerce,
|
90 |
please disable WP_DEBUG_DISPLAY in your wp-config.php file.
|
91 |
Contact your server administrator for more assistance.',
|
92 |
+
'facebook-for-woocommerce'
|
93 |
+
)
|
94 |
+
);
|
95 |
+
?>
|
96 |
+
</p>
|
97 |
+
</div>
|
98 |
+
<?php
|
99 |
+
}
|
100 |
|
101 |
+
/**
|
102 |
+
* Add a new integration to WooCommerce.
|
103 |
+
*/
|
104 |
+
public function add_woocommerce_integration( $integrations ) {
|
105 |
+
$integrations[] = 'WC_Facebookcommerce_Integration';
|
106 |
+
return $integrations;
|
107 |
+
}
|
108 |
|
109 |
+
public function add_wordpress_integration() {
|
110 |
+
new WP_Facebook_Integration();
|
111 |
+
}
|
112 |
+
}
|
113 |
|
114 |
+
$WC_Facebookcommerce = new WC_Facebookcommerce( __FILE__ );
|
115 |
|
116 |
endif;
|
includes/fbasync.php
CHANGED
@@ -8,35 +8,34 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
-
if (!defined('ABSPATH')) {
|
12 |
-
|
13 |
}
|
14 |
|
15 |
-
if (!class_exists('WP_Async_Request', false) ) {
|
16 |
-
|
17 |
-
|
18 |
}
|
19 |
|
20 |
-
if (!class_exists('WC_Facebookcommerce_Async_Request')) :
|
21 |
|
22 |
-
/**
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
class WC_Facebookcommerce_Async_Request extends WP_Async_Request {
|
27 |
|
28 |
-
|
29 |
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
|
40 |
-
}
|
41 |
|
42 |
endif;
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
12 |
+
exit;
|
13 |
}
|
14 |
|
15 |
+
if ( ! class_exists( 'WP_Async_Request', false ) ) {
|
16 |
+
// Do not attempt to create this class without WP_Async_Request
|
17 |
+
return;
|
18 |
}
|
19 |
|
20 |
+
if ( ! class_exists( 'WC_Facebookcommerce_Async_Request' ) ) :
|
21 |
|
22 |
+
/**
|
23 |
+
* FB Graph API async request
|
24 |
+
*/
|
25 |
+
class WC_Facebookcommerce_Async_Request extends WP_Async_Request {
|
|
|
26 |
|
27 |
+
protected $action = 'wc_facebook_async_request';
|
28 |
|
29 |
+
/**
|
30 |
+
* Handle
|
31 |
+
*
|
32 |
+
* Override this method to perform any actions required
|
33 |
+
* during the async request.
|
34 |
+
*/
|
35 |
+
protected function handle() {
|
36 |
+
// Actions to perform
|
37 |
+
}
|
38 |
|
39 |
+
}
|
40 |
|
41 |
endif;
|
includes/fbbackground.php
CHANGED
@@ -8,145 +8,156 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
-
if (! defined('ABSPATH')) {
|
12 |
-
|
13 |
}
|
14 |
|
15 |
-
if (!class_exists('WP_Background_Process', false) ) {
|
16 |
-
|
17 |
-
|
18 |
}
|
19 |
|
20 |
-
if (! class_exists('WC_Facebookcommerce_Background_Process')) :
|
21 |
-
|
22 |
-
class WC_Facebookcommerce_Background_Process extends WP_Background_Process {
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
|
152 |
endif;
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
12 |
+
exit;
|
13 |
}
|
14 |
|
15 |
+
if ( ! class_exists( 'WP_Background_Process', false ) ) {
|
16 |
+
// Do not attempt to create this class without WP_Background_Process
|
17 |
+
return;
|
18 |
}
|
19 |
|
20 |
+
if ( ! class_exists( 'WC_Facebookcommerce_Background_Process' ) ) :
|
21 |
+
|
22 |
+
class WC_Facebookcommerce_Background_Process extends WP_Background_Process {
|
23 |
+
|
24 |
+
public function __construct( $commerce ) {
|
25 |
+
$this->commerce = $commerce; // Full WC_Facebookcommerce_Integration obj
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @var string
|
30 |
+
*/
|
31 |
+
protected $action = 'fb_commerce_background_process';
|
32 |
+
|
33 |
+
public function dispatch() {
|
34 |
+
$commerce = $this->commerce;
|
35 |
+
$dispatched = parent::dispatch();
|
36 |
+
|
37 |
+
if ( is_wp_error( $dispatched ) ) {
|
38 |
+
WC_Facebookcommerce_Utils::log(
|
39 |
+
sprintf(
|
40 |
+
'Unable to dispatch FB Background processor: %s',
|
41 |
+
$dispatched->get_error_message()
|
42 |
+
),
|
43 |
+
array( 'source' => 'wc_facebook_background_process' )
|
44 |
+
);
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
+
public function get_item_count() {
|
49 |
+
$commerce = $this->commerce;
|
50 |
+
return (int) get_transient( $commerce::FB_SYNC_REMAINING );
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Handle cron healthcheck
|
55 |
+
*
|
56 |
+
* Restart the background process if not already running
|
57 |
+
* and data exists in the queue.
|
58 |
+
*/
|
59 |
+
public function handle_cron_healthcheck() {
|
60 |
+
$commerce = $this->commerce;
|
61 |
+
if ( $this->is_process_running() ) {
|
62 |
+
// Background process already running, no-op
|
63 |
+
return true; // Return "is running? status"
|
64 |
+
}
|
65 |
+
|
66 |
+
if ( $this->is_queue_empty() ) {
|
67 |
+
// No data to process.
|
68 |
+
$this->clear_scheduled_event();
|
69 |
+
delete_transient( $commerce::FB_SYNC_REMAINING );
|
70 |
+
return;
|
71 |
+
}
|
72 |
+
|
73 |
+
$this->handle();
|
74 |
+
return true;
|
75 |
+
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Schedule fallback event.
|
80 |
+
*/
|
81 |
+
protected function schedule_event() {
|
82 |
+
if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) {
|
83 |
+
wp_schedule_event(
|
84 |
+
time() + 10,
|
85 |
+
$this->cron_interval_identifier,
|
86 |
+
$this->cron_hook_identifier
|
87 |
+
);
|
88 |
+
}
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Is the processor updating?
|
93 |
+
*
|
94 |
+
* @return boolean
|
95 |
+
*/
|
96 |
+
public function is_updating() {
|
97 |
+
return false === $this->is_queue_empty();
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Is the processor running?
|
102 |
+
*
|
103 |
+
* @return boolean
|
104 |
+
*/
|
105 |
+
public function is_running() {
|
106 |
+
return $this->is_process_running();
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Process individual product
|
111 |
+
*
|
112 |
+
* Returns false to remove the item from the queue
|
113 |
+
* (would return item if it needed additional processing).
|
114 |
+
*
|
115 |
+
* @param mixed $item Queue item to iterate over
|
116 |
+
*
|
117 |
+
* @return mixed
|
118 |
+
*/
|
119 |
+
protected function task( $item ) {
|
120 |
+
$commerce = $this->commerce; // PHP5 compatibility for static access
|
121 |
+
$remaining = $this->get_item_count();
|
122 |
+
$count_message = sprintf(
|
123 |
+
'Background syncing products to Facebook. Products remaining: %1$d',
|
124 |
+
$remaining
|
125 |
+
);
|
126 |
+
|
127 |
+
$this->commerce->display_sticky_message( $count_message, true );
|
128 |
+
|
129 |
+
$this->commerce->on_product_publish( $item );
|
130 |
+
$remaining--;
|
131 |
+
set_transient(
|
132 |
+
$commerce::FB_SYNC_IN_PROGRESS,
|
133 |
+
true,
|
134 |
+
$commerce::FB_SYNC_TIMEOUT
|
135 |
+
);
|
136 |
+
set_transient(
|
137 |
+
$commerce::FB_SYNC_REMAINING,
|
138 |
+
$remaining
|
139 |
+
);
|
140 |
+
|
141 |
+
return false;
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Complete
|
146 |
+
*
|
147 |
+
* Override if applicable, but ensure that the below actions are
|
148 |
+
* performed, or, call parent::complete().
|
149 |
+
*/
|
150 |
+
protected function complete() {
|
151 |
+
$commerce = $this->commerce; // PHP5 compatibility for static access
|
152 |
+
delete_transient( $commerce::FB_SYNC_IN_PROGRESS );
|
153 |
+
delete_transient( $commerce::FB_SYNC_REMAINING );
|
154 |
+
WC_Facebookcommerce_Utils::log( 'Background sync complete!' );
|
155 |
+
WC_Facebookcommerce_Utils::fblog( 'Background sync complete!' );
|
156 |
+
$this->commerce->remove_sticky_message();
|
157 |
+
$this->commerce->display_info_message( 'Facebook product sync complete!' );
|
158 |
+
parent::complete();
|
159 |
+
}
|
160 |
+
|
161 |
+
}
|
162 |
|
163 |
endif;
|
includes/fbgraph.php
CHANGED
@@ -8,291 +8,305 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
-
if (!defined('ABSPATH')) {
|
12 |
-
|
13 |
}
|
14 |
|
15 |
-
if (!class_exists('WC_Facebookcommerce_Graph_API')) :
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
/**
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
$
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
297 |
|
298 |
endif;
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
12 |
+
exit;
|
13 |
}
|
14 |
|
15 |
+
if ( ! class_exists( 'WC_Facebookcommerce_Graph_API' ) ) :
|
16 |
+
|
17 |
+
if ( ! class_exists( 'WC_Facebookcommerce_Async_Request' ) ) {
|
18 |
+
include_once 'fbasync.php';
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* FB Graph API helper functions
|
23 |
+
*/
|
24 |
+
class WC_Facebookcommerce_Graph_API {
|
25 |
+
const GRAPH_API_URL = 'https://graph.facebook.com/v2.9/';
|
26 |
+
const CURL_TIMEOUT = 500;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Cache the api_key
|
30 |
+
*/
|
31 |
+
var $api_key;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Init
|
35 |
+
*/
|
36 |
+
public function __construct( $api_key ) {
|
37 |
+
$this->api_key = $api_key;
|
38 |
+
}
|
39 |
+
|
40 |
+
public function _get( $url, $api_key = '' ) {
|
41 |
+
$api_key = $api_key ?: $this->api_key;
|
42 |
+
return wp_remote_get(
|
43 |
+
$url,
|
44 |
+
array(
|
45 |
+
'headers' => array(
|
46 |
+
'Authorization' => 'Bearer ' . $api_key,
|
47 |
+
),
|
48 |
+
'timeout' => self::CURL_TIMEOUT,
|
49 |
+
)
|
50 |
+
);
|
51 |
+
}
|
52 |
+
|
53 |
+
public function _post( $url, $data, $api_key = '' ) {
|
54 |
+
if ( class_exists( 'WC_Facebookcommerce_Async_Request' ) ) {
|
55 |
+
return self::_post_async( $url, $data );
|
56 |
+
} else {
|
57 |
+
return self::_post_sync( $url, $data );
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
public function _post_sync( $url, $data, $api_key = '' ) {
|
62 |
+
$api_key = $api_key ?: $this->api_key;
|
63 |
+
return wp_remote_post(
|
64 |
+
$url,
|
65 |
+
array(
|
66 |
+
'body' => $data,
|
67 |
+
'headers' => array(
|
68 |
+
'Authorization' => 'Bearer ' . $api_key,
|
69 |
+
),
|
70 |
+
'timeout' => self::CURL_TIMEOUT,
|
71 |
+
)
|
72 |
+
);
|
73 |
+
}
|
74 |
+
|
75 |
+
public function _post_async( $url, $data, $api_key = '' ) {
|
76 |
+
if ( ! class_exists( 'WC_Facebookcommerce_Async_Request' ) ) {
|
77 |
+
return;
|
78 |
+
}
|
79 |
+
|
80 |
+
$api_key = $api_key ?: $this->api_key;
|
81 |
+
$fbasync = new WC_Facebookcommerce_Async_Request();
|
82 |
+
|
83 |
+
$fbasync->query_url = $url;
|
84 |
+
$fbasync->query_args = array();
|
85 |
+
$fbasync->post_args = array(
|
86 |
+
'body' => $data,
|
87 |
+
'headers' => array(
|
88 |
+
'Authorization' => 'Bearer ' . $api_key,
|
89 |
+
),
|
90 |
+
'timeout' => self::CURL_TIMEOUT,
|
91 |
+
);
|
92 |
+
|
93 |
+
return $fbasync->dispatch();
|
94 |
+
}
|
95 |
+
|
96 |
+
public function _delete( $url, $api_key = '' ) {
|
97 |
+
$api_key = $api_key ?: $this->api_key;
|
98 |
+
|
99 |
+
return wp_remote_request(
|
100 |
+
$url,
|
101 |
+
array(
|
102 |
+
'headers' => array(
|
103 |
+
'Authorization' => 'Bearer ' . $api_key,
|
104 |
+
),
|
105 |
+
'timeout' => self::CURL_TIMEOUT,
|
106 |
+
'method' => 'DELETE',
|
107 |
+
)
|
108 |
+
);
|
109 |
+
}
|
110 |
+
|
111 |
+
// GET https://graph.facebook.com/vX.X/{page-id}/?fields=name
|
112 |
+
public function get_page_name( $page_id, $api_key = '' ) {
|
113 |
+
$api_key = $api_key ?: $this->api_key;
|
114 |
+
$url = $this->build_url( $page_id, '/?fields=name' );
|
115 |
+
$response = self::_get( $url, $api_key );
|
116 |
+
if ( is_wp_error( $response ) ) {
|
117 |
+
WC_Facebookcommerce_Utils::log( $response->get_error_message() );
|
118 |
+
return;
|
119 |
+
}
|
120 |
+
if ( $response['response']['code'] != '200' ) {
|
121 |
+
return;
|
122 |
+
}
|
123 |
+
|
124 |
+
$response_body = wp_remote_retrieve_body( $response );
|
125 |
+
|
126 |
+
return json_decode( $response_body )->name;
|
127 |
+
}
|
128 |
+
|
129 |
+
public function validate_product_catalog( $product_catalog_id ) {
|
130 |
+
$url = $this->build_url( $product_catalog_id );
|
131 |
+
$response = self::_get( $url );
|
132 |
+
if ( is_wp_error( $response ) ) {
|
133 |
+
WC_Facebookcommerce_Utils::log( $response->get_error_message() );
|
134 |
+
return;
|
135 |
+
}
|
136 |
+
return $response['response']['code'] == '200';
|
137 |
+
}
|
138 |
+
|
139 |
+
// POST https://graph.facebook.com/vX.X/{product-catalog-id}/product_groups
|
140 |
+
public function create_product_group( $product_catalog_id, $data ) {
|
141 |
+
$url = $this->build_url( $product_catalog_id, '/product_groups' );
|
142 |
+
return self::_post( $url, $data );
|
143 |
+
}
|
144 |
+
|
145 |
+
// POST https://graph.facebook.com/vX.X/{product-group-id}/products
|
146 |
+
public function create_product_item( $product_group_id, $data ) {
|
147 |
+
$url = $this->build_url( $product_group_id, '/products' );
|
148 |
+
return self::_post( $url, $data );
|
149 |
+
}
|
150 |
+
|
151 |
+
public function update_product_group( $product_catalog_id, $data ) {
|
152 |
+
$url = $this->build_url( $product_catalog_id );
|
153 |
+
return self::_post( $url, $data );
|
154 |
+
}
|
155 |
+
|
156 |
+
public function update_product_item( $product_id, $data ) {
|
157 |
+
$url = $this->build_url( $product_id );
|
158 |
+
return self::_post( $url, $data );
|
159 |
+
}
|
160 |
+
|
161 |
+
public function delete_product_item( $product_item_id ) {
|
162 |
+
$product_item_url = $this->build_url( $product_item_id );
|
163 |
+
return self::_delete( $product_item_url );
|
164 |
+
}
|
165 |
+
|
166 |
+
public function delete_product_group( $product_group_id ) {
|
167 |
+
$product_group_url = $this->build_url( $product_group_id );
|
168 |
+
return self::_delete( $product_group_url );
|
169 |
+
}
|
170 |
+
|
171 |
+
public function log( $ems_id, $message, $error ) {
|
172 |
+
$log_url = $this->build_url( $ems_id, '/log_events' );
|
173 |
+
|
174 |
+
$data = array(
|
175 |
+
'message' => $message,
|
176 |
+
'error' => $error,
|
177 |
+
);
|
178 |
+
|
179 |
+
self::_post( $log_url, $data );
|
180 |
+
}
|
181 |
+
|
182 |
+
public function log_tip_event( $tip_id, $channel_id, $event ) {
|
183 |
+
$tip_event_log_url = $this->build_url( '', '/log_tip_events' );
|
184 |
+
|
185 |
+
$data = array(
|
186 |
+
'tip_id' => $tip_id,
|
187 |
+
'channel_id' => $channel_id,
|
188 |
+
'event' => $event,
|
189 |
+
);
|
190 |
+
|
191 |
+
self::_post( $tip_event_log_url, $data );
|
192 |
+
}
|
193 |
+
|
194 |
+
public function create_upload( $facebook_feed_id, $path_to_feed_file ) {
|
195 |
+
$url = $this->build_url(
|
196 |
+
$facebook_feed_id,
|
197 |
+
'/uploads?access_token=' . $this->api_key
|
198 |
+
);
|
199 |
+
$data = array(
|
200 |
+
'file' => new CurlFile( $path_to_feed_file, 'text/csv' ),
|
201 |
+
);
|
202 |
+
$curl = curl_init();
|
203 |
+
curl_setopt_array(
|
204 |
+
$curl,
|
205 |
+
array(
|
206 |
+
CURLOPT_URL => $url,
|
207 |
+
CURLOPT_POST => 1,
|
208 |
+
CURLOPT_POSTFIELDS => $data,
|
209 |
+
CURLOPT_RETURNTRANSFER => 1,
|
210 |
+
)
|
211 |
+
);
|
212 |
+
$response = curl_exec( $curl );
|
213 |
+
if ( curl_errno( $curl ) ) {
|
214 |
+
WC_Facebookcommerce_Utils::fblog( $response );
|
215 |
+
return null;
|
216 |
+
}
|
217 |
+
return WC_Facebookcommerce_Utils::decode_json( $response, true );
|
218 |
+
}
|
219 |
+
|
220 |
+
public function create_feed( $facebook_catalog_id, $data ) {
|
221 |
+
$url = $this->build_url( $facebook_catalog_id, '/product_feeds' );
|
222 |
+
// success API call will return {id: <product feed id>}
|
223 |
+
// failure API will return {error: <error message>}
|
224 |
+
return self::_post( $url, $data );
|
225 |
+
}
|
226 |
+
|
227 |
+
public function get_upload_status( $facebook_upload_id ) {
|
228 |
+
$url = $this->build_url( $facebook_upload_id, '/?fields=end_time' );
|
229 |
+
// success API call will return
|
230 |
+
// {id: <upload id>, end_time: <time when upload completes>}
|
231 |
+
// failure API will return {error: <error message>}
|
232 |
+
return self::_get( $url );
|
233 |
+
}
|
234 |
+
|
235 |
+
// success API call will return a JSON of tip info
|
236 |
+
public function get_tip_info( $external_merchant_settings_id ) {
|
237 |
+
$url = $this->build_url( $external_merchant_settings_id, '/?fields=connect_woo' );
|
238 |
+
$response = self::_get( $url, $this->api_key );
|
239 |
+
$data = array(
|
240 |
+
'response' => $response,
|
241 |
+
);
|
242 |
+
if ( is_wp_error( $response ) ) {
|
243 |
+
$data['error_type'] = 'is_wp_error';
|
244 |
+
WC_Facebookcommerce_Utils::fblog(
|
245 |
+
'Failed to get AYMT tip info via API.',
|
246 |
+
$data,
|
247 |
+
true
|
248 |
+
);
|
249 |
+
return;
|
250 |
+
}
|
251 |
+
if ( $response['response']['code'] != '200' ) {
|
252 |
+
$data['error_type'] = 'Non-200 error code from FB';
|
253 |
+
WC_Facebookcommerce_Utils::fblog(
|
254 |
+
'Failed to get AYMT tip info via API.',
|
255 |
+
$data,
|
256 |
+
true
|
257 |
+
);
|
258 |
+
return;
|
259 |
+
}
|
260 |
+
|
261 |
+
$response_body = wp_remote_retrieve_body( $response );
|
262 |
+
$connect_woo =
|
263 |
+
WC_Facebookcommerce_Utils::decode_json( $response_body )->connect_woo;
|
264 |
+
if ( ! isset( $connect_woo ) ) {
|
265 |
+
$data['error_type'] = 'Response body not set';
|
266 |
+
WC_Facebookcommerce_Utils::fblog(
|
267 |
+
'Failed to get AYMT tip info via API.',
|
268 |
+
$data,
|
269 |
+
true
|
270 |
+
);
|
271 |
+
}
|
272 |
+
return $connect_woo;
|
273 |
+
}
|
274 |
+
|
275 |
+
public function get_facebook_id( $facebook_catalog_id, $product_id ) {
|
276 |
+
$param = 'catalog:' . (string) $facebook_catalog_id . ':' .
|
277 |
+
base64_encode( $product_id ) . '/?fields=id,product_group{id}';
|
278 |
+
$url = $this->build_url( '', $param );
|
279 |
+
// success API call will return
|
280 |
+
// {id: <fb product id>, product_group{id} <fb product group id>}
|
281 |
+
// failure API will return {error: <error message>}
|
282 |
+
return self::_get( $url );
|
283 |
+
}
|
284 |
+
|
285 |
+
public function check_product_info( $facebook_catalog_id, $product_id, $pr_v ) {
|
286 |
+
$param = 'catalog:' . (string) $facebook_catalog_id . ':' .
|
287 |
+
base64_encode( $product_id ) . '/?fields=id,name,description,price,' .
|
288 |
+
'sale_price,sale_price_start_date,sale_price_end_date,image_url,' .
|
289 |
+
'visibility';
|
290 |
+
if ( $pr_v ) {
|
291 |
+
$param = $param . ',additional_variant_attributes{value}';
|
292 |
+
}
|
293 |
+
$url = $this->build_url( '', $param );
|
294 |
+
// success API call will return
|
295 |
+
// {id: <fb product id>, name,description,price,sale_price,sale_price_start_date
|
296 |
+
// sale_price_end_date
|
297 |
+
// failure API will return {error: <error message>}
|
298 |
+
return self::_get( $url );
|
299 |
+
}
|
300 |
+
|
301 |
+
public function set_default_variant( $product_group_id, $data ) {
|
302 |
+
$url = $this->build_url( $product_group_id );
|
303 |
+
return self::_post( $url, $data );
|
304 |
+
}
|
305 |
+
|
306 |
+
private function build_url( $field_id, $param = '' ) {
|
307 |
+
return self::GRAPH_API_URL . (string) $field_id . $param;
|
308 |
+
}
|
309 |
+
|
310 |
+
}
|
311 |
|
312 |
endif;
|
includes/fbinfobanner.php
CHANGED
@@ -8,234 +8,257 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
-
if (! defined('ABSPATH')) {
|
12 |
-
|
13 |
}
|
14 |
|
15 |
-
if (!class_exists('WC_Facebookcommerce_Utils')) {
|
16 |
-
|
17 |
}
|
18 |
|
19 |
-
if (! class_exists('WC_Facebookcommerce_Info_Banner')) :
|
20 |
|
21 |
-
/**
|
22 |
-
|
23 |
-
|
24 |
-
class WC_Facebookcommerce_Info_Banner {
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
240 |
|
241 |
endif;
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
12 |
+
exit;
|
13 |
}
|
14 |
|
15 |
+
if ( ! class_exists( 'WC_Facebookcommerce_Utils' ) ) {
|
16 |
+
include_once 'includes/fbutils.php';
|
17 |
}
|
18 |
|
19 |
+
if ( ! class_exists( 'WC_Facebookcommerce_Info_Banner' ) ) :
|
20 |
|
21 |
+
/**
|
22 |
+
* FB Info Banner class
|
23 |
+
*/
|
24 |
+
class WC_Facebookcommerce_Info_Banner {
|
25 |
+
|
26 |
+
const FB_NO_TIP_EXISTS = 'No Tip Exist!';
|
27 |
+
const DEFAULT_TIP_IMG_URL_PREFIX = 'https://www.facebook.com';
|
28 |
+
const CHANNEL_ID = 2087541767986590;
|
29 |
+
|
30 |
+
/** @var object Class Instance */
|
31 |
+
private static $instance;
|
32 |
+
|
33 |
+
/** @var string If the banner has been dismissed */
|
34 |
+
private $external_merchant_settings_id;
|
35 |
+
private $fbgraph;
|
36 |
+
private $should_query_tip;
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Get the class instance
|
40 |
+
*/
|
41 |
+
public static function get_instance(
|
42 |
+
$external_merchant_settings_id,
|
43 |
+
$fbgraph,
|
44 |
+
$should_query_tip = false ) {
|
45 |
+
return null === self::$instance
|
46 |
+
? ( self::$instance = new self(
|
47 |
+
$external_merchant_settings_id,
|
48 |
+
$fbgraph,
|
49 |
+
$should_query_tip
|
50 |
+
) )
|
51 |
+
: self::$instance;
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Constructor
|
56 |
+
*/
|
57 |
+
public function __construct(
|
58 |
+
$external_merchant_settings_id,
|
59 |
+
$fbgraph,
|
60 |
+
$should_query_tip = false ) {
|
61 |
+
$this->should_query_tip = $should_query_tip;
|
62 |
+
$this->external_merchant_settings_id = $external_merchant_settings_id;
|
63 |
+
$this->fbgraph = $fbgraph;
|
64 |
+
add_action( 'wp_ajax_ajax_woo_infobanner_post_click', array( $this, 'ajax_woo_infobanner_post_click' ) );
|
65 |
+
add_action( 'wp_ajax_ajax_woo_infobanner_post_xout', array( $this, 'ajax_woo_infobanner_post_xout' ) );
|
66 |
+
add_action( 'admin_notices', array( $this, 'banner' ) );
|
67 |
+
add_action( 'admin_init', array( $this, 'dismiss_banner' ) );
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Post click event when hit primary button.
|
72 |
+
*/
|
73 |
+
function ajax_woo_infobanner_post_click() {
|
74 |
+
WC_Facebookcommerce_Utils::check_woo_ajax_permissions(
|
75 |
+
'post tip click event',
|
76 |
+
true
|
77 |
+
);
|
78 |
+
check_ajax_referer( 'wc_facebook_infobanner_jsx' );
|
79 |
+
$tip_info = WC_Facebookcommerce_Utils::get_cached_best_tip();
|
80 |
+
$tip_id = isset( $tip_info->tip_id )
|
81 |
+
? $tip_info->tip_id
|
82 |
+
: null;
|
83 |
+
if ( $tip_id == null ) {
|
84 |
+
WC_Facebookcommerce_Utils::fblog(
|
85 |
+
'Do not have tip id when click, sth went wrong',
|
86 |
+
array( 'tip_info' => $tip_info ),
|
87 |
+
true
|
88 |
+
);
|
89 |
+
} else {
|
90 |
+
WC_Facebookcommerce_Utils::tip_events_log(
|
91 |
+
$tip_id,
|
92 |
+
self::CHANNEL_ID,
|
93 |
+
'click'
|
94 |
+
);
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Post xout event when hit dismiss button.
|
100 |
+
*/
|
101 |
+
function ajax_woo_infobanner_post_xout() {
|
102 |
+
WC_Facebookcommerce_Utils::check_woo_ajax_permissions(
|
103 |
+
'post tip xout event',
|
104 |
+
true
|
105 |
+
);
|
106 |
+
check_ajax_referer( 'wc_facebook_infobanner_jsx' );
|
107 |
+
$tip_info = WC_Facebookcommerce_Utils::get_cached_best_tip();
|
108 |
+
$tip_id = isset( $tip_info->tip_id )
|
109 |
+
? $tip_info->tip_id
|
110 |
+
: null;
|
111 |
+
// Delete cached tip if xout.
|
112 |
+
update_option( 'fb_info_banner_last_best_tip', '' );
|
113 |
+
if ( $tip_id == null ) {
|
114 |
+
WC_Facebookcommerce_Utils::fblog(
|
115 |
+
'Do not have tip id when xout, sth went wrong',
|
116 |
+
array( 'tip_info' => $tip_info ),
|
117 |
+
true
|
118 |
+
);
|
119 |
+
} else {
|
120 |
+
WC_Facebookcommerce_Utils::tip_events_log(
|
121 |
+
$tip_id,
|
122 |
+
self::CHANNEL_ID,
|
123 |
+
'xout'
|
124 |
+
);
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Display a info banner on Woocommerce pages.
|
130 |
+
*/
|
131 |
+
public function banner() {
|
132 |
+
$screen = get_current_screen();
|
133 |
+
if ( ! in_array(
|
134 |
+
$screen->base,
|
135 |
+
array(
|
136 |
+
'woocommerce_page_wc-reports',
|
137 |
+
'woocommerce_page_wc-settings',
|
138 |
+
'woocommerce_page_wc-status',
|
139 |
+
)
|
140 |
+
) ||
|
141 |
+
$screen->is_network || $screen->action ) {
|
142 |
+
return;
|
143 |
+
}
|
144 |
+
|
145 |
+
$tip_info = null;
|
146 |
+
if ( ! $this->should_query_tip ) {
|
147 |
+
// If last query is less than 1 day, either has last best tip or default
|
148 |
+
// tip pass time cap.
|
149 |
+
$tip_info = WC_Facebookcommerce_Utils::get_cached_best_tip();
|
150 |
+
} else {
|
151 |
+
$tip_info = $this->fbgraph->get_tip_info(
|
152 |
+
$this->external_merchant_settings_id
|
153 |
+
);
|
154 |
+
update_option( 'fb_info_banner_last_query_time', current_time( 'mysql' ) );
|
155 |
+
}
|
156 |
+
|
157 |
+
// Not render if no cached best tip, or no best tip returned from FB.
|
158 |
+
if ( ! $tip_info || ( $tip_info === self::FB_NO_TIP_EXISTS ) ) {
|
159 |
+
// Delete cached tip if should query and get no tip.
|
160 |
+
delete_option( 'fb_info_banner_last_best_tip' );
|
161 |
+
return;
|
162 |
+
} else {
|
163 |
+
// Get tip creatives via API
|
164 |
+
if ( is_string( $tip_info ) ) {
|
165 |
+
$tip_info = WC_Facebookcommerce_Utils::decode_json( $tip_info );
|
166 |
+
}
|
167 |
+
$tip_title = isset( $tip_info->tip_title->__html )
|
168 |
+
? $tip_info->tip_title->__html
|
169 |
+
: null;
|
170 |
+
|
171 |
+
$tip_body = isset( $tip_info->tip_body->__html )
|
172 |
+
? $tip_info->tip_body->__html
|
173 |
+
: null;
|
174 |
+
|
175 |
+
$tip_action_link = isset( $tip_info->tip_action_link )
|
176 |
+
? $tip_info->tip_action_link
|
177 |
+
: null;
|
178 |
+
|
179 |
+
$tip_action = isset( $tip_info->tip_action->__html )
|
180 |
+
? $tip_info->tip_action->__html
|
181 |
+
: null;
|
182 |
+
|
183 |
+
$tip_img_url = isset( $tip_info->tip_img_url )
|
184 |
+
? self::DEFAULT_TIP_IMG_URL_PREFIX . $tip_info->tip_img_url
|
185 |
+
: null;
|
186 |
+
|
187 |
+
if ( $tip_title == null || $tip_body == null || $tip_action_link == null
|
188 |
+
|| $tip_action == null || $tip_action == null ) {
|
189 |
+
WC_Facebookcommerce_Utils::fblog(
|
190 |
+
'Unexpected response from FB for tip info.',
|
191 |
+
array( 'tip_info' => $tip_info ),
|
192 |
+
true
|
193 |
+
);
|
194 |
+
return;
|
195 |
+
}
|
196 |
+
update_option(
|
197 |
+
'fb_info_banner_last_best_tip',
|
198 |
+
is_object( $tip_info ) || is_array( $tip_info )
|
199 |
+
? json_encode( $tip_info ) : $tip_info
|
200 |
+
);
|
201 |
+
}
|
202 |
+
|
203 |
+
$dismiss_url = $this->dismiss_url();
|
204 |
+
echo '<div class="updated fade"><div id="fbinfobanner"><div><img src="' . $tip_img_url .
|
205 |
+
'" class="iconDetails"></div><p class = "tipTitle">' .
|
206 |
+
__( '<strong>' . $tip_title . '</strong>', 'facebook-for-woocommerce' ) . "\n";
|
207 |
+
echo '<p class = "tipContent">' .
|
208 |
+
__( $tip_body, 'facebook-for-woocommerce' ) . '</p>';
|
209 |
+
echo '<p class = "tipButton"><a href="' . $tip_action_link . '" class = "btn" onclick="fb_woo_infobanner_post_click(); return true;" title="' .
|
210 |
+
__( 'Click and redirect.', 'facebook-for-woocommerce' ) .
|
211 |
+
'"> ' . __( $tip_action, 'facebook-for-woocommerce' ) . '</a>' .
|
212 |
+
'<a href="' . esc_url( $dismiss_url ) . '" class = "btn dismiss grey" onclick="fb_woo_infobanner_post_xout(); return true;" title="' .
|
213 |
+
__( 'Dismiss this notice.', 'facebook-for-woocommerce' ) .
|
214 |
+
'"> ' . __( 'Dismiss', 'facebook-for-woocommerce' ) . '</a></p></div></div>';
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* Returns the url that the user clicks to remove the info banner
|
219 |
+
*
|
220 |
+
* @return (string)
|
221 |
+
*/
|
222 |
+
private function dismiss_url() {
|
223 |
+
$url = admin_url( 'admin.php' );
|
224 |
+
|
225 |
+
$url = add_query_arg(
|
226 |
+
array(
|
227 |
+
'page' => 'wc-settings',
|
228 |
+
'tab' => 'integration',
|
229 |
+
'wc-notice' => 'dismiss-fb-info-banner',
|
230 |
+
),
|
231 |
+
$url
|
232 |
+
);
|
233 |
+
|
234 |
+
return wp_nonce_url( $url, 'woocommerce_info_banner_dismiss' );
|
235 |
+
}
|
236 |
+
|
237 |
+
/**
|
238 |
+
* Handles the dismiss action so that the banner can be permanently hidden
|
239 |
+
* during time threshold
|
240 |
+
*/
|
241 |
+
public function dismiss_banner() {
|
242 |
+
if ( ! isset( $_GET['wc-notice'] ) ) {
|
243 |
+
return;
|
244 |
+
}
|
245 |
+
|
246 |
+
if ( 'dismiss-fb-info-banner' !== $_GET['wc-notice'] ) {
|
247 |
+
return;
|
248 |
+
}
|
249 |
+
|
250 |
+
if ( ! check_admin_referer( 'woocommerce_info_banner_dismiss' ) ) {
|
251 |
+
return;
|
252 |
+
}
|
253 |
+
|
254 |
+
// Delete cached tip if xout.
|
255 |
+
delete_option( 'fb_info_banner_last_best_tip' );
|
256 |
+
if ( wp_get_referer() ) {
|
257 |
+
wp_safe_redirect( wp_get_referer() );
|
258 |
+
} else {
|
259 |
+
wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=integration' ) );
|
260 |
+
}
|
261 |
+
}
|
262 |
+
}
|
263 |
|
264 |
endif;
|
includes/fbproduct.php
CHANGED
@@ -8,745 +8,795 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
-
if (! defined('ABSPATH')) {
|
12 |
-
|
13 |
}
|
14 |
|
15 |
-
if (!class_exists('WC_Facebookcommerce_Utils')) {
|
16 |
-
|
17 |
}
|
18 |
|
19 |
-
if (! class_exists('WC_Facebook_Product')) :
|
20 |
-
|
21 |
-
/**
|
22 |
-
|
23 |
-
|
24 |
-
class WC_Facebook_Product {
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
751 |
|
752 |
endif;
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
12 |
+
exit;
|
13 |
}
|
14 |
|
15 |
+
if ( ! class_exists( 'WC_Facebookcommerce_Utils' ) ) {
|
16 |
+
include_once 'includes/fbutils.php';
|
17 |
}
|
18 |
|
19 |
+
if ( ! class_exists( 'WC_Facebook_Product' ) ) :
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Custom FB Product proxy class
|
23 |
+
*/
|
24 |
+
class WC_Facebook_Product {
|
25 |
+
|
26 |
+
// Should match facebook-commerce.php while we migrate that code over
|
27 |
+
// to this object.
|
28 |
+
const FB_PRODUCT_DESCRIPTION = 'fb_product_description';
|
29 |
+
const FB_PRODUCT_PRICE = 'fb_product_price';
|
30 |
+
const FB_PRODUCT_IMAGE = 'fb_product_image';
|
31 |
+
const FB_VARIANT_IMAGE = 'fb_image';
|
32 |
+
const FB_VISIBILITY = 'fb_visibility';
|
33 |
+
|
34 |
+
const MIN_DATE_1 = '1970-01-29';
|
35 |
+
const MIN_DATE_2 = '1970-01-30';
|
36 |
+
const MAX_DATE = '2038-01-17';
|
37 |
+
const MAX_TIME = 'T23:59+00:00';
|
38 |
+
const MIN_TIME = 'T00:00+00:00';
|
39 |
+
|
40 |
+
static $use_checkout_url = array(
|
41 |
+
'simple' => 1,
|
42 |
+
'variable' => 1,
|
43 |
+
'variation' => 1,
|
44 |
+
);
|
45 |
+
|
46 |
+
public function __construct(
|
47 |
+
$wpid, $parent_product = null ) {
|
48 |
+
$this->id = $wpid;
|
49 |
+
$this->fb_description = '';
|
50 |
+
$this->fb_visibility = get_post_meta( $wpid, self::FB_VISIBILITY, true );
|
51 |
+
$this->woo_product = wc_get_product( $wpid );
|
52 |
+
$this->gallery_urls = null;
|
53 |
+
$this->fb_use_parent_image = null;
|
54 |
+
$this->fb_price = 0;
|
55 |
+
$this->main_description = '';
|
56 |
+
$this->sync_short_description = get_option( 'fb_sync_short_description', false );
|
57 |
+
|
58 |
+
// Variable products should use some data from the parent_product
|
59 |
+
// For performance reasons, that data shouldn't be regenerated every time.
|
60 |
+
if ( $parent_product ) {
|
61 |
+
$this->gallery_urls = $parent_product->get_gallery_urls();
|
62 |
+
$this->fb_use_parent_image = $parent_product->get_use_parent_image();
|
63 |
+
$this->main_description = WC_Facebookcommerce_Utils::clean_string(
|
64 |
+
$parent_product->get_description()
|
65 |
+
);
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
+
public function exists() {
|
70 |
+
return ( $this->woo_product !== null && $this->woo_product !== false );
|
71 |
+
}
|
72 |
+
|
73 |
+
// Fall back to calling method on $woo_product
|
74 |
+
public function __call( $function, $args ) {
|
75 |
+
if ( $this->woo_product ) {
|
76 |
+
return call_user_func_array( array( $this->woo_product, $function ), $args );
|
77 |
+
} else {
|
78 |
+
$e = new Exception();
|
79 |
+
$backtrace = var_export( $e->getTraceAsString(), true );
|
80 |
+
WC_Facebookcommerce_Utils::fblog(
|
81 |
+
"Calling $function on Null Woo Object. Trace:\n" . $backtrace,
|
82 |
+
array(),
|
83 |
+
true
|
84 |
+
);
|
85 |
+
return null;
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
public function get_gallery_urls() {
|
90 |
+
if ( $this->gallery_urls === null ) {
|
91 |
+
if ( is_callable( array( $this, 'get_gallery_image_ids' ) ) ) {
|
92 |
+
$image_ids = $this->get_gallery_image_ids();
|
93 |
+
} else {
|
94 |
+
$image_ids = $this->get_gallery_attachment_ids();
|
95 |
+
}
|
96 |
+
$gallery_urls = array();
|
97 |
+
foreach ( $image_ids as $image_id ) {
|
98 |
+
$image_url = wp_get_attachment_url( $image_id );
|
99 |
+
if ( ! empty( $image_url ) ) {
|
100 |
+
array_push(
|
101 |
+
$gallery_urls,
|
102 |
+
WC_Facebookcommerce_Utils::make_url( $image_url )
|
103 |
+
);
|
104 |
+
}
|
105 |
+
}
|
106 |
+
$this->gallery_urls = array_filter( $gallery_urls );
|
107 |
+
}
|
108 |
+
|
109 |
+
return $this->gallery_urls;
|
110 |
+
}
|
111 |
+
|
112 |
+
public function get_post_data() {
|
113 |
+
if ( is_callable( 'get_post' ) ) {
|
114 |
+
return get_post( $this->id );
|
115 |
+
} else {
|
116 |
+
return $this->get_post_data();
|
117 |
+
}
|
118 |
+
}
|
119 |
+
|
120 |
+
public function get_fb_price() {
|
121 |
+
// Cache the price in this object in case of multiple calls.
|
122 |
+
if ( $this->fb_price ) {
|
123 |
+
return $this->fb_price;
|
124 |
+
}
|
125 |
+
|
126 |
+
$price = get_post_meta(
|
127 |
+
$this->id,
|
128 |
+
self::FB_PRODUCT_PRICE,
|
129 |
+
true
|
130 |
+
);
|
131 |
+
|
132 |
+
if ( is_numeric( $price ) ) {
|
133 |
+
return intval( round( $price * 100 ) );
|
134 |
+
}
|
135 |
+
|
136 |
+
// If product is composite product, we rely on their pricing.
|
137 |
+
if ( class_exists( 'WC_Product_Composite' )
|
138 |
+
&& $this->woo_product->get_type() === 'composite' ) {
|
139 |
+
$price = get_option( 'woocommerce_tax_display_shop' ) === 'incl'
|
140 |
+
? $this->woo_product->get_composite_price_including_tax()
|
141 |
+
: $this->woo_product->get_composite_price();
|
142 |
+
$this->fb_price = intval( round( $price * 100 ) );
|
143 |
+
return $this->fb_price;
|
144 |
+
}
|
145 |
+
|
146 |
+
// Get regular price: regular price doesn't include sales
|
147 |
+
$regular_price = floatval( $this->get_regular_price() );
|
148 |
+
|
149 |
+
// If it's a bookable product, the normal price is null/0.
|
150 |
+
if ( ! $regular_price &&
|
151 |
+
class_exists( 'WC_Product_Booking' ) &&
|
152 |
+
is_wc_booking_product( $this ) ) {
|
153 |
+
$product = new WC_Product_Booking( $this->woo_product );
|
154 |
+
$regular_price = $product->get_display_cost();
|
155 |
+
}
|
156 |
+
|
157 |
+
// Get regular price plus tax, if it's set to display and taxable
|
158 |
+
// whether price includes tax is based on 'woocommerce_tax_display_shop'
|
159 |
+
$price = $this->get_price_plus_tax( $regular_price );
|
160 |
+
$this->fb_price = intval( round( $price * 100 ) );
|
161 |
+
return $this->fb_price;
|
162 |
+
}
|
163 |
+
|
164 |
+
public function get_all_image_urls() {
|
165 |
+
$image_urls = array();
|
166 |
+
$parent_image_id = $this->get_parent_image_id();
|
167 |
+
$image_url = wp_get_attachment_url(
|
168 |
+
( $parent_image_id ) ?: $this->woo_product->get_image_id()
|
169 |
+
);
|
170 |
+
|
171 |
+
if ( $image_url ) {
|
172 |
+
$image_url = WC_Facebookcommerce_Utils::make_url( $image_url );
|
173 |
+
array_push( $image_urls, $image_url );
|
174 |
+
}
|
175 |
+
|
176 |
+
// For variable products, add the variation specific image.
|
177 |
+
if ( $parent_image_id ) {
|
178 |
+
$image_url2 = wp_get_attachment_url( $this->woo_product->get_image_id() );
|
179 |
+
$image_url2 = WC_Facebookcommerce_Utils::make_url( $image_url2 );
|
180 |
+
if ( $image_url != $image_url2 ) {
|
181 |
+
// A Checkbox toggles which image is primary.
|
182 |
+
// Default to variant specific image as primary.
|
183 |
+
if ( $this->fb_use_parent_image ) {
|
184 |
+
array_push( $image_urls, $image_url2 );
|
185 |
+
} else {
|
186 |
+
array_unshift( $image_urls, $image_url2 );
|
187 |
+
}
|
188 |
+
}
|
189 |
+
}
|
190 |
+
|
191 |
+
$gallery_urls = $this->get_gallery_urls();
|
192 |
+
$image_urls = array_merge( $image_urls, $gallery_urls );
|
193 |
+
$image_urls = array_filter( $image_urls );
|
194 |
+
|
195 |
+
// If there are no images, create a placeholder image.
|
196 |
+
if ( empty( $image_urls ) ) {
|
197 |
+
$name = urlencode( strip_tags( $this->woo_product->get_title() ) );
|
198 |
+
$image_url = 'https://placeholdit.imgix.net/~text?txtsize=33&txt='
|
199 |
+
. $name . '&w=530&h=530'; // TODO: BETTER PLACEHOLDER
|
200 |
+
return array( $image_url );
|
201 |
+
}
|
202 |
+
|
203 |
+
$image_override = get_post_meta( $this->id, self::FB_PRODUCT_IMAGE, true );
|
204 |
+
if ( $image_override ) {
|
205 |
+
array_unshift( $image_urls, $image_override );
|
206 |
+
$image_urls = array_unique( $image_urls );
|
207 |
+
}
|
208 |
+
|
209 |
+
return $image_urls;
|
210 |
+
}
|
211 |
+
|
212 |
+
// Returns the parent image id for variable products only.
|
213 |
+
public function get_parent_image_id() {
|
214 |
+
if ( WC_Facebookcommerce_Utils::is_variation_type( $this->woo_product->get_type() ) ) {
|
215 |
+
$parent_data = $this->get_parent_data();
|
216 |
+
return $parent_data['image_id'];
|
217 |
+
}
|
218 |
+
return null;
|
219 |
+
}
|
220 |
+
|
221 |
+
public function set_description( $description ) {
|
222 |
+
$description = stripslashes(
|
223 |
+
WC_Facebookcommerce_Utils::clean_string( $description )
|
224 |
+
);
|
225 |
+
$this->fb_description = $description;
|
226 |
+
update_post_meta(
|
227 |
+
$this->id,
|
228 |
+
self::FB_PRODUCT_DESCRIPTION,
|
229 |
+
$description
|
230 |
+
);
|
231 |
+
}
|
232 |
+
|
233 |
+
public function set_product_image( $image ) {
|
234 |
+
if ( $image !== null && strlen( $image ) !== 0 ) {
|
235 |
+
$image = WC_Facebookcommerce_Utils::clean_string( $image );
|
236 |
+
$image = WC_Facebookcommerce_Utils::make_url( $image );
|
237 |
+
update_post_meta(
|
238 |
+
$this->id,
|
239 |
+
self::FB_PRODUCT_IMAGE,
|
240 |
+
$image
|
241 |
+
);
|
242 |
+
}
|
243 |
+
}
|
244 |
+
|
245 |
+
public function set_price( $price ) {
|
246 |
+
if ( is_numeric( $price ) ) {
|
247 |
+
$this->fb_price = intval( round( $price * 100 ) );
|
248 |
+
update_post_meta(
|
249 |
+
$this->id,
|
250 |
+
self::FB_PRODUCT_PRICE,
|
251 |
+
$price
|
252 |
+
);
|
253 |
+
} else {
|
254 |
+
delete_post_meta(
|
255 |
+
$this->id,
|
256 |
+
self::FB_PRODUCT_PRICE
|
257 |
+
);
|
258 |
+
}
|
259 |
+
}
|
260 |
+
|
261 |
+
public function get_use_parent_image() {
|
262 |
+
if ( $this->fb_use_parent_image === null ) {
|
263 |
+
$variant_image_setting =
|
264 |
+
get_post_meta( $this->id, self::FB_VARIANT_IMAGE, true );
|
265 |
+
$this->fb_use_parent_image = ( $variant_image_setting ) ? true : false;
|
266 |
+
}
|
267 |
+
return $this->fb_use_parent_image;
|
268 |
+
}
|
269 |
+
|
270 |
+
public function set_use_parent_image( $setting ) {
|
271 |
+
$this->fb_use_parent_image = ( $setting == 'yes' );
|
272 |
+
update_post_meta(
|
273 |
+
$this->id,
|
274 |
+
self::FB_VARIANT_IMAGE,
|
275 |
+
$this->fb_use_parent_image
|
276 |
+
);
|
277 |
+
}
|
278 |
+
|
279 |
+
public function get_fb_description() {
|
280 |
+
if ( $this->fb_description ) {
|
281 |
+
return $this->fb_description;
|
282 |
+
}
|
283 |
+
|
284 |
+
$description = get_post_meta(
|
285 |
+
$this->id,
|
286 |
+
self::FB_PRODUCT_DESCRIPTION,
|
287 |
+
true
|
288 |
+
);
|
289 |
+
|
290 |
+
if ( $description ) {
|
291 |
+
return $description;
|
292 |
+
}
|
293 |
+
|
294 |
+
if ( WC_Facebookcommerce_Utils::is_variation_type( $this->woo_product->get_type() ) ) {
|
295 |
+
$description = WC_Facebookcommerce_Utils::clean_string(
|
296 |
+
$this->get_description()
|
297 |
+
);
|
298 |
+
if ( $description ) {
|
299 |
+
return $description;
|
300 |
+
}
|
301 |
+
if ( $this->main_description ) {
|
302 |
+
return $this->main_description;
|
303 |
+
}
|
304 |
+
}
|
305 |
+
|
306 |
+
$post = $this->get_post_data();
|
307 |
+
|
308 |
+
$post_content = WC_Facebookcommerce_Utils::clean_string(
|
309 |
+
$post->post_content
|
310 |
+
);
|
311 |
+
$post_excerpt = WC_Facebookcommerce_Utils::clean_string(
|
312 |
+
$post->post_excerpt
|
313 |
+
);
|
314 |
+
$post_title = WC_Facebookcommerce_Utils::clean_string(
|
315 |
+
$post->post_title
|
316 |
+
);
|
317 |
+
|
318 |
+
// Sanitize description
|
319 |
+
if ( $post_content ) {
|
320 |
+
$description = $post_content;
|
321 |
+
}
|
322 |
+
if ( $this->sync_short_description || ( $description == '' && $post_excerpt ) ) {
|
323 |
+
$description = $post_excerpt;
|
324 |
+
}
|
325 |
+
if ( $description == '' ) {
|
326 |
+
$description = $post_title;
|
327 |
+
}
|
328 |
+
|
329 |
+
return $description;
|
330 |
+
}
|
331 |
+
|
332 |
+
public function add_sale_price( $product_data ) {
|
333 |
+
// initialize sale date and sale_price
|
334 |
+
$product_data['sale_price_start_date'] = self::MIN_DATE_1 . self::MIN_TIME;
|
335 |
+
$product_data['sale_price_end_date'] = self::MIN_DATE_2 . self::MAX_TIME;
|
336 |
+
$product_data['sale_price'] = $product_data['price'];
|
337 |
+
|
338 |
+
$sale_price = $this->woo_product->get_sale_price();
|
339 |
+
// check if sale exist
|
340 |
+
if ( ! is_numeric( $sale_price ) ) {
|
341 |
+
return $product_data;
|
342 |
+
}
|
343 |
+
$sale_price =
|
344 |
+
intval( round( $this->get_price_plus_tax( $sale_price ) * 100 ) );
|
345 |
+
|
346 |
+
$sale_start =
|
347 |
+
( $date = get_post_meta( $this->id, '_sale_price_dates_from', true ) )
|
348 |
+
? date_i18n( 'Y-m-d', $date ) . self::MIN_TIME
|
349 |
+
: self::MIN_DATE_1 . self::MIN_TIME;
|
350 |
+
|
351 |
+
$sale_end =
|
352 |
+
( $date = get_post_meta( $this->id, '_sale_price_dates_to', true ) )
|
353 |
+
? date_i18n( 'Y-m-d', $date ) . self::MAX_TIME
|
354 |
+
: self::MAX_DATE . self::MAX_TIME;
|
355 |
+
|
356 |
+
// check if sale is expired and sale time range is valid
|
357 |
+
$product_data['sale_price_start_date'] = $sale_start;
|
358 |
+
$product_data['sale_price_end_date'] = $sale_end;
|
359 |
+
$product_data['sale_price'] = $sale_price;
|
360 |
+
return $product_data;
|
361 |
+
}
|
362 |
+
|
363 |
+
public function is_hidden() {
|
364 |
+
$wpid = $this->id;
|
365 |
+
if ( WC_Facebookcommerce_Utils::is_variation_type( $this->get_type() ) ) {
|
366 |
+
$wpid = $this->get_parent_id();
|
367 |
+
}
|
368 |
+
$hidden_from_catalog = has_term(
|
369 |
+
'exclude-from-catalog',
|
370 |
+
'product_visibility',
|
371 |
+
$wpid
|
372 |
+
);
|
373 |
+
$hidden_from_search = has_term(
|
374 |
+
'exclude-from-search',
|
375 |
+
'product_visibility',
|
376 |
+
$wpid
|
377 |
+
);
|
378 |
+
// fb_visibility === '': after initial sync by feed
|
379 |
+
// fb_visibility === false: set hidden on FB metadata
|
380 |
+
// Explicitly check whether flip 'hide' before.
|
381 |
+
return ( $hidden_from_catalog && $hidden_from_search ) ||
|
382 |
+
$this->fb_visibility === false || ! $this->get_fb_price();
|
383 |
+
}
|
384 |
+
|
385 |
+
public function get_price_plus_tax( $price ) {
|
386 |
+
$woo_product = $this->woo_product;
|
387 |
+
// // wc_get_price_including_tax exist for Woo > 2.7
|
388 |
+
if ( function_exists( 'wc_get_price_including_tax' ) ) {
|
389 |
+
$args = array(
|
390 |
+
'qty' => 1,
|
391 |
+
'price' => $price,
|
392 |
+
);
|
393 |
+
return get_option( 'woocommerce_tax_display_shop' ) === 'incl'
|
394 |
+
? wc_get_price_including_tax( $woo_product, $args )
|
395 |
+
: wc_get_price_excluding_tax( $woo_product, $args );
|
396 |
+
} else {
|
397 |
+
return get_option( 'woocommerce_tax_display_shop' ) === 'incl'
|
398 |
+
? $woo_product->get_price_including_tax( 1, $price )
|
399 |
+
: $woo_product->get_price_excluding_tax( 1, $price );
|
400 |
+
}
|
401 |
+
}
|
402 |
+
|
403 |
+
public function get_grouped_product_option_names( $key, $option_values ) {
|
404 |
+
// Convert all slug_names in $option_values into the visible names that
|
405 |
+
// advertisers have set to be the display names for a given attribute value
|
406 |
+
$terms = get_the_terms( $this->id, $key );
|
407 |
+
return array_map(
|
408 |
+
function ( $slug_name ) use ( $terms ) {
|
409 |
+
foreach ( $terms as $term ) {
|
410 |
+
if ( $term->slug === $slug_name ) {
|
411 |
+
return $term->name;
|
412 |
+
}
|
413 |
+
}
|
414 |
+
return $slug_name;
|
415 |
+
},
|
416 |
+
$option_values
|
417 |
+
);
|
418 |
+
}
|
419 |
+
|
420 |
+
public function get_variant_option_name( $label, $default_value ) {
|
421 |
+
// For the given label, get the Visible name rather than the slug
|
422 |
+
$meta = get_post_meta( $this->id, $label, true );
|
423 |
+
$attribute_name = str_replace( 'attribute_', '', $label );
|
424 |
+
$term = get_term_by( 'slug', $meta, $attribute_name );
|
425 |
+
return $term && $term->name ? $term->name : $default_value;
|
426 |
+
}
|
427 |
+
|
428 |
+
public function update_visibility( $is_product_page, $visible_box_checked ) {
|
429 |
+
$visibility = get_post_meta( $this->id, self::FB_VISIBILITY, true );
|
430 |
+
if ( $visibility && ! $is_product_page ) {
|
431 |
+
// If the product was previously set to visible, keep it as visible
|
432 |
+
// (unless we're on the product page)
|
433 |
+
$this->fb_visibility = $visibility;
|
434 |
+
} else {
|
435 |
+
// If the product is not visible OR we're on the product page,
|
436 |
+
// then update the visibility as needed.
|
437 |
+
$this->fb_visibility = $visible_box_checked ? true : false;
|
438 |
+
update_post_meta( $this->id, self::FB_VISIBILITY, $this->fb_visibility );
|
439 |
+
}
|
440 |
+
}
|
441 |
+
|
442 |
+
// wrapper function to find item_id for default variation
|
443 |
+
function find_matching_product_variation() {
|
444 |
+
if ( is_callable( array( $this, 'get_default_attributes' ) ) ) {
|
445 |
+
$default_attributes = $this->get_default_attributes();
|
446 |
+
} else {
|
447 |
+
$default_attributes = $this->get_variation_default_attributes();
|
448 |
+
}
|
449 |
+
|
450 |
+
if ( ! $default_attributes ) {
|
451 |
+
return;
|
452 |
+
}
|
453 |
+
foreach ( $default_attributes as $key => $value ) {
|
454 |
+
if ( strncmp( $key, 'attribute_', strlen( 'attribute_' ) ) === 0 ) {
|
455 |
+
continue;
|
456 |
+
}
|
457 |
+
unset( $default_attributes[ $key ] );
|
458 |
+
$default_attributes[ sprintf( 'attribute_%s', $key ) ] = $value;
|
459 |
+
}
|
460 |
+
if ( class_exists( 'WC_Data_Store' ) ) {
|
461 |
+
// for >= woo 3.0.0
|
462 |
+
$data_store = WC_Data_Store::load( 'product' );
|
463 |
+
return $data_store->find_matching_product_variation(
|
464 |
+
$this,
|
465 |
+
$default_attributes
|
466 |
+
);
|
467 |
+
} else {
|
468 |
+
return $this->get_matching_variation( $default_attributes );
|
469 |
+
}
|
470 |
+
}
|
471 |
+
|
472 |
+
/**
|
473 |
+
* Assemble product payload for POST
|
474 |
+
**/
|
475 |
+
function prepare_product(
|
476 |
+
$retailer_id = null,
|
477 |
+
$prepare_for_product_feed = false ) {
|
478 |
+
if ( ! $retailer_id ) {
|
479 |
+
$retailer_id =
|
480 |
+
WC_Facebookcommerce_Utils::get_fb_retailer_id( $this );
|
481 |
+
}
|
482 |
+
$image_urls = $this->get_all_image_urls();
|
483 |
+
|
484 |
+
// Replace WordPress sanitization's ampersand with a real ampersand.
|
485 |
+
$product_url = str_replace(
|
486 |
+
'&%3B',
|
487 |
+
'&',
|
488 |
+
html_entity_decode( $this->get_permalink() )
|
489 |
+
);
|
490 |
+
|
491 |
+
// Use product_url for external/bundle product setting.
|
492 |
+
$product_type = $this->get_type();
|
493 |
+
if ( ! $product_type || ! isset( self::$use_checkout_url[ $product_type ] ) ) {
|
494 |
+
$checkout_url = $product_url;
|
495 |
+
} elseif ( wc_get_cart_url() ) {
|
496 |
+
$char = '?';
|
497 |
+
// Some merchant cart pages are actually a querystring
|
498 |
+
if ( strpos( wc_get_cart_url(), '?' ) !== false ) {
|
499 |
+
$char = '&';
|
500 |
+
}
|
501 |
+
|
502 |
+
$checkout_url = WC_Facebookcommerce_Utils::make_url(
|
503 |
+
wc_get_cart_url() . $char
|
504 |
+
);
|
505 |
+
|
506 |
+
if ( WC_Facebookcommerce_Utils::is_variation_type( $this->get_type() ) ) {
|
507 |
+
$query_data = array(
|
508 |
+
'add-to-cart' => $this->get_parent_id(),
|
509 |
+
'variation_id' => $this->get_id(),
|
510 |
+
);
|
511 |
+
|
512 |
+
$query_data = array_merge(
|
513 |
+
$query_data,
|
514 |
+
$this->get_variation_attributes()
|
515 |
+
);
|
516 |
+
|
517 |
+
} else {
|
518 |
+
$query_data = array(
|
519 |
+
'add-to-cart' => $this->get_id(),
|
520 |
+
);
|
521 |
+
}
|
522 |
+
|
523 |
+
$checkout_url = $checkout_url . http_build_query( $query_data );
|
524 |
+
|
525 |
+
} else {
|
526 |
+
$checkout_url = null;
|
527 |
+
}
|
528 |
+
|
529 |
+
$id = $this->get_id();
|
530 |
+
if ( WC_Facebookcommerce_Utils::is_variation_type( $this->get_type() ) ) {
|
531 |
+
$id = $this->get_parent_id();
|
532 |
+
}
|
533 |
+
$categories =
|
534 |
+
WC_Facebookcommerce_Utils::get_product_categories( $id );
|
535 |
+
$brand = get_the_term_list( $id, 'product_brand', '', ', ' );
|
536 |
+
$brand = is_wp_error( $brand ) || ! $brand
|
537 |
+
? WC_Facebookcommerce_Utils::get_store_name()
|
538 |
+
: WC_Facebookcommerce_Utils::clean_string( $brand );
|
539 |
+
|
540 |
+
$product_data = array(
|
541 |
+
'name' => WC_Facebookcommerce_Utils::clean_string(
|
542 |
+
$this->get_title()
|
543 |
+
),
|
544 |
+
'description' => $this->get_fb_description(),
|
545 |
+
'image_url' => $image_urls[0], // The array can't be empty.
|
546 |
+
'additional_image_urls' => array_filter( $image_urls ),
|
547 |
+
'url' => $product_url,
|
548 |
+
'category' => $categories['categories'],
|
549 |
+
'brand' => $brand,
|
550 |
+
'retailer_id' => $retailer_id,
|
551 |
+
'price' => $this->get_fb_price(),
|
552 |
+
'currency' => get_woocommerce_currency(),
|
553 |
+
'availability' => $this->is_in_stock() ? 'in stock' :
|
554 |
+
'out of stock',
|
555 |
+
'visibility' => ! $this->is_hidden()
|
556 |
+
? 'published'
|
557 |
+
: 'staging',
|
558 |
+
);
|
559 |
+
|
560 |
+
// Only use checkout URLs if they exist.
|
561 |
+
if ( $checkout_url ) {
|
562 |
+
$product_data['checkout_url'] = $checkout_url;
|
563 |
+
}
|
564 |
+
|
565 |
+
$product_data = $this->add_sale_price( $product_data );
|
566 |
+
|
567 |
+
// IF using WPML, set the product to staging unless it is in the
|
568 |
+
// default language. WPML >= 3.2 Supported.
|
569 |
+
if ( defined( 'ICL_LANGUAGE_CODE' ) ) {
|
570 |
+
if ( class_exists( 'WC_Facebook_WPML_Injector' ) && WC_Facebook_WPML_Injector::should_hide( $id ) ) {
|
571 |
+
$product_data['visibility'] = 'staging';
|
572 |
+
}
|
573 |
+
}
|
574 |
+
|
575 |
+
// Exclude variations that are "virtual" products from export to Facebook &&
|
576 |
+
// No Visibility Option for Variations
|
577 |
+
if ( true === $this->get_virtual() ) {
|
578 |
+
$product_data['visibility'] = 'staging';
|
579 |
+
}
|
580 |
+
|
581 |
+
if ( ! $prepare_for_product_feed ) {
|
582 |
+
$this->prepare_variants_for_item( $product_data );
|
583 |
+
} elseif (
|
584 |
+
WC_Facebookcommerce_Utils::is_all_caps( $product_data['description'] )
|
585 |
+
) {
|
586 |
+
$product_data['description'] =
|
587 |
+
mb_strtolower( $product_data['description'] );
|
588 |
+
}
|
589 |
+
|
590 |
+
/**
|
591 |
+
* Filters the generated product data.
|
592 |
+
*
|
593 |
+
* @param int $id Woocommerce product id
|
594 |
+
* @param array $product_data An array of product data
|
595 |
+
*/
|
596 |
+
return apply_filters(
|
597 |
+
'facebook_for_woocommerce_integration_prepare_product',
|
598 |
+
$product_data,
|
599 |
+
$id
|
600 |
+
);
|
601 |
+
}
|
602 |
+
|
603 |
+
|
604 |
+
/**
|
605 |
+
* Modify Woo variant/taxonomies to be FB compatible
|
606 |
+
**/
|
607 |
+
public function prepare_variants_for_item( &$product_data ) {
|
608 |
+
if ( ! WC_Facebookcommerce_Utils::is_variation_type(
|
609 |
+
$this->get_type()
|
610 |
+
) ) {
|
611 |
+
return;
|
612 |
+
}
|
613 |
+
|
614 |
+
$attributes = $this->get_variation_attributes();
|
615 |
+
if ( ! $attributes ) {
|
616 |
+
return;
|
617 |
+
}
|
618 |
+
|
619 |
+
$variant_names = array_keys( $attributes );
|
620 |
+
$variant_array = array();
|
621 |
+
|
622 |
+
// Loop through variants (size, color, etc) if they exist
|
623 |
+
// For each product field type, pull the single variant
|
624 |
+
foreach ( $variant_names as $orig_name ) {
|
625 |
+
// Retrieve label name for attribute
|
626 |
+
$label = wc_attribute_label( $orig_name, $this );
|
627 |
+
|
628 |
+
// Clean up variant name (e.g. pa_color should be color)
|
629 |
+
// Replace "custom_data:foo" with just "foo" so we can use the key
|
630 |
+
// Product item API expects "custom_data" instead of "custom_data:foo"
|
631 |
+
$new_name = str_replace(
|
632 |
+
'custom_data:',
|
633 |
+
'',
|
634 |
+
WC_Facebookcommerce_Utils::sanitize_variant_name( $orig_name )
|
635 |
+
);
|
636 |
+
|
637 |
+
// Sometimes WC returns an array, sometimes it's an assoc array, depending
|
638 |
+
// on what type of taxonomy it's using. array_values will guarantee we
|
639 |
+
// only get a flat array of values.
|
640 |
+
$options = $this->get_variant_option_name(
|
641 |
+
$label,
|
642 |
+
$attributes[ $orig_name ]
|
643 |
+
);
|
644 |
+
if ( isset( $options ) ) {
|
645 |
+
if ( is_array( $options ) ) {
|
646 |
+
$option_values = array_values( $options );
|
647 |
+
} else {
|
648 |
+
$option_values = array( $options );
|
649 |
+
// If this attribute has value 'any', options will be empty strings
|
650 |
+
// Redirect to product page to select variants.
|
651 |
+
// Reset checkout url since checkout_url (build from query data will
|
652 |
+
// be invalid in this case.
|
653 |
+
if ( count( $option_values ) === 1 && empty( $option_values[0] ) ) {
|
654 |
+
$option_values[0] = 'any';
|
655 |
+
$product_data['checkout_url'] = $product_data['url'];
|
656 |
+
}
|
657 |
+
}
|
658 |
+
if ( $new_name === WC_Facebookcommerce_Utils::FB_VARIANT_GENDER ) {
|
659 |
+
// If we can't validate the gender, this will be null.
|
660 |
+
$product_data[ $new_name ] =
|
661 |
+
WC_Facebookcommerce_Utils::validateGender( $option_values[0] );
|
662 |
+
}
|
663 |
+
|
664 |
+
switch ( $new_name ) {
|
665 |
+
case WC_Facebookcommerce_Utils::FB_VARIANT_SIZE:
|
666 |
+
case WC_Facebookcommerce_Utils::FB_VARIANT_COLOR:
|
667 |
+
case WC_Facebookcommerce_Utils::FB_VARIANT_PATTERN:
|
668 |
+
array_push(
|
669 |
+
$variant_array,
|
670 |
+
array(
|
671 |
+
'product_field' => $new_name,
|
672 |
+
'label' => $label,
|
673 |
+
'options' => $option_values,
|
674 |
+
)
|
675 |
+
);
|
676 |
+
$product_data[ $new_name ] = $option_values[0];
|
677 |
+
break;
|
678 |
+
case WC_Facebookcommerce_Utils::FB_VARIANT_GENDER:
|
679 |
+
// If we can't validate the GENDER field, we'll fall through to the
|
680 |
+
// default case and set the gender into custom data.
|
681 |
+
if ( $product_data[ $new_name ] ) {
|
682 |
+
array_push(
|
683 |
+
$variant_array,
|
684 |
+
array(
|
685 |
+
'product_field' => $new_name,
|
686 |
+
'label' => $label,
|
687 |
+
'options' => $option_values,
|
688 |
+
)
|
689 |
+
);
|
690 |
+
break;
|
691 |
+
}
|
692 |
+
|
693 |
+
default:
|
694 |
+
// This is for any custom_data.
|
695 |
+
if ( ! isset( $product_data['custom_data'] ) ) {
|
696 |
+
$product_data['custom_data'] = array();
|
697 |
+
}
|
698 |
+
$product_data['custom_data'][ $new_name ]
|
699 |
+
= urldecode( $option_values[0] );
|
700 |
+
break;
|
701 |
+
}
|
702 |
+
} else {
|
703 |
+
WC_Facebookcommerce_Utils::log(
|
704 |
+
$this->get_id() . ': No options for ' . $orig_name
|
705 |
+
);
|
706 |
+
continue;
|
707 |
+
}
|
708 |
+
}
|
709 |
+
return $variant_array;
|
710 |
+
}
|
711 |
+
|
712 |
+
/**
|
713 |
+
* Modify Woo variant/taxonomies for variable products to be FB compatible
|
714 |
+
**/
|
715 |
+
public function prepare_variants_for_group( $feed_data = false ) {
|
716 |
+
if ( ! WC_Facebookcommerce_Utils::is_variable_type(
|
717 |
+
$this->get_type()
|
718 |
+
) ) {
|
719 |
+
WC_Facebookcommerce_Utils::fblog(
|
720 |
+
'prepare_variants_for_group called on non-variable product'
|
721 |
+
);
|
722 |
+
return;
|
723 |
+
}
|
724 |
+
|
725 |
+
$variation_attributes = $this->get_variation_attributes();
|
726 |
+
if ( ! $variation_attributes ) {
|
727 |
+
return;
|
728 |
+
}
|
729 |
+
$final_variants = array();
|
730 |
+
|
731 |
+
$attrs = array_keys( $this->get_attributes() );
|
732 |
+
foreach ( $attrs as $name ) {
|
733 |
+
$label = wc_attribute_label( $name, $this );
|
734 |
+
|
735 |
+
if ( taxonomy_is_product_attribute( $name ) ) {
|
736 |
+
$key = $name;
|
737 |
+
} else {
|
738 |
+
// variation_attributes keys are labels for custom attrs for some reason
|
739 |
+
$key = $label;
|
740 |
+
}
|
741 |
+
|
742 |
+
if ( ! $key ) {
|
743 |
+
WC_Facebookcommerce_Utils::fblog(
|
744 |
+
"Critical error: can't get attribute name or label!"
|
745 |
+
);
|
746 |
+
return;
|
747 |
+
}
|
748 |
+
|
749 |
+
if ( isset( $variation_attributes[ $key ] ) ) {
|
750 |
+
// Array of the options (e.g. small, medium, large)
|
751 |
+
$option_values = $variation_attributes[ $key ];
|
752 |
+
} else {
|
753 |
+
WC_Facebookcommerce_Utils::log(
|
754 |
+
$this->get_id() . ': No options for ' . $name
|
755 |
+
);
|
756 |
+
continue; // Skip variations without valid attribute options
|
757 |
+
}
|
758 |
+
|
759 |
+
// If this is a wc_product_variable, check default attrib.
|
760 |
+
// If it's being used, show it as the first option on Facebook.
|
761 |
+
$first_option = $this->get_variation_default_attribute( $key );
|
762 |
+
if ( $first_option ) {
|
763 |
+
$idx = array_search( $first_option, $option_values );
|
764 |
+
unset( $option_values[ $idx ] );
|
765 |
+
array_unshift( $option_values, $first_option );
|
766 |
+
}
|
767 |
+
|
768 |
+
if (
|
769 |
+
function_exists( 'taxonomy_is_product_attribute' ) &&
|
770 |
+
taxonomy_is_product_attribute( $name )
|
771 |
+
) {
|
772 |
+
$option_values = $this->get_grouped_product_option_names(
|
773 |
+
$key,
|
774 |
+
$option_values
|
775 |
+
);
|
776 |
+
}
|
777 |
+
|
778 |
+
// https://developers.facebook.com/docs/marketing-api/reference/product-variant/
|
779 |
+
// For API approach, product_field need to start with 'custom_data:'
|
780 |
+
// Clean up variant name (e.g. pa_color should be color)
|
781 |
+
$name = WC_Facebookcommerce_Utils::sanitize_variant_name( $name );
|
782 |
+
|
783 |
+
// For feed uploading, product field should remove prefix 'custom_data:'
|
784 |
+
if ( $feed_data ) {
|
785 |
+
$name = str_replace( 'custom_data:', '', $name );
|
786 |
+
}
|
787 |
+
array_push(
|
788 |
+
$final_variants,
|
789 |
+
array(
|
790 |
+
'product_field' => $name,
|
791 |
+
'label' => $label,
|
792 |
+
'options' => $option_values,
|
793 |
+
)
|
794 |
+
);
|
795 |
+
}
|
796 |
+
|
797 |
+
return $final_variants;
|
798 |
+
|
799 |
+
}
|
800 |
+
}
|
801 |
|
802 |
endif;
|
includes/fbproductfeed.php
CHANGED
@@ -8,360 +8,393 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
-
if (! defined('ABSPATH')) {
|
12 |
-
|
13 |
}
|
14 |
|
15 |
-
if (! class_exists('WC_Facebook_Product_Feed')) :
|
16 |
-
|
17 |
-
/**
|
18 |
-
|
19 |
-
|
20 |
-
class WC_Facebook_Product_Feed {
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
366 |
|
367 |
endif;
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
12 |
+
exit;
|
13 |
}
|
14 |
|
15 |
+
if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Initial Sync by Facebook feed class
|
19 |
+
*/
|
20 |
+
class WC_Facebook_Product_Feed {
|
21 |
+
|
22 |
+
const FACEBOOK_CATALOG_FEED_FILENAME = 'fae_product_catalog.csv';
|
23 |
+
const FB_ADDITIONAL_IMAGES_FOR_FEED = 5;
|
24 |
+
const FEED_NAME = 'Initial product sync from WooCommerce. DO NOT DELETE.';
|
25 |
+
const FB_PRODUCT_GROUP_ID = 'fb_product_group_id';
|
26 |
+
const FB_VISIBILITY = 'fb_visibility';
|
27 |
+
|
28 |
+
private $has_default_product_count = 0;
|
29 |
+
private $no_default_product_count = 0;
|
30 |
+
|
31 |
+
public function __construct(
|
32 |
+
$facebook_catalog_id,
|
33 |
+
$fbgraph,
|
34 |
+
$feed_id = null ) {
|
35 |
+
$this->facebook_catalog_id = $facebook_catalog_id;
|
36 |
+
$this->fbgraph = $fbgraph;
|
37 |
+
$this->feed_id = $feed_id;
|
38 |
+
}
|
39 |
+
|
40 |
+
public function sync_all_products_using_feed() {
|
41 |
+
$start_time = microtime( true );
|
42 |
+
$this->log_feed_progress( 'Sync all products using feed' );
|
43 |
+
|
44 |
+
if ( ! is_writable( dirname( __FILE__ ) ) ) {
|
45 |
+
$this->log_feed_progress(
|
46 |
+
'Failure - Sync all products using feed, folder is not writable'
|
47 |
+
);
|
48 |
+
return false;
|
49 |
+
}
|
50 |
+
|
51 |
+
if ( ! $this->generate_productfeed_file() ) {
|
52 |
+
$this->log_feed_progress(
|
53 |
+
'Failure - Sync all products using feed, feed file not generated'
|
54 |
+
);
|
55 |
+
return false;
|
56 |
+
}
|
57 |
+
$this->log_feed_progress( 'Sync all products using feed, feed file generated' );
|
58 |
+
|
59 |
+
if ( ! $this->feed_id ) {
|
60 |
+
$this->feed_id = $this->create_feed();
|
61 |
+
if ( ! $this->feed_id ) {
|
62 |
+
$this->log_feed_progress(
|
63 |
+
'Failure - Sync all products using feed, facebook feed not created'
|
64 |
+
);
|
65 |
+
return false;
|
66 |
+
}
|
67 |
+
$this->log_feed_progress(
|
68 |
+
'Sync all products using feed, facebook feed created'
|
69 |
+
);
|
70 |
+
} else {
|
71 |
+
$this->log_feed_progress(
|
72 |
+
'Sync all products using feed, facebook feed already exists.'
|
73 |
+
);
|
74 |
+
}
|
75 |
+
|
76 |
+
$this->upload_id = $this->create_upload( $this->feed_id );
|
77 |
+
if ( ! $this->upload_id ) {
|
78 |
+
$this->log_feed_progress(
|
79 |
+
'Failure - Sync all products using feed, facebook upload not created'
|
80 |
+
);
|
81 |
+
return false;
|
82 |
+
}
|
83 |
+
$this->log_feed_progress(
|
84 |
+
'Sync all products using feed, facebook upload created'
|
85 |
+
);
|
86 |
+
|
87 |
+
unlink(
|
88 |
+
dirname( __FILE__ ) .
|
89 |
+
DIRECTORY_SEPARATOR . ( self::FACEBOOK_CATALOG_FEED_FILENAME )
|
90 |
+
);
|
91 |
+
|
92 |
+
$total_product_count =
|
93 |
+
$this->has_default_product_count + $this->no_default_product_count;
|
94 |
+
$default_product_percentage =
|
95 |
+
( $total_product_count == 0 || $this->has_default_product_count == 0 )
|
96 |
+
? 0
|
97 |
+
: $this->has_default_product_count / $total_product_count * 100;
|
98 |
+
$time_spent = microtime( true ) - $start_time;
|
99 |
+
$data = array();
|
100 |
+
// Only log performance if this store has products in order to get average
|
101 |
+
// performance.
|
102 |
+
if ( $total_product_count != 0 ) {
|
103 |
+
$data = array(
|
104 |
+
'sync_time' => $time_spent,
|
105 |
+
'total' => $total_product_count,
|
106 |
+
'default_product_percentage' => $default_product_percentage,
|
107 |
+
);
|
108 |
+
}
|
109 |
+
$this->log_feed_progress( 'Complete - Sync all products using feed.', $data );
|
110 |
+
return true;
|
111 |
+
}
|
112 |
+
|
113 |
+
public function generate_productfeed_file() {
|
114 |
+
$this->log_feed_progress( 'Generating product feed file' );
|
115 |
+
$post_ids = $this->get_product_wpid();
|
116 |
+
$all_parent_product = array_map(
|
117 |
+
function( $post_id ) {
|
118 |
+
if ( get_post_type( $post_id ) == 'product_variation' ) {
|
119 |
+
return wp_get_post_parent_id( $post_id );
|
120 |
+
}
|
121 |
+
},
|
122 |
+
$post_ids
|
123 |
+
);
|
124 |
+
$all_parent_product = array_filter( array_unique( $all_parent_product ) );
|
125 |
+
$product_ids = array_diff( $post_ids, $all_parent_product );
|
126 |
+
return $this->write_product_feed_file( $product_ids );
|
127 |
+
}
|
128 |
+
|
129 |
+
public function write_product_feed_file( $wp_ids ) {
|
130 |
+
try {
|
131 |
+
$feed_file =
|
132 |
+
fopen(
|
133 |
+
dirname( __FILE__ ) . DIRECTORY_SEPARATOR .
|
134 |
+
( self::FACEBOOK_CATALOG_FEED_FILENAME ),
|
135 |
+
'w'
|
136 |
+
);
|
137 |
+
fwrite( $feed_file, $this->get_product_feed_header_row() );
|
138 |
+
|
139 |
+
$product_group_attribute_variants = array();
|
140 |
+
foreach ( $wp_ids as $wp_id ) {
|
141 |
+
$woo_product = new WC_Facebook_Product( $wp_id );
|
142 |
+
if ( $woo_product->is_hidden() ) {
|
143 |
+
continue;
|
144 |
+
}
|
145 |
+
if ( get_option( 'woocommerce_hide_out_of_stock_items' ) === 'yes' &&
|
146 |
+
! $woo_product->is_in_stock() ) {
|
147 |
+
continue;
|
148 |
+
}
|
149 |
+
$product_data_as_feed_row = $this->prepare_product_for_feed(
|
150 |
+
$woo_product,
|
151 |
+
$product_group_attribute_variants
|
152 |
+
);
|
153 |
+
fwrite( $feed_file, $product_data_as_feed_row );
|
154 |
+
}
|
155 |
+
fclose( $feed_file );
|
156 |
+
wp_reset_postdata();
|
157 |
+
return true;
|
158 |
+
} catch ( Exception $e ) {
|
159 |
+
WC_Facebookcommerce_Utils::log( json_encode( $e->getMessage() ) );
|
160 |
+
return false;
|
161 |
+
}
|
162 |
+
}
|
163 |
+
|
164 |
+
public function get_product_feed_header_row() {
|
165 |
+
return 'id,title,description,image_link,link,product_type,' .
|
166 |
+
'brand,price,availability,item_group_id,checkout_url,' .
|
167 |
+
'additional_image_link,sale_price_effective_date,sale_price,condition,' .
|
168 |
+
'visibility,default_product,variant' . PHP_EOL;
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* Assemble product payload in feed upload for initial sync.
|
173 |
+
**/
|
174 |
+
private function prepare_product_for_feed(
|
175 |
+
$woo_product,
|
176 |
+
&$attribute_variants ) {
|
177 |
+
$product_data = $woo_product->prepare_product( null, true );
|
178 |
+
$item_group_id = $product_data['retailer_id'];
|
179 |
+
// prepare variant column for variable products
|
180 |
+
$product_data['variant'] = '';
|
181 |
+
if (
|
182 |
+
WC_Facebookcommerce_Utils::is_variation_type( $woo_product->get_type() )
|
183 |
+
) {
|
184 |
+
$parent_id = $woo_product->get_parent_id();
|
185 |
+
|
186 |
+
if ( ! isset( $attribute_variants[ $parent_id ] ) ) {
|
187 |
+
$parent_product = new WC_Facebook_Product( $parent_id );
|
188 |
+
|
189 |
+
$gallery_urls = array_filter( $parent_product->get_gallery_urls() );
|
190 |
+
$variation_id = $parent_product->find_matching_product_variation();
|
191 |
+
$variants_for_group = $parent_product->prepare_variants_for_group( true );
|
192 |
+
$parent_attribute_values = array();
|
193 |
+
$parent_attribute_values['gallery_urls'] = $gallery_urls;
|
194 |
+
$parent_attribute_values['default_variant_id'] = $variation_id;
|
195 |
+
$parent_attribute_values['item_group_id'] =
|
196 |
+
WC_Facebookcommerce_Utils::get_fb_retailer_id( $parent_product );
|
197 |
+
foreach ( $variants_for_group as $variant ) {
|
198 |
+
$parent_attribute_values[ $variant['product_field'] ] =
|
199 |
+
$variant['options'];
|
200 |
+
}
|
201 |
+
// cache product group variants
|
202 |
+
$attribute_variants[ $parent_id ] = $parent_attribute_values;
|
203 |
+
}
|
204 |
+
$parent_attribute_values = $attribute_variants[ $parent_id ];
|
205 |
+
$variants_for_item =
|
206 |
+
$woo_product->prepare_variants_for_item( $product_data );
|
207 |
+
$variant_feed_column = array();
|
208 |
+
foreach ( $variants_for_item as $variant_array ) {
|
209 |
+
static::format_variant_for_feed(
|
210 |
+
$variant_array['product_field'],
|
211 |
+
$variant_array['options'][0],
|
212 |
+
$parent_attribute_values,
|
213 |
+
$variant_feed_column
|
214 |
+
);
|
215 |
+
}
|
216 |
+
if ( isset( $product_data['custom_data'] ) ) {
|
217 |
+
foreach ( $product_data['custom_data'] as $product_field => $value ) {
|
218 |
+
static::format_variant_for_feed(
|
219 |
+
$product_field,
|
220 |
+
$value,
|
221 |
+
$parent_attribute_values,
|
222 |
+
$variant_feed_column
|
223 |
+
);
|
224 |
+
}
|
225 |
+
}
|
226 |
+
if ( ! empty( $variant_feed_column ) ) {
|
227 |
+
$product_data['variant'] =
|
228 |
+
'"' . implode( ',', $variant_feed_column ) . '"';
|
229 |
+
}
|
230 |
+
if ( isset( $parent_attribute_values['gallery_urls'] ) ) {
|
231 |
+
$product_data['additional_image_urls'] =
|
232 |
+
array_merge(
|
233 |
+
$product_data['additional_image_urls'],
|
234 |
+
$parent_attribute_values['gallery_urls']
|
235 |
+
);
|
236 |
+
}
|
237 |
+
if ( isset( $parent_attribute_values['item_group_id'] ) ) {
|
238 |
+
$item_group_id = $parent_attribute_values['item_group_id'];
|
239 |
+
}
|
240 |
+
|
241 |
+
$product_data['default_product'] =
|
242 |
+
$parent_attribute_values['default_variant_id'] == $woo_product->id
|
243 |
+
? 'default'
|
244 |
+
: '';
|
245 |
+
|
246 |
+
// If this group has default variant value, log this product item
|
247 |
+
if ( isset( $parent_attribute_values['default_variant_id'] ) &&
|
248 |
+
! empty( $parent_attribute_values['default_variant_id'] ) ) {
|
249 |
+
$this->has_default_product_count++;
|
250 |
+
} else {
|
251 |
+
$this->no_default_product_count++;
|
252 |
+
}
|
253 |
+
}
|
254 |
+
|
255 |
+
// log simple product
|
256 |
+
if ( ! isset( $product_data['default_product'] ) ) {
|
257 |
+
$this->no_default_product_count++;
|
258 |
+
$product_data['default_product'];
|
259 |
+
}
|
260 |
+
|
261 |
+
return $product_data['retailer_id'] . ',' .
|
262 |
+
static::format_string_for_feed( $product_data['name'] ) . ',' .
|
263 |
+
static::format_string_for_feed( $product_data['description'] ) . ',' .
|
264 |
+
$product_data['image_url'] . ',' .
|
265 |
+
$product_data['url'] . ',' .
|
266 |
+
static::format_string_for_feed( $product_data['category'] ) . ',' .
|
267 |
+
static::format_string_for_feed( $product_data['brand'] ) . ',' .
|
268 |
+
static::format_price_for_feed(
|
269 |
+
$product_data['price'],
|
270 |
+
$product_data['currency']
|
271 |
+
) . ',' .
|
272 |
+
$product_data['availability'] . ',' .
|
273 |
+
$item_group_id . ',' .
|
274 |
+
$product_data['checkout_url'] . ',' .
|
275 |
+
static::format_additional_image_url(
|
276 |
+
$product_data['additional_image_urls']
|
277 |
+
) . ',' .
|
278 |
+
$product_data['sale_price_start_date'] . '/' .
|
279 |
+
$product_data['sale_price_end_date'] . ',' .
|
280 |
+
static::format_price_for_feed(
|
281 |
+
$product_data['sale_price'],
|
282 |
+
$product_data['currency']
|
283 |
+
) . ',' .
|
284 |
+
'new' . ',' .
|
285 |
+
$product_data['visibility'] . ',' .
|
286 |
+
$product_data['default_product'] . ',' .
|
287 |
+
$product_data['variant'] . PHP_EOL;
|
288 |
+
}
|
289 |
+
|
290 |
+
private function create_feed() {
|
291 |
+
$result = $this->fbgraph->create_feed(
|
292 |
+
$this->facebook_catalog_id,
|
293 |
+
array( 'name' => self::FEED_NAME )
|
294 |
+
);
|
295 |
+
if ( is_wp_error( $result ) || ! isset( $result['body'] ) ) {
|
296 |
+
$this->log_feed_progress( json_encode( $result ) );
|
297 |
+
return null;
|
298 |
+
}
|
299 |
+
$decode_result = WC_Facebookcommerce_Utils::decode_json( $result['body'] );
|
300 |
+
$feed_id = $decode_result->id;
|
301 |
+
if ( ! $feed_id ) {
|
302 |
+
$this->log_feed_progress(
|
303 |
+
'Response from creating feed not return feed id!'
|
304 |
+
);
|
305 |
+
return null;
|
306 |
+
}
|
307 |
+
return $feed_id;
|
308 |
+
}
|
309 |
+
|
310 |
+
private function create_upload( $facebook_feed_id ) {
|
311 |
+
$result = $this->fbgraph->create_upload(
|
312 |
+
$facebook_feed_id,
|
313 |
+
dirname( __FILE__ ) . DIRECTORY_SEPARATOR .
|
314 |
+
( self::FACEBOOK_CATALOG_FEED_FILENAME )
|
315 |
+
);
|
316 |
+
if ( is_null( $result ) || ! isset( $result['id'] ) || ! $result['id'] ) {
|
317 |
+
$this->log_feed_progress( json_encode( $result ) );
|
318 |
+
return null;
|
319 |
+
}
|
320 |
+
$upload_id = $result['id'];
|
321 |
+
return $upload_id;
|
322 |
+
}
|
323 |
+
|
324 |
+
private static function format_additional_image_url( $product_image_urls ) {
|
325 |
+
// returns the top 10 additional image urls separated by a comma
|
326 |
+
// according to feed api rules
|
327 |
+
$product_image_urls = array_slice(
|
328 |
+
$product_image_urls,
|
329 |
+
0,
|
330 |
+
self::FB_ADDITIONAL_IMAGES_FOR_FEED
|
331 |
+
);
|
332 |
+
if ( $product_image_urls ) {
|
333 |
+
return '"' . implode( ',', $product_image_urls ) . '"';
|
334 |
+
} else {
|
335 |
+
return '';
|
336 |
+
}
|
337 |
+
}
|
338 |
+
|
339 |
+
private static function format_string_for_feed( $text ) {
|
340 |
+
if ( (bool) $text ) {
|
341 |
+
return '"' . str_replace( '"', "'", $text ) . '"';
|
342 |
+
} else {
|
343 |
+
return '';
|
344 |
+
}
|
345 |
+
}
|
346 |
+
|
347 |
+
private static function format_price_for_feed( $value, $currency ) {
|
348 |
+
return (string) ( round( $value / (float) 100, 2 ) ) . $currency;
|
349 |
+
}
|
350 |
+
|
351 |
+
private static function format_variant_for_feed(
|
352 |
+
$product_field,
|
353 |
+
$value,
|
354 |
+
$parent_attribute_values,
|
355 |
+
&$variant_feed_column ) {
|
356 |
+
if ( ! array_key_exists( $product_field, $parent_attribute_values ) ) {
|
357 |
+
return;
|
358 |
+
}
|
359 |
+
array_push(
|
360 |
+
$variant_feed_column,
|
361 |
+
$product_field . ':' .
|
362 |
+
implode( '/', $parent_attribute_values[ $product_field ] ) . ':' .
|
363 |
+
$value
|
364 |
+
);
|
365 |
+
}
|
366 |
+
|
367 |
+
public function is_upload_complete( &$settings ) {
|
368 |
+
$result = $this->fbgraph->get_upload_status( $settings['fb_upload_id'] );
|
369 |
+
if ( is_wp_error( $result ) || ! isset( $result['body'] ) ) {
|
370 |
+
$this->log_feed_progress( json_encode( $result ) );
|
371 |
+
return 'error';
|
372 |
+
}
|
373 |
+
$decode_result = WC_Facebookcommerce_Utils::decode_json( $result['body'], true );
|
374 |
+
$end_time = $decode_result['end_time'];
|
375 |
+
if ( isset( $end_time ) ) {
|
376 |
+
$settings['upload_end_time'] = $end_time;
|
377 |
+
return 'complete';
|
378 |
+
} else {
|
379 |
+
return 'in progress';
|
380 |
+
}
|
381 |
+
}
|
382 |
+
|
383 |
+
// Log progress in local log file and FB.
|
384 |
+
public function log_feed_progress( $msg, $object = array() ) {
|
385 |
+
WC_Facebookcommerce_Utils::fblog( $msg, $object );
|
386 |
+
$msg = empty( $object ) ? $msg : $msg . json_encode( $object );
|
387 |
+
WC_Facebookcommerce_Utils::log( $msg );
|
388 |
+
}
|
389 |
+
|
390 |
+
public function get_product_wpid() {
|
391 |
+
$post_ids = WC_Facebookcommerce_Utils::get_wp_posts(
|
392 |
+
null,
|
393 |
+
null,
|
394 |
+
array( 'product', 'product_variation' )
|
395 |
+
);
|
396 |
+
return $post_ids;
|
397 |
+
}
|
398 |
+
}
|
399 |
|
400 |
endif;
|
includes/fbutils.php
CHANGED
@@ -8,478 +8,498 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
-
if (!defined('ABSPATH')) {
|
12 |
-
|
13 |
}
|
14 |
|
15 |
-
if (!class_exists('WC_Facebookcommerce_Utils')) :
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
484 |
|
485 |
endif;
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
12 |
+
exit;
|
13 |
}
|
14 |
|
15 |
+
if ( ! class_exists( 'WC_Facebookcommerce_Utils' ) ) :
|
16 |
+
|
17 |
+
/**
|
18 |
+
* FB Graph API helper functions
|
19 |
+
*/
|
20 |
+
class WC_Facebookcommerce_Utils {
|
21 |
+
|
22 |
+
const FB_RETAILER_ID_PREFIX = 'wc_post_id_';
|
23 |
+
const PLUGIN_VERSION = '1.9.15'; // Change it in `facebook-for-*.php` also
|
24 |
+
|
25 |
+
const FB_VARIANT_IMAGE = 'fb_image';
|
26 |
+
const FB_VARIANT_SIZE = 'size';
|
27 |
+
const FB_VARIANT_COLOR = 'color';
|
28 |
+
const FB_VARIANT_COLOUR = 'colour';
|
29 |
+
const FB_VARIANT_PATTERN = 'pattern';
|
30 |
+
const FB_VARIANT_GENDER = 'gender';
|
31 |
+
|
32 |
+
public static $ems = null;
|
33 |
+
public static $fbgraph = null;
|
34 |
+
public static $store_name = null;
|
35 |
+
|
36 |
+
public static $validGenderArray =
|
37 |
+
array(
|
38 |
+
'male' => 1,
|
39 |
+
'female' => 1,
|
40 |
+
'unisex' => 1,
|
41 |
+
);
|
42 |
+
/**
|
43 |
+
* WooCommerce 2.1 support for wc_enqueue_js
|
44 |
+
*
|
45 |
+
* @since 1.2.1
|
46 |
+
*
|
47 |
+
* @access public
|
48 |
+
* @param string $code
|
49 |
+
* @return void
|
50 |
+
*/
|
51 |
+
public static function wc_enqueue_js( $code ) {
|
52 |
+
global $wc_queued_js;
|
53 |
+
|
54 |
+
if ( function_exists( 'wc_enqueue_js' ) && empty( $wc_queued_js ) ) {
|
55 |
+
wc_enqueue_js( $code );
|
56 |
+
} else {
|
57 |
+
$wc_queued_js = $code . "\n" . $wc_queued_js;
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Validate URLs, make relative URLs absolute
|
63 |
+
*
|
64 |
+
* @access public
|
65 |
+
* @param string $url
|
66 |
+
* @return string
|
67 |
+
*/
|
68 |
+
public static function make_url( $url ) {
|
69 |
+
if (
|
70 |
+
// The first check incorrectly fails for URLs with special chars.
|
71 |
+
! filter_var( $url, FILTER_VALIDATE_URL ) &&
|
72 |
+
substr( $url, 0, 4 ) !== 'http'
|
73 |
+
) {
|
74 |
+
return get_site_url() . $url;
|
75 |
+
} else {
|
76 |
+
return $url;
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Product ID for Dynamic Ads on Facebook can be SKU or wc_post_id_123
|
82 |
+
* This function should be used to get retailer_id based on a WC_Product
|
83 |
+
* from WooCommerce
|
84 |
+
*
|
85 |
+
* @access public
|
86 |
+
* @param WC_Product $woo_product
|
87 |
+
* @return string
|
88 |
+
*/
|
89 |
+
public static function get_fb_retailer_id( $woo_product ) {
|
90 |
+
$woo_id = $woo_product->get_id();
|
91 |
+
|
92 |
+
// Call $woo_product->get_id() instead of ->id to account for Variable
|
93 |
+
// products, which have their own variant_ids.
|
94 |
+
return $woo_product->get_sku() ? $woo_product->get_sku() . '_' .
|
95 |
+
$woo_id : self::FB_RETAILER_ID_PREFIX . $woo_id;
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Return categories for products/pixel
|
100 |
+
*
|
101 |
+
* @access public
|
102 |
+
* @param String $id
|
103 |
+
* @return Array
|
104 |
+
*/
|
105 |
+
public static function get_product_categories( $wpid ) {
|
106 |
+
$category_path = wp_get_post_terms(
|
107 |
+
$wpid,
|
108 |
+
'product_cat',
|
109 |
+
array( 'fields' => 'all' )
|
110 |
+
);
|
111 |
+
$content_category = array_values(
|
112 |
+
array_map(
|
113 |
+
function( $item ) {
|
114 |
+
return $item->name;
|
115 |
+
},
|
116 |
+
$category_path
|
117 |
+
)
|
118 |
+
);
|
119 |
+
$content_category_slice = array_slice( $content_category, -1 );
|
120 |
+
$categories =
|
121 |
+
empty( $content_category ) ? '""' : implode( ', ', $content_category );
|
122 |
+
return array(
|
123 |
+
'name' => array_pop( $content_category_slice ),
|
124 |
+
'categories' => $categories,
|
125 |
+
);
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Returns content id to match on for Pixel fires.
|
130 |
+
*
|
131 |
+
* @access public
|
132 |
+
* @param WC_Product $woo_product
|
133 |
+
* @return array
|
134 |
+
*/
|
135 |
+
public static function get_fb_content_ids( $woo_product ) {
|
136 |
+
return array( self::get_fb_retailer_id( $woo_product ) );
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Clean up strings for FB Graph POSTing.
|
141 |
+
* This function should will:
|
142 |
+
* 1. Replace newlines chars/nbsp with a real space
|
143 |
+
* 2. strip_tags()
|
144 |
+
* 3. trim()
|
145 |
+
*
|
146 |
+
* @access public
|
147 |
+
* @param String string
|
148 |
+
* @return string
|
149 |
+
*/
|
150 |
+
public static function clean_string( $string ) {
|
151 |
+
$string = do_shortcode( $string );
|
152 |
+
$string = str_replace( array( '&%3B', '&' ), '&', $string );
|
153 |
+
$string = str_replace( array( "\r", ' ', "\t" ), ' ', $string );
|
154 |
+
$string = wp_strip_all_tags( $string, false ); // true == remove line breaks
|
155 |
+
return $string;
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Returns flat array of woo IDs for variable products, or
|
160 |
+
* an array with a single woo ID for simple products.
|
161 |
+
*
|
162 |
+
* @access public
|
163 |
+
* @param WC_Product $woo_product
|
164 |
+
* @return array
|
165 |
+
*/
|
166 |
+
public static function get_product_array( $woo_product ) {
|
167 |
+
$result = array();
|
168 |
+
if ( self::is_variable_type( $woo_product->get_type() ) ) {
|
169 |
+
foreach ( $woo_product->get_children() as $item_id ) {
|
170 |
+
array_push( $result, $item_id );
|
171 |
+
}
|
172 |
+
return $result;
|
173 |
+
} else {
|
174 |
+
return array( $woo_product->get_id() );
|
175 |
+
}
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Returns true if WooCommerce plugin found.
|
180 |
+
*
|
181 |
+
* @access public
|
182 |
+
* @return bool
|
183 |
+
*/
|
184 |
+
public static function isWoocommerceIntegration() {
|
185 |
+
return class_exists( 'WooCommerce' );
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* Returns integration dependent name.
|
190 |
+
*
|
191 |
+
* @access public
|
192 |
+
* @return string
|
193 |
+
*/
|
194 |
+
public static function getIntegrationName() {
|
195 |
+
if ( self::isWoocommerceIntegration() ) {
|
196 |
+
return 'WooCommerce';
|
197 |
+
} else {
|
198 |
+
return 'WordPress';
|
199 |
+
}
|
200 |
+
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* Returns user info for the current WP user.
|
204 |
+
*
|
205 |
+
* @access public
|
206 |
+
* @param boolean $use_pii
|
207 |
+
* @return array
|
208 |
+
*/
|
209 |
+
public static function get_user_info( $use_pii ) {
|
210 |
+
$current_user = wp_get_current_user();
|
211 |
+
if ( 0 === $current_user->ID || $use_pii === false ) {
|
212 |
+
// User not logged in or admin chose not to send PII.
|
213 |
+
return array();
|
214 |
+
} else {
|
215 |
+
return array_filter(
|
216 |
+
array(
|
217 |
+
// Keys documented in
|
218 |
+
// https://developers.facebook.com/docs/facebook-pixel/pixel-with-ads/
|
219 |
+
// /conversion-tracking#advanced_match
|
220 |
+
'em' => $current_user->user_email,
|
221 |
+
'fn' => $current_user->user_firstname,
|
222 |
+
'ln' => $current_user->user_lastname,
|
223 |
+
),
|
224 |
+
function ( $value ) {
|
225 |
+
return $value !== null && $value !== '';
|
226 |
+
}
|
227 |
+
);
|
228 |
+
}
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Utility function for development logging.
|
233 |
+
*/
|
234 |
+
public static function fblog(
|
235 |
+
$message,
|
236 |
+
$object = array(),
|
237 |
+
$error = false,
|
238 |
+
$ems = '' ) {
|
239 |
+
if ( $error ) {
|
240 |
+
$object['plugin_version'] = self::PLUGIN_VERSION;
|
241 |
+
$object['php_version'] = phpversion();
|
242 |
+
}
|
243 |
+
$message = json_encode(
|
244 |
+
array(
|
245 |
+
'message' => $message,
|
246 |
+
'object' => $object,
|
247 |
+
)
|
248 |
+
);
|
249 |
+
$ems = $ems ?: self::$ems;
|
250 |
+
if ( $ems ) {
|
251 |
+
self::$fbgraph->log(
|
252 |
+
$ems,
|
253 |
+
$message,
|
254 |
+
$error
|
255 |
+
);
|
256 |
+
} else {
|
257 |
+
error_log(
|
258 |
+
'external merchant setting is null, something wrong here: ' .
|
259 |
+
$message
|
260 |
+
);
|
261 |
+
}
|
262 |
+
}
|
263 |
+
|
264 |
+
/**
|
265 |
+
* Utility function for development Tip Events logging.
|
266 |
+
*/
|
267 |
+
public static function tip_events_log(
|
268 |
+
$tip_id,
|
269 |
+
$channel_id,
|
270 |
+
$event,
|
271 |
+
$ems = '' ) {
|
272 |
+
|
273 |
+
$ems = $ems ?: self::$ems;
|
274 |
+
if ( $ems ) {
|
275 |
+
self::$fbgraph->log_tip_event(
|
276 |
+
$tip_id,
|
277 |
+
$channel_id,
|
278 |
+
$event
|
279 |
+
);
|
280 |
+
} else {
|
281 |
+
error_log( 'external merchant setting is null' );
|
282 |
+
}
|
283 |
+
}
|
284 |
+
|
285 |
+
public static function is_variation_type( $type ) {
|
286 |
+
return $type == 'variation' || $type == 'subscription_variation';
|
287 |
+
}
|
288 |
+
|
289 |
+
public static function is_variable_type( $type ) {
|
290 |
+
return $type == 'variable' || $type == 'variable-subscription';
|
291 |
+
}
|
292 |
+
|
293 |
+
public static function check_woo_ajax_permissions( $action_text, $die ) {
|
294 |
+
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
295 |
+
self::log(
|
296 |
+
'Non manage_woocommerce user attempting to' . $action_text . '!',
|
297 |
+
array(),
|
298 |
+
true
|
299 |
+
);
|
300 |
+
if ( $die ) {
|
301 |
+
wp_die();
|
302 |
+
}
|
303 |
+
return false;
|
304 |
+
}
|
305 |
+
return true;
|
306 |
+
}
|
307 |
+
|
308 |
+
/**
|
309 |
+
* Returns true if id is a positive non-zero integer
|
310 |
+
*
|
311 |
+
* @access public
|
312 |
+
* @param string $pixel_id
|
313 |
+
* @return bool
|
314 |
+
*/
|
315 |
+
public static function is_valid_id( $pixel_id ) {
|
316 |
+
return isset( $pixel_id ) && is_numeric( $pixel_id ) && (int) $pixel_id > 0;
|
317 |
+
}
|
318 |
+
|
319 |
+
/**
|
320 |
+
* Helper function to query posts.
|
321 |
+
*/
|
322 |
+
public static function get_wp_posts(
|
323 |
+
$product_group_id = null,
|
324 |
+
$compare_condition = null,
|
325 |
+
$post_type = 'product' ) {
|
326 |
+
$args = array(
|
327 |
+
'fields' => 'ids',
|
328 |
+
'meta_query' => array(
|
329 |
+
( ( $product_group_id ) ?
|
330 |
+
array(
|
331 |
+
'key' => $product_group_id,
|
332 |
+
'compare' => $compare_condition,
|
333 |
+
) : array()
|
334 |
+
),
|
335 |
+
),
|
336 |
+
'post_status' => 'publish',
|
337 |
+
'post_type' => $post_type,
|
338 |
+
'posts_per_page' => -1,
|
339 |
+
);
|
340 |
+
return get_posts( $args );
|
341 |
+
}
|
342 |
+
|
343 |
+
/**
|
344 |
+
* Helper log function for debugging
|
345 |
+
*/
|
346 |
+
public static function log( $message ) {
|
347 |
+
if ( WP_DEBUG === true ) {
|
348 |
+
if ( is_array( $message ) || is_object( $message ) ) {
|
349 |
+
error_log( json_encode( $message ) );
|
350 |
+
} else {
|
351 |
+
error_log( sanitize_textarea_field( $message ) );
|
352 |
+
}
|
353 |
+
}
|
354 |
+
}
|
355 |
+
|
356 |
+
// Return store name with sanitized apostrophe
|
357 |
+
public static function get_store_name() {
|
358 |
+
if ( self::$store_name ) {
|
359 |
+
return self::$store_name;
|
360 |
+
}
|
361 |
+
$name = trim(
|
362 |
+
str_replace(
|
363 |
+
"'",
|
364 |
+
"\u{2019}",
|
365 |
+
html_entity_decode(
|
366 |
+
get_bloginfo( 'name' ),
|
367 |
+
ENT_QUOTES,
|
368 |
+
'UTF-8'
|
369 |
+
)
|
370 |
+
)
|
371 |
+
);
|
372 |
+
if ( $name ) {
|
373 |
+
self::$store_name = $name;
|
374 |
+
return $name;
|
375 |
+
}
|
376 |
+
// Fallback to site url
|
377 |
+
$url = get_site_url();
|
378 |
+
if ( $url ) {
|
379 |
+
self::$store_name = parse_url( $url, PHP_URL_HOST );
|
380 |
+
return self::$store_name;
|
381 |
+
}
|
382 |
+
// If site url doesn't exist, fall back to http host.
|
383 |
+
if ( $_SERVER['HTTP_HOST'] ) {
|
384 |
+
self::$store_name = $_SERVER['HTTP_HOST'];
|
385 |
+
return self::$store_name;
|
386 |
+
}
|
387 |
+
|
388 |
+
// If http host doesn't exist, fall back to local host name.
|
389 |
+
$url = gethostname();
|
390 |
+
self::$store_name = $url;
|
391 |
+
return ( self::$store_name ) ? ( self::$store_name ) : 'A Store Has No Name';
|
392 |
+
}
|
393 |
+
|
394 |
+
/*
|
395 |
+
* Change variant product field name from Woo taxonomy to FB name
|
396 |
+
*/
|
397 |
+
public static function sanitize_variant_name( $name ) {
|
398 |
+
$name = str_replace( array( 'attribute_', 'pa_' ), '', strtolower( $name ) );
|
399 |
+
|
400 |
+
// British spelling
|
401 |
+
if ( $name === self::FB_VARIANT_COLOUR ) {
|
402 |
+
$name = self::FB_VARIANT_COLOR;
|
403 |
+
}
|
404 |
+
|
405 |
+
switch ( $name ) {
|
406 |
+
case self::FB_VARIANT_SIZE:
|
407 |
+
case self::FB_VARIANT_COLOR:
|
408 |
+
case self::FB_VARIANT_GENDER:
|
409 |
+
case self::FB_VARIANT_PATTERN:
|
410 |
+
break;
|
411 |
+
default:
|
412 |
+
$name = 'custom_data:' . strtolower( $name );
|
413 |
+
break;
|
414 |
+
}
|
415 |
+
|
416 |
+
return $name;
|
417 |
+
}
|
418 |
+
|
419 |
+
public static function validateGender( $gender ) {
|
420 |
+
if ( $gender && ! isset( self::$validGenderArray[ $gender ] ) ) {
|
421 |
+
$first_char = strtolower( substr( $gender, 0, 1 ) );
|
422 |
+
// Men, Man, Boys
|
423 |
+
if ( $first_char === 'm' || $first_char === 'b' ) {
|
424 |
+
return 'male';
|
425 |
+
}
|
426 |
+
// Women, Woman, Female, Ladies
|
427 |
+
if ( $first_char === 'w' || $first_char === 'f' || $first_char === 'l' ) {
|
428 |
+
return 'female';
|
429 |
+
}
|
430 |
+
if ( $first_char === 'u' ) {
|
431 |
+
return 'unisex';
|
432 |
+
}
|
433 |
+
if ( strlen( $gender ) >= 3 ) {
|
434 |
+
$gender = strtolower( substr( $gender, 0, 3 ) );
|
435 |
+
if ( $gender === 'gir' || $gender === 'her' ) {
|
436 |
+
return 'female';
|
437 |
+
}
|
438 |
+
if ( $gender === 'him' || $gender === 'his' || $gender == 'guy' ) {
|
439 |
+
return 'male';
|
440 |
+
}
|
441 |
+
}
|
442 |
+
return null;
|
443 |
+
}
|
444 |
+
return $gender;
|
445 |
+
}
|
446 |
+
|
447 |
+
public static function get_fbid_post_meta( $wp_id, $fbid_type ) {
|
448 |
+
return get_post_meta( $wp_id, $fbid_type, true );
|
449 |
+
}
|
450 |
+
|
451 |
+
public static function is_all_caps( $value ) {
|
452 |
+
if ( $value === null || $value === '' ) {
|
453 |
+
return true;
|
454 |
+
}
|
455 |
+
if ( preg_match( '/[^\\p{Common}\\p{Latin}]/u', $value ) ) {
|
456 |
+
// Contains non-western characters
|
457 |
+
// So, it can't be all uppercase
|
458 |
+
return false;
|
459 |
+
}
|
460 |
+
$latin_string = preg_replace( '/[^\\p{Latin}]/u', '', $value );
|
461 |
+
if ( $latin_string === '' ) {
|
462 |
+
// Symbols only
|
463 |
+
return true;
|
464 |
+
}
|
465 |
+
return strtoupper( $latin_string ) === $latin_string;
|
466 |
+
}
|
467 |
+
|
468 |
+
public static function decode_json( $json_string, $assoc = false ) {
|
469 |
+
// Plugin requires 5.6.0 but for some user use 5.5.9 JSON_BIGINT_AS_STRING
|
470 |
+
// will cause 502 issue when redirect.
|
471 |
+
return version_compare( phpversion(), '5.6.0' ) >= 0
|
472 |
+
? json_decode( $json_string, $assoc, 512, JSON_BIGINT_AS_STRING )
|
473 |
+
: json_decode( $json_string, $assoc, 512 );
|
474 |
+
}
|
475 |
+
|
476 |
+
public static function set_test_fail_reason( $msg, $trace ) {
|
477 |
+
$reason_msg = get_transient( 'facebook_plugin_test_fail' );
|
478 |
+
if ( $reason_msg ) {
|
479 |
+
$msg = $reason_msg . PHP_EOL . $msg;
|
480 |
+
}
|
481 |
+
set_transient( 'facebook_plugin_test_fail', $msg );
|
482 |
+
set_transient( 'facebook_plugin_test_stack_trace', $trace );
|
483 |
+
}
|
484 |
+
|
485 |
+
/**
|
486 |
+
* Helper function to check time cap.
|
487 |
+
*/
|
488 |
+
public static function check_time_cap( $from, $date_cap ) {
|
489 |
+
if ( $from == null ) {
|
490 |
+
return true;
|
491 |
+
}
|
492 |
+
$now = new DateTime( current_time( 'mysql' ) );
|
493 |
+
$diff_in_day = $now->diff( new DateTime( $from ) )->format( '%a' );
|
494 |
+
return is_numeric( $diff_in_day ) && (int) $diff_in_day > $date_cap;
|
495 |
+
}
|
496 |
+
|
497 |
+
public static function get_cached_best_tip() {
|
498 |
+
$cached_best_tip = self::decode_json(
|
499 |
+
get_option( 'fb_info_banner_last_best_tip', '' )
|
500 |
+
);
|
501 |
+
return $cached_best_tip;
|
502 |
+
}
|
503 |
+
}
|
504 |
|
505 |
endif;
|
includes/fbwpml.php
CHANGED
@@ -8,130 +8,134 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
-
if (!defined('ABSPATH')) {
|
12 |
-
|
13 |
}
|
14 |
|
15 |
-
if (!class_exists('WC_Facebook_WPML_Injector')) :
|
16 |
|
17 |
-
class FB_WPML_Language_Status {
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
}
|
22 |
|
23 |
-
class WC_Facebook_WPML_Injector {
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
|
|
|
|
|
|
88 |
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
<p><label>
|
105 |
-
<input type="checkbox" id="icl_fb_woo_chk" name="'
|
106 |
-
'
|
107 |
</label></p>
|
108 |
';
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
}
|
|
|
136 |
|
137 |
endif;
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
12 |
+
exit;
|
13 |
}
|
14 |
|
15 |
+
if ( ! class_exists( 'WC_Facebook_WPML_Injector' ) ) :
|
16 |
|
17 |
+
class FB_WPML_Language_Status {
|
18 |
+
const VISIBLE = 1;
|
19 |
+
const HIDDEN = 2;
|
20 |
+
const NOT_SYNCED = 0;
|
21 |
+
}
|
22 |
|
23 |
+
class WC_Facebook_WPML_Injector {
|
24 |
+
public static $settings = null;
|
25 |
+
public static $default_lang = null;
|
26 |
+
const OPTION = 'fb_wmpl_language_visibility';
|
27 |
|
28 |
+
public function __construct() {
|
29 |
+
add_action( 'icl_menu_footer', array( $this, 'wpml_support' ) );
|
30 |
+
add_action( 'icl_ajx_custom_call', array( $this, 'wpml_ajax_support' ), 10, 2 );
|
31 |
+
self::$settings = get_option( self::OPTION );
|
32 |
+
self::$default_lang = apply_filters( 'wpml_default_language', null );
|
33 |
+
}
|
34 |
|
35 |
+
public static function should_hide( $wp_id ) {
|
36 |
+
$product_lang = apply_filters( 'wpml_post_language_details', null, $wp_id );
|
37 |
+
$settings = self::$settings;
|
38 |
+
if ( $product_lang && isset( $product_lang['language_code'] ) ) {
|
39 |
+
$product_lang = $product_lang['language_code'];
|
40 |
+
}
|
41 |
|
42 |
+
// Option doesn't exist : Backwards Compatibility
|
43 |
+
if ( ! $settings ) {
|
44 |
+
return ( $product_lang && self::$default_lang !== $product_lang );
|
45 |
+
}
|
46 |
+
// Hide products from non-active languages.
|
47 |
+
if ( ! isset( $settings[ $product_lang ] ) ) {
|
48 |
+
return true;
|
49 |
+
}
|
50 |
+
return $settings[ $product_lang ] !== FB_WPML_Language_Status::VISIBLE;
|
51 |
+
}
|
52 |
|
53 |
+
public function wpml_ajax_support( $call, $REQUEST ) {
|
54 |
+
global $sitepress;
|
55 |
+
if ( isset( $REQUEST['icl_ajx_action'] ) ) {
|
56 |
+
$call = $REQUEST['icl_ajx_action'];
|
57 |
+
}
|
58 |
+
if ( $call === 'icl_fb_woo' ) {
|
59 |
+
$active_languages = array_keys( $sitepress->get_active_languages() );
|
60 |
+
$settings = array();
|
61 |
+
foreach ( $active_languages as $lang ) {
|
62 |
+
$settings[ $lang ] = $REQUEST[ $lang ] === 'on' ?
|
63 |
+
FB_WPML_Language_Status::VISIBLE : FB_WPML_Language_Status::HIDDEN;
|
64 |
+
}
|
65 |
|
66 |
+
update_option( 'fb_wmpl_language_visibility', $settings, false );
|
67 |
+
self::$settings = $settings;
|
68 |
+
}
|
69 |
+
}
|
70 |
|
71 |
+
public function wpml_support() {
|
72 |
+
global $sitepress;
|
73 |
+
if ( strpos( $_GET['page'], 'languages.php' ) ) {
|
74 |
+
$active_languages = $sitepress->get_active_languages();
|
75 |
+
$settings = get_option( self::OPTION );
|
76 |
|
77 |
+
// Default setting is only show default lang.
|
78 |
+
if ( ! $settings ) {
|
79 |
+
$settings = array_fill_keys(
|
80 |
+
array_keys( $active_languages ),
|
81 |
+
FB_WPML_Language_Status::HIDDEN
|
82 |
+
);
|
83 |
+
$settings[ self::$default_lang ] = FB_WPML_Language_Status::VISIBLE;
|
84 |
+
}
|
85 |
+
$ajax_response = sprintf(
|
86 |
+
'Saved. You should now ' .
|
87 |
+
' <a href="%s&fb_force_resync=true">Re-Sync</a>' .
|
88 |
+
' your products with Facebook. ',
|
89 |
+
WOOCOMMERCE_FACEBOOK_PLUGIN_SETTINGS_URL
|
90 |
+
);
|
91 |
|
92 |
+
?><div id="lang-sec-fb" class="wpml-section wpml-section-languages">
|
93 |
+
<div class="wpml-section-header">
|
94 |
+
<h3><?php _e( 'Facebook Visibility', 'sitepress' ); ?></h3>
|
95 |
+
</div>
|
96 |
+
<div class="wpml-section-content">
|
97 |
+
WooCommerce Products with languages that are selected
|
98 |
+
here will be visible to customers who see your Facebook Shop.
|
99 |
|
100 |
+
<div class="wpml-section-content-inner">
|
101 |
+
<form id="icl_fb_woo" name="icl_fb_woo" action="">
|
102 |
+
<?php
|
103 |
+
foreach ( $settings as $language => $set ) {
|
104 |
+
$is_checked = $set === FB_WPML_Language_Status::VISIBLE ?
|
105 |
+
'checked' : '';
|
106 |
+
$str = '
|
107 |
<p><label>
|
108 |
+
<input type="checkbox" id="icl_fb_woo_chk" name="' . $language . '" ' . $is_checked . '>
|
109 |
+
' . $active_languages[ $language ]['native_name'] . '
|
110 |
</label></p>
|
111 |
';
|
112 |
+
echo $str;
|
113 |
+
}
|
114 |
+
?>
|
115 |
+
<p class="buttons-wrap">
|
116 |
+
<span class="icl_ajx_response_fb" id="icl_ajx_response_fb" hidden="true">
|
117 |
+
<?php echo $ajax_response; ?>
|
118 |
+
</span>
|
119 |
+
<input class="button button-primary"
|
120 |
+
name="save"
|
121 |
+
value="<?php _e( 'Save', 'sitepress' ); ?>"
|
122 |
+
type="submit" />
|
123 |
+
</p>
|
124 |
+
</form>
|
125 |
+
<script type="text/javascript">
|
126 |
+
addLoadEvent(function(){
|
127 |
+
jQuery('#icl_fb_woo').submit(iclSaveForm);
|
128 |
+
jQuery('#icl_fb_woo').submit(function(){
|
129 |
+
jQuery('#icl_ajx_response_fb').show();
|
130 |
+
});
|
131 |
+
});
|
132 |
+
</script>
|
133 |
+
</div>
|
134 |
+
</div>
|
135 |
+
</div>
|
136 |
+
<?php
|
137 |
+
}
|
138 |
+
}
|
139 |
+
}
|
140 |
|
141 |
endif;
|
includes/test/facebook-integration-test.php
CHANGED
@@ -14,562 +14,627 @@
|
|
14 |
* https://codex.wordpress.org/WP_DEBUG
|
15 |
*/
|
16 |
|
17 |
-
if (!defined('ABSPATH')) {
|
18 |
-
|
19 |
}
|
20 |
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
if (!class_exists('WC_Facebook_Integration_Test')) :
|
25 |
-
|
26 |
-
/**
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
class WC_Facebook_Integration_Test {
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
574 |
|
575 |
endif;
|
14 |
* https://codex.wordpress.org/WP_DEBUG
|
15 |
*/
|
16 |
|
17 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
18 |
+
exit;
|
19 |
}
|
20 |
|
21 |
+
require_once dirname( __DIR__ ) . '/fbutils.php';
|
22 |
+
require_once 'fbproductfeed-test.php';
|
23 |
+
|
24 |
+
if ( ! class_exists( 'WC_Facebook_Integration_Test' ) ) :
|
25 |
+
|
26 |
+
/**
|
27 |
+
* This tests the upload of test objects into Facebook using the plugin's
|
28 |
+
* infrastructure and checks to see if the product field have been correctly
|
29 |
+
* uploaded into FB.
|
30 |
+
*/
|
31 |
+
class WC_Facebook_Integration_Test {
|
32 |
+
|
33 |
+
const FB_PRODUCT_GROUP_ID = 'fb_product_group_id';
|
34 |
+
const FB_PRODUCT_ITEM_ID = 'fb_product_item_id';
|
35 |
+
const MAX_SLEEP_IN_SEC = 90;
|
36 |
+
const MAX_TIME = 'T23:59+00:00';
|
37 |
+
const MIN_TIME = 'T00:00+00:00';
|
38 |
+
/** Class Instance */
|
39 |
+
private static $instance;
|
40 |
+
|
41 |
+
public static $commerce = null; // Full WC_Facebookcommerce_Integration obj
|
42 |
+
public static $fbgraph = null;
|
43 |
+
public static $test_mode = false;
|
44 |
+
|
45 |
+
// simple products' id and variable products' parent_id
|
46 |
+
public static $wp_post_ids = array();
|
47 |
+
// FB product item retailer id.
|
48 |
+
public static $retailer_ids = array();
|
49 |
+
// product and product_variation post id for test
|
50 |
+
public $product_post_wpid = null;
|
51 |
+
public static $test_pass = 1;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Get the class instance
|
55 |
+
*/
|
56 |
+
public static function get_instance( $commerce ) {
|
57 |
+
return null === self::$instance
|
58 |
+
? ( self::$instance = new self( $commerce ) )
|
59 |
+
: self::$instance;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Constructor
|
64 |
+
*/
|
65 |
+
public function __construct( $commerce ) {
|
66 |
+
|
67 |
+
self::$commerce = $commerce;
|
68 |
+
|
69 |
+
add_action(
|
70 |
+
'wp_ajax_ajax_test_sync_products_using_feed',
|
71 |
+
array( $this, 'ajax_test_sync_products_using_feed' )
|
72 |
+
);
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Test visible products by uploading feed.
|
77 |
+
**/
|
78 |
+
function ajax_test_sync_products_using_feed() {
|
79 |
+
self::$test_mode = true;
|
80 |
+
// test ajax reset all products in db
|
81 |
+
$reset = self::$commerce->reset_all_products();
|
82 |
+
if ( $reset ) {
|
83 |
+
WC_Facebookcommerce_Utils::log( 'Test - Removing FBIDs from all products' );
|
84 |
+
$this->product_post_wpid = $this->create_data();
|
85 |
+
if ( empty( $this->product_post_wpid ) ) {
|
86 |
+
self::$test_pass = 0;
|
87 |
+
WC_Facebookcommerce_Utils::log(
|
88 |
+
'Test - Fail to create test product by inserting posts.'
|
89 |
+
);
|
90 |
+
WC_Facebookcommerce_Utils::set_test_fail_reason(
|
91 |
+
'Fail to create test products by inserting posts.',
|
92 |
+
( new Exception() )->getTraceAsString()
|
93 |
+
);
|
94 |
+
update_option( 'fb_test_pass', false );
|
95 |
+
wp_die();
|
96 |
+
return;
|
97 |
+
}
|
98 |
+
$this->set_product_wpid( $this->product_post_wpid );
|
99 |
+
$upload_success =
|
100 |
+
self::$commerce->ajax_sync_all_fb_products_using_feed( true );
|
101 |
+
if ( $upload_success ) {
|
102 |
+
// verification Step.
|
103 |
+
// Wait till FB finish backend creation to prevent race condition.
|
104 |
+
$time_start = microtime( true );
|
105 |
+
while ( ( microtime( true ) - $time_start ) < self::MAX_SLEEP_IN_SEC ) {
|
106 |
+
$complete = self::$commerce->fbproductfeed->is_upload_complete(
|
107 |
+
self::$commerce->settings
|
108 |
+
);
|
109 |
+
if ( $complete ) {
|
110 |
+
break;
|
111 |
+
} else {
|
112 |
+
$this->sleep_til_upload_complete( 10 );
|
113 |
+
}
|
114 |
+
}
|
115 |
+
$this->sleep_til_upload_complete( 60 );
|
116 |
+
$check_product_create = $this->check_product_create();
|
117 |
+
if ( ! $check_product_create ) {
|
118 |
+
self::$test_pass = 0;
|
119 |
+
} else {
|
120 |
+
WC_Facebookcommerce_Utils::log(
|
121 |
+
'Test - Products create successfully.'
|
122 |
+
);
|
123 |
+
}
|
124 |
+
// Clean up whatever has been created.
|
125 |
+
// Test on_product_delete API hook.
|
126 |
+
$clean_up = $this->clean_up();
|
127 |
+
if ( ! $clean_up ) {
|
128 |
+
self::$test_pass = 0;
|
129 |
+
WC_Facebookcommerce_Utils::log(
|
130 |
+
'Test - Fail to delete product from FB'
|
131 |
+
);
|
132 |
+
WC_Facebookcommerce_Utils::set_test_fail_reason(
|
133 |
+
'Fail to delete product from FB',
|
134 |
+
( new Exception() )->getTraceAsString()
|
135 |
+
);
|
136 |
+
} else {
|
137 |
+
WC_Facebookcommerce_Utils::log(
|
138 |
+
'Test - Delete product from FB successfully'
|
139 |
+
);
|
140 |
+
}
|
141 |
+
} else {
|
142 |
+
self::$test_pass = 0;
|
143 |
+
WC_Facebookcommerce_Utils::log(
|
144 |
+
'Test - Sync all products using feed, curl failed.'
|
145 |
+
);
|
146 |
+
WC_Facebookcommerce_Utils::set_test_fail_reason(
|
147 |
+
'Sync all products using feed, curl failed',
|
148 |
+
( new Exception() )->getTraceAsString()
|
149 |
+
);
|
150 |
+
}
|
151 |
+
} else {
|
152 |
+
self::$test_pass = 0;
|
153 |
+
WC_Facebookcommerce_Utils::log(
|
154 |
+
'Test - Fail to remove FBIDs from local DB'
|
155 |
+
);
|
156 |
+
WC_Facebookcommerce_Utils::set_test_fail_reason(
|
157 |
+
'Fail to remove FBIDs from local DB',
|
158 |
+
( new Exception() )->getTraceAsString()
|
159 |
+
);
|
160 |
+
}
|
161 |
+
update_option( 'fb_test_pass', self::$test_pass );
|
162 |
+
wp_die();
|
163 |
+
return;
|
164 |
+
}
|
165 |
+
|
166 |
+
function check_product_create() {
|
167 |
+
if ( count( self::$retailer_ids ) < 3 ) {
|
168 |
+
WC_Facebookcommerce_Utils::log( 'Test - Failed to create 3 product items.' );
|
169 |
+
WC_Facebookcommerce_Utils::set_test_fail_reason(
|
170 |
+
'Failed to create 3 product items.',
|
171 |
+
( new Exception() )->getTraceAsString()
|
172 |
+
);
|
173 |
+
return false;
|
174 |
+
}
|
175 |
+
|
176 |
+
if ( count( self::$retailer_ids ) > 3 ) {
|
177 |
+
WC_Facebookcommerce_Utils::log(
|
178 |
+
'Test - Failed to skip invisible products.'
|
179 |
+
);
|
180 |
+
WC_Facebookcommerce_Utils::set_test_fail_reason(
|
181 |
+
'Failed to skip invisible products.',
|
182 |
+
( new Exception() )->getTraceAsString()
|
183 |
+
);
|
184 |
+
return false;
|
185 |
+
}
|
186 |
+
|
187 |
+
// Check 3 products have been created.
|
188 |
+
for ( $i = 0; $i < 3; $i++ ) {
|
189 |
+
$product_type = $i == 0 ? 'Simple' : 'Variable';
|
190 |
+
$retailer_id = self::$retailer_ids[ $i ];
|
191 |
+
$item_fbid =
|
192 |
+
$this->check_fbid_api( self::FB_PRODUCT_ITEM_ID, $retailer_id );
|
193 |
+
$group_fbid =
|
194 |
+
$this->check_fbid_api( self::FB_PRODUCT_GROUP_ID, $retailer_id );
|
195 |
+
if ( ! $item_fbid || ! $group_fbid ) {
|
196 |
+
WC_Facebookcommerce_Utils::log(
|
197 |
+
'Test - ' . $product_type .
|
198 |
+
' product failed to create.'
|
199 |
+
);
|
200 |
+
WC_Facebookcommerce_Utils::set_test_fail_reason(
|
201 |
+
$product_type .
|
202 |
+
' product failed to create.',
|
203 |
+
( new Exception() )->getTraceAsString()
|
204 |
+
);
|
205 |
+
return false;
|
206 |
+
}
|
207 |
+
}
|
208 |
+
|
209 |
+
// Check product detailed as expected.
|
210 |
+
$data = array(
|
211 |
+
'name' => 'a simple product for test',
|
212 |
+
'price' => '20.00',
|
213 |
+
'description' => 'This is to test a simple product.',
|
214 |
+
'sale_price' => '10.00',
|
215 |
+
'sale_price_dates_from' =>
|
216 |
+
date_i18n( 'Y-m-d', strtotime( 'now' ) ) . self::MIN_TIME,
|
217 |
+
'sale_price_dates_to' =>
|
218 |
+
date_i18n( 'Y-m-d', strtotime( '+10 day' ) ) . self::MAX_TIME,
|
219 |
+
'visibility' => 'published',
|
220 |
+
);
|
221 |
+
$simple_product_result =
|
222 |
+
$this->check_product_info( self::$retailer_ids[0], false, $data );
|
223 |
+
if ( ! $simple_product_result ) {
|
224 |
+
WC_Facebookcommerce_Utils::log(
|
225 |
+
'Test - Simple product failed to match ' .
|
226 |
+
'product details.'
|
227 |
+
);
|
228 |
+
WC_Facebookcommerce_Utils::set_test_fail_reason(
|
229 |
+
'Simple product failed to'
|
230 |
+
. ' match product details.',
|
231 |
+
( new Exception() )->getTraceAsString()
|
232 |
+
);
|
233 |
+
return false;
|
234 |
+
}
|
235 |
+
|
236 |
+
$data = array(
|
237 |
+
'name' => 'a variable product for test',
|
238 |
+
'price' => '30.00',
|
239 |
+
'description' => 'This is to test a variable product. - Red',
|
240 |
+
'additional_variant_attributes' => array( 'value' => 'Red' ),
|
241 |
+
'visibility' => 'published',
|
242 |
+
);
|
243 |
+
$variable_product_result =
|
244 |
+
$this->check_product_info( self::$retailer_ids[1], true, $data );
|
245 |
+
if ( ! $variable_product_result ) {
|
246 |
+
WC_Facebookcommerce_Utils::log(
|
247 |
+
'Test - Variable product failed to match product details.'
|
248 |
+
);
|
249 |
+
WC_Facebookcommerce_Utils::set_test_fail_reason(
|
250 |
+
'Variable product failed to match product details.',
|
251 |
+
( new Exception() )->getTraceAsString()
|
252 |
+
);
|
253 |
+
return false;
|
254 |
+
}
|
255 |
+
return true;
|
256 |
+
}
|
257 |
+
|
258 |
+
function check_fbid_api( $fbid_type, $fb_retailer_id ) {
|
259 |
+
$product_fbid_result = self::$fbgraph->get_facebook_id(
|
260 |
+
self::$commerce->product_catalog_id,
|
261 |
+
$fb_retailer_id,
|
262 |
+
true
|
263 |
+
);
|
264 |
+
|
265 |
+
if ( is_wp_error( $product_fbid_result ) ) {
|
266 |
+
WC_Facebookcommerce_Utils::log(
|
267 |
+
'Test - ' . $product_fbid_result->get_error_message()
|
268 |
+
);
|
269 |
+
WC_Facebookcommerce_Utils::set_test_fail_reason(
|
270 |
+
'There was an issue connecting to the Facebook API: ' .
|
271 |
+
$product_fbid_result->get_error_message(),
|
272 |
+
( new Exception() )->getTraceAsString()
|
273 |
+
);
|
274 |
+
return false;
|
275 |
+
}
|
276 |
+
|
277 |
+
if ( $product_fbid_result && isset( $product_fbid_result['body'] ) ) {
|
278 |
+
$body = WC_Facebookcommerce_Utils::decode_json(
|
279 |
+
$product_fbid_result['body'],
|
280 |
+
true
|
281 |
+
);
|
282 |
+
if ( $body && isset( $body['id'] ) ) {
|
283 |
+
if ( $fbid_type == self::FB_PRODUCT_GROUP_ID ) {
|
284 |
+
$fb_id =
|
285 |
+
isset( $body['product_group'] )
|
286 |
+
? $body['product_group']['id']
|
287 |
+
: false;
|
288 |
+
} else {
|
289 |
+
$fb_id = $body['id'];
|
290 |
+
}
|
291 |
+
return $fb_id;
|
292 |
+
}
|
293 |
+
}
|
294 |
+
|
295 |
+
return false;
|
296 |
+
}
|
297 |
+
|
298 |
+
function check_product_info( $retailer_id, $has_variant, $data ) {
|
299 |
+
$prod_info_result = self::$fbgraph->check_product_info(
|
300 |
+
self::$commerce->product_catalog_id,
|
301 |
+
$retailer_id,
|
302 |
+
$has_variant
|
303 |
+
);
|
304 |
+
if ( is_wp_error( $prod_info_result ) ) {
|
305 |
+
WC_Facebookcommerce_Utils::log(
|
306 |
+
'Test - ' . $prod_info_result->get_error_message()
|
307 |
+
);
|
308 |
+
WC_Facebookcommerce_Utils::set_test_fail_reason(
|
309 |
+
'There was an issue connecting to the Facebook API: ' .
|
310 |
+
$prod_info_result->get_error_message(),
|
311 |
+
( new Exception() )->getTraceAsString()
|
312 |
+
);
|
313 |
+
return false;
|
314 |
+
}
|
315 |
+
|
316 |
+
$match = true;
|
317 |
+
if ( $prod_info_result && isset( $prod_info_result['body'] ) ) {
|
318 |
+
$body = WC_Facebookcommerce_Utils::decode_json(
|
319 |
+
$prod_info_result['body'],
|
320 |
+
true
|
321 |
+
);
|
322 |
+
if ( ! $body ) {
|
323 |
+
return false;
|
324 |
+
}
|
325 |
+
if ( $body['name'] != $data['name'] ) {
|
326 |
+
WC_Facebookcommerce_Utils::log(
|
327 |
+
'Test - ' . $retailer_id . " doesn\'t match name."
|
328 |
+
);
|
329 |
+
$match = false;
|
330 |
+
}
|
331 |
+
|
332 |
+
if ( $body['description'] != $data['description'] ) {
|
333 |
+
WC_Facebookcommerce_Utils::log(
|
334 |
+
'Test - ' . $retailer_id . " doesn\'t match description."
|
335 |
+
);
|
336 |
+
$match = false;
|
337 |
+
}
|
338 |
+
// Woo doesn't have API to return currency symbol.
|
339 |
+
// FB graph API only support to response with a currency symbol price.
|
340 |
+
// No php built-in function to support cast html number to symbol.
|
341 |
+
// Compare numeric price only.
|
342 |
+
$price = floatval( preg_replace( '/[^\d\.]+/', '', $body['price'] ) );
|
343 |
+
if ( $price != $data['price'] ) {
|
344 |
+
WC_Facebookcommerce_Utils::log(
|
345 |
+
'Test - ' . $retailer_id . " doesn\'t match price."
|
346 |
+
);
|
347 |
+
$match = false;
|
348 |
+
}
|
349 |
+
// Check sale price and dates.
|
350 |
+
if ( isset( $data['sale_price'] ) ) {
|
351 |
+
$sale_price = floatval(
|
352 |
+
preg_replace( '/[^\d\.]+/', '', $body['sale_price'] )
|
353 |
+
);
|
354 |
+
if ( $sale_price != $data['sale_price'] ) {
|
355 |
+
WC_Facebookcommerce_Utils::log(
|
356 |
+
'Test - ' . $retailer_id . " doesn\'t match sale price."
|
357 |
+
);
|
358 |
+
$match = false;
|
359 |
+
}
|
360 |
+
if ( $body['sale_price_start_date'] != $data['sale_price_dates_from'] ) {
|
361 |
+
WC_Facebookcommerce_Utils::log(
|
362 |
+
'Test - ' . $retailer_id . " doesn\'t match sale price start date"
|
363 |
+
);
|
364 |
+
$match = false;
|
365 |
+
}
|
366 |
+
if ( $body['sale_price_end_date'] != $data['sale_price_dates_to'] ) {
|
367 |
+
WC_Facebookcommerce_Utils::log(
|
368 |
+
'Test - ' . $retailer_id . " doesn\'t match sale price end date."
|
369 |
+
);
|
370 |
+
$match = false;
|
371 |
+
}
|
372 |
+
}
|
373 |
+
|
374 |
+
if ( $body['visibility'] != $data['visibility'] ) {
|
375 |
+
WC_Facebookcommerce_Utils::log(
|
376 |
+
'Test - ' . $retailer_id . " doesn\'t match visibility."
|
377 |
+
);
|
378 |
+
$match = false;
|
379 |
+
}
|
380 |
+
|
381 |
+
if ( $has_variant &&
|
382 |
+
( ! isset( $body['additional_variant_attributes'] ) ||
|
383 |
+
$body['additional_variant_attributes'][0]['value'] !=
|
384 |
+
$data['additional_variant_attributes']['value'] ) ) {
|
385 |
+
|
386 |
+
WC_Facebookcommerce_Utils::log(
|
387 |
+
'Test - ' . $retailer_id . " doesn\'t match variation."
|
388 |
+
);
|
389 |
+
$match = false;
|
390 |
+
}
|
391 |
+
}
|
392 |
+
return $match;
|
393 |
+
}
|
394 |
+
|
395 |
+
// Don't early return to prevent haunting product id.
|
396 |
+
function clean_up() {
|
397 |
+
$failure = false;
|
398 |
+
foreach ( self::$wp_post_ids as $post_id ) {
|
399 |
+
$delete_post_result = wp_delete_post( $post_id );
|
400 |
+
// return false or null if failed.
|
401 |
+
if ( ! $delete_post_result ) {
|
402 |
+
WC_Facebookcommerce_Utils::log( 'Test - Fail to delete post ' . $post_id );
|
403 |
+
WC_Facebookcommerce_Utils::set_test_fail_reason(
|
404 |
+
'Fail to delete post ' . $post_id,
|
405 |
+
( new Exception() )->getTraceAsString()
|
406 |
+
);
|
407 |
+
$failure = true;
|
408 |
+
}
|
409 |
+
}
|
410 |
+
self::$wp_post_ids = array();
|
411 |
+
|
412 |
+
$this->sleep_til_upload_complete( 60 );
|
413 |
+
foreach ( self::$retailer_ids as $retailer_id ) {
|
414 |
+
$item_fbid =
|
415 |
+
$this->check_fbid_api( self::FB_PRODUCT_ITEM_ID, $retailer_id );
|
416 |
+
$group_fbid =
|
417 |
+
$this->check_fbid_api( self::FB_PRODUCT_GROUP_ID, $retailer_id );
|
418 |
+
if ( $item_fbid || $group_fbid ) {
|
419 |
+
WC_Facebookcommerce_Utils::log(
|
420 |
+
'Test - Failed to delete product ' .
|
421 |
+
$retailer_id . ' via plugin deletion hook.'
|
422 |
+
);
|
423 |
+
WC_Facebookcommerce_Utils::set_test_fail_reason(
|
424 |
+
'Failed to delete product ' . $retailer_id .
|
425 |
+
' via plugin deletion hook.',
|
426 |
+
( new Exception() )->getTraceAsString()
|
427 |
+
);
|
428 |
+
$failure = true;
|
429 |
+
}
|
430 |
+
}
|
431 |
+
self::$retailer_ids = array();
|
432 |
+
|
433 |
+
return ! $failure;
|
434 |
+
}
|
435 |
+
|
436 |
+
function create_data() {
|
437 |
+
$prod_and_variant_wpid = array();
|
438 |
+
// Gets term object from Accessories in the database.
|
439 |
+
$term = get_term_by( 'name', 'Accessories', 'product_cat' );
|
440 |
+
// Accessories should be a default category.
|
441 |
+
// If not exist, set categories term first.
|
442 |
+
if ( ! $term ) {
|
443 |
+
$term = wp_insert_term(
|
444 |
+
'Accessories', // the term
|
445 |
+
'product_cat', // the taxonomy
|
446 |
+
array(
|
447 |
+
'slug' => 'accessories',
|
448 |
+
)
|
449 |
+
);
|
450 |
+
}
|
451 |
+
$data = array(
|
452 |
+
'post_content' => 'This is to test a simple product.',
|
453 |
+
'post_title' => 'a simple product for test',
|
454 |
+
'post_status' => 'publish',
|
455 |
+
'post_type' => 'product',
|
456 |
+
'term' => $term,
|
457 |
+
'price' => 20,
|
458 |
+
'sale_price' => 10,
|
459 |
+
'sale_price_dates_from' => strtotime( 'now' ),
|
460 |
+
'sale_price_dates_to' => strtotime( '+10 day' ),
|
461 |
+
);
|
462 |
+
$simple_product_result =
|
463 |
+
$this->create_test_simple_product( $data, $prod_and_variant_wpid );
|
464 |
+
|
465 |
+
if ( ! $simple_product_result ) {
|
466 |
+
return false;
|
467 |
+
}
|
468 |
+
|
469 |
+
// Test an invisible product - invisible products won't be synced by feed.
|
470 |
+
$data['visibility'] = false;
|
471 |
+
$simple_product_result =
|
472 |
+
$this->create_test_simple_product( $data, $prod_and_variant_wpid );
|
473 |
+
|
474 |
+
if ( ! $simple_product_result ) {
|
475 |
+
return false;
|
476 |
+
}
|
477 |
+
|
478 |
+
$data['post_content'] = 'This is to test a variable product.';
|
479 |
+
$data['post_title'] = 'a variable product for test';
|
480 |
+
$data['price'] = 30;
|
481 |
+
|
482 |
+
// Test variable products.
|
483 |
+
$variable_product_result =
|
484 |
+
$this->create_test_variable_product( $data, $prod_and_variant_wpid );
|
485 |
+
if ( ! $variable_product_result ) {
|
486 |
+
return false;
|
487 |
+
}
|
488 |
+
return $prod_and_variant_wpid;
|
489 |
+
}
|
490 |
+
|
491 |
+
function create_test_simple_product( $data, &$prod_and_variant_wpid ) {
|
492 |
+
$post_id = $this->fb_insert_post( $data, 'Simple' );
|
493 |
+
if ( ! $post_id ) {
|
494 |
+
return false;
|
495 |
+
}
|
496 |
+
array_push( $prod_and_variant_wpid, $post_id );
|
497 |
+
update_post_meta( $post_id, '_regular_price', $data['price'] );
|
498 |
+
update_post_meta( $post_id, '_sale_price', $data['sale_price'] );
|
499 |
+
update_post_meta( $post_id, '_sale_price_dates_from', $data['sale_price_dates_from'] );
|
500 |
+
update_post_meta( $post_id, '_sale_price_dates_to', $data['sale_price_dates_to'] );
|
501 |
+
|
502 |
+
wp_set_object_terms( $post_id, 'simple', 'product_type' );
|
503 |
+
// Invisible products won't be synced by feed.
|
504 |
+
if ( isset( $data['visibility'] ) ) {
|
505 |
+
$terms = array( 'exclude-from-catalog', 'exclude-from-search' );
|
506 |
+
wp_set_object_terms( $post_id, $terms, 'product_visibility' );
|
507 |
+
} else {
|
508 |
+
array_push( self::$wp_post_ids, $post_id );
|
509 |
+
array_push( self::$retailer_ids, 'wc_post_id_' . $post_id );
|
510 |
+
}
|
511 |
+
|
512 |
+
$product = wc_get_product( $post_id );
|
513 |
+
$product->set_stock_status( 'instock' );
|
514 |
+
wp_set_object_terms( $post_id, $data['term']->term_id, 'product_cat' );
|
515 |
+
return true;
|
516 |
+
}
|
517 |
+
|
518 |
+
function create_test_variable_product( $data, &$prod_and_variant_wpid ) {
|
519 |
+
$post_id = $this->fb_insert_post( $data, 'Variable' );
|
520 |
+
if ( ! $post_id ) {
|
521 |
+
return false;
|
522 |
+
}
|
523 |
+
|
524 |
+
wp_set_object_terms( $post_id, 'variable', 'product_type' );
|
525 |
+
array_push( $prod_and_variant_wpid, $post_id );
|
526 |
+
array_push( self::$wp_post_ids, $post_id );
|
527 |
+
// Gets term object from Accessories in the database.
|
528 |
+
$term = get_term_by( 'name', 'Accessories', 'product_cat' );
|
529 |
+
wp_set_object_terms( $post_id, $term->term_id, 'product_cat' );
|
530 |
+
|
531 |
+
// Set up attributes.
|
532 |
+
$avail_attribute_values = array(
|
533 |
+
'Red',
|
534 |
+
'Blue',
|
535 |
+
);
|
536 |
+
wp_set_object_terms( $post_id, $avail_attribute_values, 'pa_color' );
|
537 |
+
$thedata = array(
|
538 |
+
'pa_color' => array(
|
539 |
+
'name' => 'pa_color',
|
540 |
+
'value' => '',
|
541 |
+
'is_visible' => '1',
|
542 |
+
'is_variation' => '1',
|
543 |
+
'is_taxonomy' => '1',
|
544 |
+
),
|
545 |
+
);
|
546 |
+
update_post_meta( $post_id, '_product_attributes', $thedata );
|
547 |
+
|
548 |
+
// Insert variations.
|
549 |
+
$variation_data = array(
|
550 |
+
'post_content' => 'This is to test a variable product. - Red',
|
551 |
+
'post_status' => 'publish',
|
552 |
+
'post_type' => 'product_variation',
|
553 |
+
'post_parent' => $post_id,
|
554 |
+
'price' => 30,
|
555 |
+
);
|
556 |
+
$variation_red = $this->fb_insert_post( $variation_data, 'Variation' );
|
557 |
+
if ( ! $variation_red ) {
|
558 |
+
return;
|
559 |
+
}
|
560 |
+
|
561 |
+
$this->fb_update_variation_meta(
|
562 |
+
$prod_and_variant_wpid,
|
563 |
+
$variation_red,
|
564 |
+
'Red',
|
565 |
+
$variation_data
|
566 |
+
);
|
567 |
+
|
568 |
+
$variation_data['post_content'] = 'a variable product for test - Blue';
|
569 |
+
$variation_blue = $this->fb_insert_post( $variation_data, 'Variatoin' );
|
570 |
+
if ( ! $variation_blue ) {
|
571 |
+
return false;
|
572 |
+
}
|
573 |
+
$this->fb_update_variation_meta(
|
574 |
+
$prod_and_variant_wpid,
|
575 |
+
$variation_blue,
|
576 |
+
'Blue',
|
577 |
+
$variation_data
|
578 |
+
);
|
579 |
+
$product = wc_get_product( $variation_blue );
|
580 |
+
$product->set_stock_status( 'instock' );
|
581 |
+
wp_set_object_terms( $variation_blue, 'variation', 'product_type' );
|
582 |
+
return true;
|
583 |
+
}
|
584 |
+
|
585 |
+
function fb_update_variation_meta(
|
586 |
+
&$prod_and_variant_wpid,
|
587 |
+
$variation_id,
|
588 |
+
$value,
|
589 |
+
$data ) {
|
590 |
+
array_push( $prod_and_variant_wpid, $variation_id );
|
591 |
+
array_push( self::$retailer_ids, 'wc_post_id_' . $variation_id );
|
592 |
+
|
593 |
+
$attribute_term = get_term_by( 'name', $value, 'pa_color' );
|
594 |
+
|
595 |
+
update_post_meta( $variation_id, 'attribute_pa_color', $attribute_term->slug );
|
596 |
+
update_post_meta( $variation_id, '_price', $data['price'] );
|
597 |
+
update_post_meta( $variation_id, '_regular_price', $data['price'] );
|
598 |
+
wp_set_object_terms( $variation_id, 'variation', 'product_type' );
|
599 |
+
$product = wc_get_product( $variation_id );
|
600 |
+
$product->set_stock_status( 'instock' );
|
601 |
+
}
|
602 |
+
|
603 |
+
function fb_insert_post( $data, $p_type ) {
|
604 |
+
$postarr = array_intersect_key(
|
605 |
+
$data,
|
606 |
+
array_flip(
|
607 |
+
array(
|
608 |
+
'post_content',
|
609 |
+
'post_title',
|
610 |
+
'post_status',
|
611 |
+
'post_type',
|
612 |
+
'post_parent',
|
613 |
+
)
|
614 |
+
)
|
615 |
+
);
|
616 |
+
$post_id = wp_insert_post( $postarr );
|
617 |
+
if ( is_wp_error( $post_id ) ) {
|
618 |
+
WC_Facebookcommerce_Utils::log(
|
619 |
+
'Test - ' . $p_type .
|
620 |
+
' product wp_insert_post' . 'failed: ' . json_encode( $post_id )
|
621 |
+
);
|
622 |
+
return false;
|
623 |
+
} else {
|
624 |
+
return $post_id;
|
625 |
+
}
|
626 |
+
}
|
627 |
+
|
628 |
+
/**
|
629 |
+
* IMPORTANT! Wait for Ents creation and prevent race condition.
|
630 |
+
**/
|
631 |
+
function sleep_til_upload_complete( $sec ) {
|
632 |
+
sleep( $sec );
|
633 |
+
}
|
634 |
+
|
635 |
+
function set_product_wpid( $product_post_wpid ) {
|
636 |
+
WC_Facebook_Product_Feed_Test_Mock::$product_post_wpid = $product_post_wpid;
|
637 |
+
}
|
638 |
+
}
|
639 |
|
640 |
endif;
|
includes/test/fbproductfeed-test.php
CHANGED
@@ -8,33 +8,33 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
-
if (! defined('ABSPATH')) {
|
12 |
-
|
13 |
}
|
14 |
|
15 |
-
|
16 |
-
|
17 |
|
18 |
-
if (! class_exists('WC_Facebook_Product_Feed_Test')) :
|
19 |
-
/**
|
20 |
-
|
21 |
-
|
22 |
-
class WC_Facebook_Product_Feed_Test_Mock extends WC_Facebook_Product_Feed {
|
23 |
|
24 |
-
|
25 |
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
}
|
39 |
|
40 |
endif;
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
12 |
+
exit;
|
13 |
}
|
14 |
|
15 |
+
require_once dirname( __DIR__ ) . '/fbproductfeed.php';
|
16 |
+
require_once dirname( __DIR__ ) . '/fbutils.php';
|
17 |
|
18 |
+
if ( ! class_exists( 'WC_Facebook_Product_Feed_Test' ) ) :
|
19 |
+
/**
|
20 |
+
* Mock for Facebook feed class
|
21 |
+
*/
|
22 |
+
class WC_Facebook_Product_Feed_Test_Mock extends WC_Facebook_Product_Feed {
|
23 |
|
24 |
+
public static $product_post_wpid = null;
|
25 |
|
26 |
+
// Return test product post id.
|
27 |
+
// Don't mess up actual products.
|
28 |
+
public function get_product_wpid() {
|
29 |
+
return self::$product_post_wpid;
|
30 |
+
}
|
31 |
|
32 |
+
// Log progress in local log file for testing.
|
33 |
+
// Not to overwhelm DB log to track important signals.
|
34 |
+
public function log_feed_progress( $msg, $object = array() ) {
|
35 |
+
$msg = empty( $object ) ? $msg : $msg . json_encode( $object );
|
36 |
+
WC_Facebookcommerce_Utils::log( 'Test - ' . $msg );
|
37 |
+
}
|
38 |
+
}
|
39 |
|
40 |
endif;
|
readme.txt
CHANGED
@@ -2,9 +2,9 @@
|
|
2 |
Contributors: facebook, automattic, woothemes
|
3 |
Tags: facebook, shop, catalog, advertise, pixel, product
|
4 |
Requires at least: 4.4
|
5 |
-
Tested up to:
|
6 |
-
Stable tag: 1.9.
|
7 |
-
Requires PHP: 5.6
|
8 |
MySQL: 5.6 or greater
|
9 |
License: GPLv2 or later
|
10 |
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
@@ -38,9 +38,15 @@ When opening a bug on GitHub, please give us as many details as possible.
|
|
38 |
* Current version of Facebook-for-WooCommerce, WooCommerce, Wordpress, PHP
|
39 |
|
40 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
41 |
= 1.9.14 - 2019-06-20 =
|
42 |
* Revisit CSRF security issue
|
43 |
* Remove rest controller which is not used
|
|
|
44 |
|
45 |
= 1.9.13 - 2019-06-18 =
|
46 |
* Fix security issue
|
@@ -58,7 +64,3 @@ When opening a bug on GitHub, please give us as many details as possible.
|
|
58 |
https://wordpress.org/plugins/facebook-for-woocommerce/#developers
|
59 |
* removing debug flags notice under facebook-for-woocommerce.php so that
|
60 |
developers will be able to debug with debug logs
|
61 |
-
|
62 |
-
= 1.9.10 - 2019-02-11 =
|
63 |
-
* Add facebook support link, this will help merchants to reach out to facebook customer service.
|
64 |
-
* Make plugin wordpress compatible by removing woocommerce updater and removing woo_include
|
2 |
Contributors: facebook, automattic, woothemes
|
3 |
Tags: facebook, shop, catalog, advertise, pixel, product
|
4 |
Requires at least: 4.4
|
5 |
+
Tested up to: 5.2.2
|
6 |
+
Stable tag: 1.9.15
|
7 |
+
Requires PHP: 5.6 or greater
|
8 |
MySQL: 5.6 or greater
|
9 |
License: GPLv2 or later
|
10 |
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
38 |
* Current version of Facebook-for-WooCommerce, WooCommerce, Wordpress, PHP
|
39 |
|
40 |
== Changelog ==
|
41 |
+
= 1.9.15 - 2019-06-27 =
|
42 |
+
* CSRF handling for Ajax calls like ajax_woo_infobanner_post_click, ajax_woo_infobanner_post_xout, ajax_fb_toggle_visibility
|
43 |
+
* use phpcs to adhere to WP coding standards
|
44 |
+
* Minor UI changes on the iFrame
|
45 |
+
|
46 |
= 1.9.14 - 2019-06-20 =
|
47 |
* Revisit CSRF security issue
|
48 |
* Remove rest controller which is not used
|
49 |
+
* Tested installation in wordpress 5.2.2, WooCommerce 3.64, php 5.6/7.3 with browser Chrome v75/Safari v12.1/Firefox v67.
|
50 |
|
51 |
= 1.9.13 - 2019-06-18 =
|
52 |
* Fix security issue
|
64 |
https://wordpress.org/plugins/facebook-for-woocommerce/#developers
|
65 |
* removing debug flags notice under facebook-for-woocommerce.php so that
|
66 |
developers will be able to debug with debug logs
|
|
|
|
|
|
|
|