Version Description
Download this release
Release Info
Developer | SkyVerge |
Plugin | Facebook for WooCommerce |
Version | 1.11.0 |
Comparing to | |
See all releases |
Code changes from version 1.10.2 to 1.11.0
- assets/css/admin/facebook-for-woocommerce-products-admin.css +6 -0
- assets/js/admin/facebook-for-woocommerce-products-admin.js +41 -12
- assets/js/admin/facebook-for-woocommerce-products-admin.min.js +1 -1
- assets/js/facebook-for-woocommerce-modal.js +35 -29
- assets/js/facebook-for-woocommerce-modal.min.js +1 -1
- assets/js/facebook-settings.js +160 -33
- assets/js/facebook-settings.min.js +1 -1
- changelog.txt +11 -0
- class-wc-facebookcommerce.php +67 -2
- facebook-commerce-events-tracker.php +86 -60
- facebook-commerce-pixel-event.php +26 -2
- facebook-commerce.php +323 -85
- facebook-for-woocommerce.php +2 -3
- i18n/languages/facebook-for-woocommerce.pot +174 -145
- includes/AJAX.php +12 -7
- includes/Admin.php +125 -6
- includes/Lifecycle.php +17 -0
- includes/Products/Feed.php +251 -0
- includes/fbproduct.php +139 -123
- includes/fbproductfeed.php +468 -76
- readme.txt +12 -1
assets/css/admin/facebook-for-woocommerce-products-admin.css
CHANGED
@@ -35,3 +35,9 @@
|
|
35 |
.woocommerce_variation .fb-product-image-source-field .wc-radios {
|
36 |
clear: both;
|
37 |
}
|
|
|
|
|
|
|
|
|
|
|
|
35 |
.woocommerce_variation .fb-product-image-source-field .wc-radios {
|
36 |
clear: both;
|
37 |
}
|
38 |
+
|
39 |
+
/* adjusts widths of the products table, same as WooCommerce categories and tags */
|
40 |
+
#facebook_sync_enabled,
|
41 |
+
#facebook_catalog_visibility {
|
42 |
+
width: 11% !important;
|
43 |
+
}
|
assets/js/admin/facebook-for-woocommerce-products-admin.js
CHANGED
@@ -69,7 +69,8 @@ jQuery( document ).ready( function( $ ) {
|
|
69 |
let $submitButton = $( this ),
|
70 |
chosenBulkAction = $submitButton.prev( 'select' ).val();
|
71 |
|
72 |
-
|
|
|
73 |
|
74 |
let products = [];
|
75 |
|
@@ -195,26 +196,34 @@ jQuery( document ).ready( function( $ ) {
|
|
195 |
return true;
|
196 |
}
|
197 |
|
198 |
-
let $submitButton
|
199 |
$visibleCheckbox = $( 'input[name="fb_visibility"]' ),
|
200 |
-
productID
|
201 |
-
productCat
|
202 |
-
|
203 |
-
|
|
|
|
|
204 |
|
205 |
$( '#taxonomy-product_cat input[name="tax_input[product_cat][]"]:checked' ).each( function() {
|
206 |
productCat.push( parseInt( $( this ).val(), 10 ) );
|
207 |
} );
|
208 |
|
|
|
|
|
|
|
|
|
|
|
209 |
if ( productID > 0 ) {
|
210 |
|
211 |
$.post( facebook_for_woocommerce_products_admin.ajax_url, {
|
212 |
-
action:
|
213 |
-
security:
|
214 |
-
sync_enabled:
|
215 |
-
|
216 |
-
|
217 |
-
|
|
|
218 |
}, function( response ) {
|
219 |
|
220 |
// open modal if visibility checkbox is checked or if there are conflicting terms set for sync exclusion
|
@@ -261,4 +270,24 @@ jQuery( document ).ready( function( $ ) {
|
|
261 |
} );
|
262 |
}
|
263 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
264 |
} );
|
69 |
let $submitButton = $( this ),
|
70 |
chosenBulkAction = $submitButton.prev( 'select' ).val();
|
71 |
|
72 |
+
// TODO: also check `'facebook_exclude' === chosenBulkAction` once Catalog Visibility settings are available again {WV 2020-04-20}
|
73 |
+
if ( 'facebook_include' === chosenBulkAction ) {
|
74 |
|
75 |
let products = [];
|
76 |
|
196 |
return true;
|
197 |
}
|
198 |
|
199 |
+
let $submitButton = $( this ),
|
200 |
$visibleCheckbox = $( 'input[name="fb_visibility"]' ),
|
201 |
+
productID = parseInt( $( 'input#post_ID' ).val(), 10 ),
|
202 |
+
productCat = [],
|
203 |
+
// this query will get tags when not using checkboxes
|
204 |
+
productTag = $( 'textarea[name="tax_input[product_tag]"]' ).length ? $( 'textarea[name="tax_input[product_tag]"]' ).val().split( ',' ) : [],
|
205 |
+
syncEnabled = $( 'input#fb_sync_enabled' ).prop( 'checked' ),
|
206 |
+
varSyncEnabled = $( '.js-variable-fb-sync-toggle' ).is( ':checked' );
|
207 |
|
208 |
$( '#taxonomy-product_cat input[name="tax_input[product_cat][]"]:checked' ).each( function() {
|
209 |
productCat.push( parseInt( $( this ).val(), 10 ) );
|
210 |
} );
|
211 |
|
212 |
+
// this query will get tags when using checkboxes
|
213 |
+
$( '#taxonomy-product_tag input[name="tax_input[product_tag][]"]:checked' ).each( function() {
|
214 |
+
productTag.push( parseInt( $( this ).val(), 10 ) );
|
215 |
+
} );
|
216 |
+
|
217 |
if ( productID > 0 ) {
|
218 |
|
219 |
$.post( facebook_for_woocommerce_products_admin.ajax_url, {
|
220 |
+
action: 'facebook_for_woocommerce_set_product_sync_prompt',
|
221 |
+
security: facebook_for_woocommerce_products_admin.set_product_sync_prompt_nonce,
|
222 |
+
sync_enabled: syncEnabled ? 'enabled' : 'disabled',
|
223 |
+
var_sync_enabled: varSyncEnabled ? 'enabled' : 'disabled',
|
224 |
+
product: productID,
|
225 |
+
categories: productCat,
|
226 |
+
tags: productTag
|
227 |
}, function( response ) {
|
228 |
|
229 |
// open modal if visibility checkbox is checked or if there are conflicting terms set for sync exclusion
|
270 |
} );
|
271 |
}
|
272 |
|
273 |
+
|
274 |
+
// product list screen or individual product edit screen
|
275 |
+
if ( 'product' === pagenow || 'edit-product' === pagenow ) {
|
276 |
+
|
277 |
+
// handle the "Do not show this notice again" button
|
278 |
+
$( '.js-wc-plugin-framework-admin-notice' ).on( 'click', '.notice-dismiss-permanently', function() {
|
279 |
+
|
280 |
+
var $notice = $( this ).closest( '.js-wc-plugin-framework-admin-notice' );
|
281 |
+
|
282 |
+
$.get( ajaxurl, {
|
283 |
+
action: 'wc_plugin_framework_' + $( $notice ).data( 'plugin-id' ) + '_dismiss_notice',
|
284 |
+
messageid: $( $notice ).data( 'message-id' ),
|
285 |
+
permanently: true
|
286 |
+
} );
|
287 |
+
|
288 |
+
$notice.fadeOut();
|
289 |
+
} );
|
290 |
+
}
|
291 |
+
|
292 |
+
|
293 |
} );
|
assets/js/admin/facebook-for-woocommerce-products-admin.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
"use strict";jQuery(document).ready(function(
|
1 |
+
"use strict";jQuery(document).ready(function(s){var o=window.pagenow.length?window.pagenow:"";window.typenow.length&&window.typenow;if("edit-product"===o){var e=s(".facebook-for-woocommerce-product-visibility-toggle");e.tipTip({attribute:"title",edgeOffset:5,fadeIn:50,fadeOut:50,delay:200}),e.on("click",function(o){o.preventDefault();var e=s(this).data("action"),c="show"===e?"yes":"no",t=parseInt(s(this).data("product-id"),10);"show"===e?s(this).hide().next("button").show():"hide"===e&&s(this).hide().prev("button").show(),s.post(facebook_for_woocommerce_products_admin.ajax_url,{action:"facebook_for_woocommerce_set_products_visibility",security:facebook_for_woocommerce_products_admin.set_product_visibility_nonce,products:[{product_id:t,visibility:c}]})});var i=!1;s("input#doaction, input#doaction2").on("click",function(o){if(i)return!0;o.preventDefault();var e=s(this),c=e.prev("select").val();if("facebook_include"===c){var t=[];s.each(s('input[name="post[]"]:checked'),function(){t.push(parseInt(s(this).val(),10))}),s.post(facebook_for_woocommerce_products_admin.ajax_url,{action:"facebook_for_woocommerce_set_product_sync_bulk_action_prompt",security:facebook_for_woocommerce_products_admin.set_product_sync_bulk_action_prompt_nonce,toggle:c,products:t},function(o){o&&!o.success?(s("#wc-backbone-modal-dialog .modal-close").trigger("click"),new s.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:o.data}),s(".facebook-for-woocommerce-toggle-product-visibility").on("click",function(o){blockModal(),s(this).hasClass("hide-products")&&s.each(t,function(){var o=s("#post-"+this).find("td.facebook_catalog_visibility button.facebook-for-woocommerce-product-visibility-hide");o.is(":visible")&&o.trigger("click")}),i=!0,e.trigger("click")})):(i=!0,e.trigger("click"))})}else i=!0,e.trigger("click")})}if("product"===o){var c=function(o,e){e.find(".enable-if-sync-enabled").prop("disabled",!o)},t=s("#fb_sync_enabled"),a=t.closest(".woocommerce_options_panel");t.on("click",function(){c(s(this).prop("checked"),a)}),c(t.prop("checked"),a),s(".woocommerce_variations").on("change",".js-variable-fb-sync-toggle",function(){c(s(this).prop("checked"),s(this).closest(".wc-metabox-content"))}),s("#woocommerce-product-data").on("change",".js-fb-product-image-source",function(){var o=s(this).closest(".woocommerce_options_panel, .wc-metabox-content"),e=s(this).val();o.find(".product-image-source-field").closest(".form-field").hide(),o.find(".show-if-product-image-source-"+e).closest(".form-field").show()}),s(".js-fb-product-image-source:checked").trigger("change"),s("#woocommerce-product-data").on("woocommerce_variations_loaded",function(){s(".js-variable-fb-sync-toggle").trigger("change"),s(".js-fb-product-image-source:checked").trigger("change")});var d=!1;s('form#post input[type="submit"]').on("click",function(o){if(d)return!0;o.preventDefault();var e=s(this),c=s('input[name="fb_visibility"]'),t=parseInt(s("input#post_ID").val(),10),i=[],a=s('textarea[name="tax_input[product_tag]"]').length?s('textarea[name="tax_input[product_tag]"]').val().split(","):[],n=s("input#fb_sync_enabled").prop("checked"),r=s(".js-variable-fb-sync-toggle").is(":checked");s('#taxonomy-product_cat input[name="tax_input[product_cat][]"]:checked').each(function(){i.push(parseInt(s(this).val(),10))}),s('#taxonomy-product_tag input[name="tax_input[product_tag][]"]:checked').each(function(){a.push(parseInt(s(this).val(),10))}),0<t?s.post(facebook_for_woocommerce_products_admin.ajax_url,{action:"facebook_for_woocommerce_set_product_sync_prompt",security:facebook_for_woocommerce_products_admin.set_product_sync_prompt_nonce,sync_enabled:n?"enabled":"disabled",var_sync_enabled:r?"enabled":"disabled",product:t,categories:i,tags:a},function(o){o&&!o.success&&(n||!n&&c.length&&c.is(":checked"))?(s("#wc-backbone-modal-dialog .modal-close").trigger("click"),new s.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:o.data}),s(".facebook-for-woocommerce-toggle-product-visibility").on("click",function(o){blockModal(),s(this).hasClass("hide-products")&&c.prop("checked",!1),d=!0,e.trigger("click")})):(d=!0,e.trigger("click"))}):(d=!0,e.trigger("click"))})}"product"!==o&&"edit-product"!==o||s(".js-wc-plugin-framework-admin-notice").on("click",".notice-dismiss-permanently",function(){var o=s(this).closest(".js-wc-plugin-framework-admin-notice");s.get(ajaxurl,{action:"wc_plugin_framework_"+s(o).data("plugin-id")+"_dismiss_notice",messageid:s(o).data("message-id"),permanently:!0}),o.fadeOut()})});
|
assets/js/facebook-for-woocommerce-modal.js
CHANGED
@@ -7,38 +7,44 @@
|
|
7 |
* @package FacebookCommerce
|
8 |
*/
|
9 |
|
10 |
-
$
|
11 |
|
12 |
-
/**
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
function
|
18 |
-
let $modal = $( '.wc-backbone-modal-content' );
|
19 |
-
return $modal.is( '.processing') || $modal.parents( '.processing' ).length;
|
20 |
-
}
|
21 |
|
|
|
22 |
|
23 |
-
|
24 |
-
* Blocks the current modal.
|
25 |
-
*/
|
26 |
-
function blockModal() {
|
27 |
-
if ( ! isModalBlocked() ) {
|
28 |
-
return $( '.wc-backbone-modal-content' ).addClass( 'processing' ).block( {
|
29 |
-
message: null,
|
30 |
-
overlayCSS: {
|
31 |
-
background: '#fff',
|
32 |
-
opacity: 0.6
|
33 |
-
}
|
34 |
-
} );
|
35 |
}
|
36 |
-
}
|
37 |
|
38 |
|
39 |
-
/**
|
40 |
-
|
41 |
-
|
42 |
-
function
|
43 |
-
|
44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
* @package FacebookCommerce
|
8 |
*/
|
9 |
|
10 |
+
(function( $ ) {
|
11 |
|
12 |
+
/**
|
13 |
+
* Determines if the current modal is blocked.
|
14 |
+
*
|
15 |
+
* @returns {boolean}
|
16 |
+
*/
|
17 |
+
window.isModalBlocked = function() {
|
|
|
|
|
|
|
18 |
|
19 |
+
let $modal = $( '.wc-backbone-modal-content' );
|
20 |
|
21 |
+
return $modal.is( '.processing' ) || $modal.parents( '.processing' ).length;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
}
|
|
|
23 |
|
24 |
|
25 |
+
/**
|
26 |
+
* Blocks the current modal.
|
27 |
+
*/
|
28 |
+
window.blockModal = function() {
|
29 |
+
|
30 |
+
if ( ! isModalBlocked() ) {
|
31 |
+
return $( '.wc-backbone-modal-content' ).addClass( 'processing' ).block( {
|
32 |
+
message: null,
|
33 |
+
overlayCSS: {
|
34 |
+
background: '#fff',
|
35 |
+
opacity: 0.6
|
36 |
+
}
|
37 |
+
} );
|
38 |
+
}
|
39 |
+
}
|
40 |
+
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Unblocks the current modal.
|
44 |
+
*/
|
45 |
+
window.unBlockModal = function() {
|
46 |
+
|
47 |
+
$( '.wc-backbone-modal-content' ).removeClass( 'processing' ).unblock();
|
48 |
+
}
|
49 |
+
|
50 |
+
})( jQuery );
|
assets/js/facebook-for-woocommerce-modal.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
"use strict"
|
1 |
+
"use strict";!function(n){window.isModalBlocked=function(){var o=n(".wc-backbone-modal-content");return o.is(".processing")||o.parents(".processing").length},window.blockModal=function(){if(!isModalBlocked())return n(".wc-backbone-modal-content").addClass("processing").block({message:null,overlayCSS:{background:"#fff",opacity:.6}})},window.unBlockModal=function(){n(".wc-backbone-modal-content").removeClass("processing").unblock()}}(jQuery);
|
assets/js/facebook-settings.js
CHANGED
@@ -166,8 +166,10 @@ function sync_confirm(verbose = null) {
|
|
166 |
}
|
167 |
}
|
168 |
|
169 |
-
|
170 |
-
|
|
|
|
|
171 |
if (window.location.href.includes( "fb_force_resync" )) {
|
172 |
window.onload = function() { sync_confirm( "fb_force_resync" ); };
|
173 |
} else if (window.location.href.includes( "fb_test_product_sync" )) {
|
@@ -175,6 +177,7 @@ if (window.location.href.includes( "fb_force_resync" )) {
|
|
175 |
window.is_test = true;
|
176 |
window.onload = function() { sync_confirm( "fb_test_product_sync" ); };
|
177 |
}
|
|
|
178 |
|
179 |
|
180 |
/**
|
@@ -241,7 +244,7 @@ function sync_all_products($using_feed = false, $is_test = false) {
|
|
241 |
message = facebook_for_woocommerce_settings_sync.i18n.general_error;
|
242 |
}
|
243 |
|
244 |
-
|
245 |
}
|
246 |
} );
|
247 |
}
|
@@ -266,8 +269,8 @@ function delete_all_settings(callback = null, failcallback = null) {
|
|
266 |
|
267 |
jQuery( '.messenger-field' ).each( function () {
|
268 |
|
269 |
-
if ( typeof
|
270 |
-
|
271 |
}
|
272 |
} );
|
273 |
|
@@ -322,11 +325,11 @@ function save_settings(callback = null, failcallback = null, localsettings = nul
|
|
322 |
function save_settings_for_plugin(callback, failcallback) {
|
323 |
save_settings(
|
324 |
function(response){
|
325 |
-
if (response && response.
|
326 |
console.log( response );
|
327 |
callback( response );
|
328 |
} else {
|
329 |
-
console.log( 'Fail response on
|
330 |
failcallback( response );
|
331 |
}
|
332 |
},
|
@@ -348,7 +351,7 @@ function save_settings_and_sync(message) {
|
|
348 |
window.sendToFacebook( 'ack set pixel', message.params );
|
349 |
window.sendToFacebook( 'ack set page access token', message.params );
|
350 |
window.sendToFacebook( 'ack set merchant settings', message.params );
|
351 |
-
sync_all_products( true );
|
352 |
} else {
|
353 |
window.sendToFacebook( 'fail save_settings', response );
|
354 |
console.log( 'Fail response on save_settings_and_sync' );
|
@@ -460,7 +463,7 @@ function setPixel(message) {
|
|
460 |
// We need this to support changing the pixel id after setup.
|
461 |
save_settings(
|
462 |
function(response){
|
463 |
-
if (response && response.
|
464 |
window.sendToFacebook( 'ack set pixel', message.params );
|
465 |
} //may not get settings_saved if we try to save pixel before an API key
|
466 |
},
|
@@ -472,8 +475,17 @@ function setPixel(message) {
|
|
472 |
);
|
473 |
}
|
474 |
|
475 |
-
function genFeed(message) {
|
476 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
477 |
}
|
478 |
|
479 |
function setAccessTokenAndPageId(message) {
|
@@ -549,12 +561,51 @@ function setMsgerChatSetup( data ) {
|
|
549 |
}
|
550 |
}
|
551 |
|
552 |
-
function
|
553 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
554 |
const origin = event.origin || event.originalEvent.origin;
|
555 |
-
|
556 |
-
|
557 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
558 |
}
|
559 |
|
560 |
switch (event.data.type) {
|
@@ -580,28 +631,74 @@ function iFrameListener(event) {
|
|
580 |
case 'get dia settings':
|
581 |
window.sendToFacebook( 'dia settings', window.diaConfig );
|
582 |
break;
|
583 |
-
case 'set merchant settings':
|
584 |
-
setMerchantSettings( event.data );
|
585 |
-
break;
|
586 |
case 'set catalog':
|
587 |
setCatalog( event.data );
|
588 |
break;
|
|
|
|
|
|
|
589 |
case 'set pixel':
|
590 |
setPixel( event.data );
|
591 |
break;
|
592 |
case 'gen feed':
|
593 |
-
genFeed();
|
594 |
break;
|
595 |
|
|
|
596 |
case 'set page access token':
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
605 |
break;
|
606 |
|
607 |
case 'set msger chat':
|
@@ -611,7 +708,7 @@ function iFrameListener(event) {
|
|
611 |
window.sendToFacebook( 'ack msger chat', event.data );
|
612 |
},
|
613 |
function(response) {
|
614 |
-
window.sendToFacebook( 'fail
|
615 |
}
|
616 |
);
|
617 |
break;
|
@@ -620,6 +717,31 @@ function iFrameListener(event) {
|
|
620 |
|
621 |
addAnEventListener( window,'message',iFrameListener );
|
622 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
623 |
function urlFromSameDomain(url1, url2) {
|
624 |
if ( ! url1.startsWith( 'http' ) || ! url2.startsWith( 'http' )) {
|
625 |
return false;
|
@@ -804,7 +926,7 @@ function check_feed_upload_queue(check_num) {
|
|
804 |
// enable Manage connection and Sync products buttons when sync stops
|
805 |
jQuery( '#woocommerce-facebook-settings-manage-connection, #woocommerce-facebook-settings-sync-products' ).css( 'pointer-events', 'auto' );
|
806 |
|
807 |
-
|
808 |
|
809 |
window.feed_upload = false;
|
810 |
if (window.is_test) {
|
@@ -957,11 +1079,15 @@ function syncShortDescription() {
|
|
957 |
);
|
958 |
}
|
959 |
|
960 |
-
|
961 |
jQuery( document ).ready( function( $ ) {
|
962 |
|
963 |
-
//
|
964 |
-
|
|
|
|
|
|
|
|
|
|
|
965 |
|
966 |
$( '#woocommerce-facebook-settings-sync-products' ).click( function( event ) {
|
967 |
|
@@ -969,4 +1095,5 @@ jQuery( document ).ready( function( $ ) {
|
|
969 |
|
970 |
sync_confirm();
|
971 |
} );
|
|
|
972 |
} );
|
166 |
}
|
167 |
}
|
168 |
|
169 |
+
/*
|
170 |
+
* Launch the confirm dialog immediately if the param is in the URL.
|
171 |
+
* TODO: restore after migration to FBE 2.0
|
172 |
+
*
|
173 |
if (window.location.href.includes( "fb_force_resync" )) {
|
174 |
window.onload = function() { sync_confirm( "fb_force_resync" ); };
|
175 |
} else if (window.location.href.includes( "fb_test_product_sync" )) {
|
177 |
window.is_test = true;
|
178 |
window.onload = function() { sync_confirm( "fb_test_product_sync" ); };
|
179 |
}
|
180 |
+
*/
|
181 |
|
182 |
|
183 |
/**
|
244 |
message = facebook_for_woocommerce_settings_sync.i18n.general_error;
|
245 |
}
|
246 |
|
247 |
+
jQuery( '#sync_progress' ).show().html( '<span style="color: #DC3232">' + message + '</span>' );
|
248 |
}
|
249 |
} );
|
250 |
}
|
269 |
|
270 |
jQuery( '.messenger-field' ).each( function () {
|
271 |
|
272 |
+
if ( typeof jQuery( this ).data( 'default' ) !== 'undefined' ) {
|
273 |
+
jQuery( this ).val( jQuery( this ).data( 'default' ) ).trigger( 'change' );
|
274 |
}
|
275 |
} );
|
276 |
|
325 |
function save_settings_for_plugin(callback, failcallback) {
|
326 |
save_settings(
|
327 |
function(response){
|
328 |
+
if (response && true === response.success ) {
|
329 |
console.log( response );
|
330 |
callback( response );
|
331 |
} else {
|
332 |
+
console.log( 'Fail response on save_settings_for_plugin' );
|
333 |
failcallback( response );
|
334 |
}
|
335 |
},
|
351 |
window.sendToFacebook( 'ack set pixel', message.params );
|
352 |
window.sendToFacebook( 'ack set page access token', message.params );
|
353 |
window.sendToFacebook( 'ack set merchant settings', message.params );
|
354 |
+
// sync_all_products( true ); TODO: reinstate when switching back to FBE 2
|
355 |
} else {
|
356 |
window.sendToFacebook( 'fail save_settings', response );
|
357 |
console.log( 'Fail response on save_settings_and_sync' );
|
463 |
// We need this to support changing the pixel id after setup.
|
464 |
save_settings(
|
465 |
function(response){
|
466 |
+
if (response && true === response.success ) {
|
467 |
window.sendToFacebook( 'ack set pixel', message.params );
|
468 |
} //may not get settings_saved if we try to save pixel before an API key
|
469 |
},
|
475 |
);
|
476 |
}
|
477 |
|
478 |
+
function genFeed( message ) {
|
479 |
+
|
480 |
+
console.log( 'generating feed' );
|
481 |
+
|
482 |
+
jQuery.get( window.facebookAdsToolboxConfig.feedPrepared.feedUrl + '®enerate=true' )
|
483 |
+
.done( function( json ) {
|
484 |
+
window.sendToFacebook( 'ack feed', message.params );
|
485 |
+
} )
|
486 |
+
.fail( function( xhr, ajaxOptions, thronwError ) {
|
487 |
+
window.sendToFacebook( 'fail feed', message.params );
|
488 |
+
} );
|
489 |
}
|
490 |
|
491 |
function setAccessTokenAndPageId(message) {
|
561 |
}
|
562 |
}
|
563 |
|
564 |
+
function setFeedMigrated(message) {
|
565 |
+
|
566 |
+
if ( ! message.params.hasOwnProperty( 'feed_migrated' ) ) {
|
567 |
+
|
568 |
+
console.error(
|
569 |
+
'Facebook Extension Error: feed migrated not received',
|
570 |
+
message.params
|
571 |
+
);
|
572 |
+
|
573 |
+
window.sendToFacebook( 'fail set feed migrated', message.params );
|
574 |
+
return;
|
575 |
+
}
|
576 |
+
|
577 |
+
settings.feed_migrated = message.params.feed_migrated;
|
578 |
+
window.facebookAdsToolboxConfig.feedPrepared.feedMigrated = message.params.feed_migrated;
|
579 |
+
|
580 |
+
jQuery( '#woocommerce-facebook-settings-sync-products' ).hide();
|
581 |
+
jQuery( '.notice.wc-facebook-migrate-notice' ).hide();
|
582 |
+
|
583 |
+
save_settings_for_plugin(
|
584 |
+
function( response ) {
|
585 |
+
window.sendToFacebook( 'ack set feed migrated', event.data );
|
586 |
+
},
|
587 |
+
function( response ) {
|
588 |
+
window.sendToFacebook( 'fail set feed migrated', event.data );
|
589 |
+
}
|
590 |
+
);
|
591 |
+
}
|
592 |
+
|
593 |
+
function iFrameListener( event ) {
|
594 |
+
|
595 |
const origin = event.origin || event.originalEvent.origin;
|
596 |
+
|
597 |
+
if ( origin !== window.facebookAdsToolboxConfig.popupOrigin ) {
|
598 |
+
|
599 |
+
// Fix for web.facebook.com
|
600 |
+
if ( urlFromSameDomain( origin, window.facebookAdsToolboxConfig.popupOrigin ) ) {
|
601 |
+
|
602 |
+
window.facebookAdsToolboxConfig.popupOrigin = origin;
|
603 |
+
|
604 |
+
// otherwise bail if not a message from facebook.com
|
605 |
+
} else {
|
606 |
+
|
607 |
+
return;
|
608 |
+
}
|
609 |
}
|
610 |
|
611 |
switch (event.data.type) {
|
631 |
case 'get dia settings':
|
632 |
window.sendToFacebook( 'dia settings', window.diaConfig );
|
633 |
break;
|
|
|
|
|
|
|
634 |
case 'set catalog':
|
635 |
setCatalog( event.data );
|
636 |
break;
|
637 |
+
case 'set feed migrated':
|
638 |
+
setFeedMigrated( event.data );
|
639 |
+
break;
|
640 |
case 'set pixel':
|
641 |
setPixel( event.data );
|
642 |
break;
|
643 |
case 'gen feed':
|
644 |
+
genFeed( event.data );
|
645 |
break;
|
646 |
|
647 |
+
// simulate this success response so FBE considers setup complete
|
648 |
case 'set page access token':
|
649 |
+
window.sendToFacebook( 'ack set page access token', event.data.params );
|
650 |
+
break;
|
651 |
+
|
652 |
+
case 'set page':
|
653 |
+
setPage( event.data );
|
654 |
+
break;
|
655 |
+
|
656 |
+
case 'set merchant settings':
|
657 |
+
|
658 |
+
setMerchantSettings( event.data );
|
659 |
+
|
660 |
+
// this should be the final message sent, so save the settings at this point
|
661 |
+
save_settings(
|
662 |
+
function( response ) {
|
663 |
+
|
664 |
+
console.log( response );
|
665 |
+
|
666 |
+
if ( response && true === response.success ) {
|
667 |
+
|
668 |
+
// final acks
|
669 |
+
if ( settings.pixel_id ) {
|
670 |
+
window.sendToFacebook( 'ack set pixel', event.data.params );
|
671 |
+
}
|
672 |
+
|
673 |
+
if ( settings.page_id ) {
|
674 |
+
window.sendToFacebook( 'ack set page', event.data.params );
|
675 |
+
}
|
676 |
+
|
677 |
+
if ( settings.external_merchant_settings_id ) {
|
678 |
+
|
679 |
+
window.sendToFacebook( 'ack set merchant settings', event.data.params );
|
680 |
+
|
681 |
+
// hide Facebook fancy box and show integration settings
|
682 |
+
jQuery( '#fbsetup' ).hide();
|
683 |
+
jQuery( '#integration-settings' ).show();
|
684 |
+
jQuery( '.woocommerce-save-button' ).show();
|
685 |
+
}
|
686 |
+
|
687 |
+
} else {
|
688 |
+
|
689 |
+
window.sendToFacebook( 'fail save_settings', response );
|
690 |
+
|
691 |
+
console.log( 'Fail response on save_settings' );
|
692 |
+
}
|
693 |
+
},
|
694 |
+
function( errorResponse ){
|
695 |
+
|
696 |
+
console.log( 'Ajax error while saving settings:' + JSON.stringify( errorResponse ) );
|
697 |
+
|
698 |
+
window.sendToFacebook( 'fail save_settings_ajax', JSON.stringify( errorResponse ) );
|
699 |
+
}
|
700 |
+
);
|
701 |
+
|
702 |
break;
|
703 |
|
704 |
case 'set msger chat':
|
708 |
window.sendToFacebook( 'ack msger chat', event.data );
|
709 |
},
|
710 |
function(response) {
|
711 |
+
window.sendToFacebook( 'fail msger chat', event.data );
|
712 |
}
|
713 |
);
|
714 |
break;
|
717 |
|
718 |
addAnEventListener( window,'message',iFrameListener );
|
719 |
|
720 |
+
/**
|
721 |
+
* Sets the page parameters received from FBE.
|
722 |
+
*
|
723 |
+
* @since 1.11.0
|
724 |
+
*
|
725 |
+
* @param {Object} message
|
726 |
+
*/
|
727 |
+
function setPage( message ) {
|
728 |
+
|
729 |
+
if ( ! message.params.hasOwnProperty( 'page_id' ) ) {
|
730 |
+
|
731 |
+
console.error(
|
732 |
+
'Facebook Extension Error: page ID not received',
|
733 |
+
message.params
|
734 |
+
);
|
735 |
+
|
736 |
+
window.sendToFacebook( 'fail set page', message.params );
|
737 |
+
return;
|
738 |
+
}
|
739 |
+
|
740 |
+
settings.page_id = message.params.page_id;
|
741 |
+
|
742 |
+
jQuery( '#woocommerce_facebookcommerce_facebook_page_id' ).val( settings.page_id );
|
743 |
+
}
|
744 |
+
|
745 |
function urlFromSameDomain(url1, url2) {
|
746 |
if ( ! url1.startsWith( 'http' ) || ! url2.startsWith( 'http' )) {
|
747 |
return false;
|
926 |
// enable Manage connection and Sync products buttons when sync stops
|
927 |
jQuery( '#woocommerce-facebook-settings-manage-connection, #woocommerce-facebook-settings-sync-products' ).css( 'pointer-events', 'auto' );
|
928 |
|
929 |
+
jQuery( '#sync_progress' ).show().html( '<span style="color: #DC3232">' + facebook_for_woocommerce_settings_sync.i18n.feed_upload_error + '</span>' );
|
930 |
|
931 |
window.feed_upload = false;
|
932 |
if (window.is_test) {
|
1079 |
);
|
1080 |
}
|
1081 |
|
|
|
1082 |
jQuery( document ).ready( function( $ ) {
|
1083 |
|
1084 |
+
// when a "manage connection" link is click from a notice
|
1085 |
+
$( '.notice .wc-facebook-manage-connection' ).click( function( event ) {
|
1086 |
+
|
1087 |
+
event.preventDefault();
|
1088 |
+
|
1089 |
+
facebookConfig();
|
1090 |
+
} );
|
1091 |
|
1092 |
$( '#woocommerce-facebook-settings-sync-products' ).click( function( event ) {
|
1093 |
|
1095 |
|
1096 |
sync_confirm();
|
1097 |
} );
|
1098 |
+
|
1099 |
} );
|
assets/js/facebook-settings.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
"use strict";var fb_sync_no_response_count=0,fb_show_advanced_options=!1;function openPopup(){var e,o=screen.height/2-404,n=screen.width/2-576.5;window.originParam=window.location.protocol+"//"+window.location.host,window.facebookAdsToolboxConfig.popupOrigin.includes("staticxx")&&(window.facebookAdsToolboxConfig.popupOrigin="https://www.facebook.com/"),window.facebookAdsToolboxConfig.popupOrigin=prepend_protocol(window.facebookAdsToolboxConfig.popupOrigin),e=window.facebookAdsToolboxConfig.popupOrigin;var t=window.open(e+"/login.php?display=popup&next="+encodeURIComponent(e+"/ads/dia?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=1153","height=808","top="+o,"left="+n].join(","));return function(e,o){t.postMessage({type:e,params:o},window.facebookAdsToolboxConfig.popupOrigin)}}function prepend_protocol(e){return 0===e.indexOf("//www.")&&(e="https:"+e),e}function get_pixel_id_box(){return document.querySelector("#woocommerce_facebookcommerce_facebook_pixel_id")}function get_pixel_use_pii_id_box(){return document.querySelector("#woocommerce_facebookcommerce_enable_advanced_matching")}function get_page_id_box(){return document.querySelector("#woocommerce_facebookcommerce_facebook_page_id")}function ajax(e){var o=1<arguments.length&&void 0!==arguments[1]?arguments[1]:null,n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null,t=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null,s=Object.assign({},{action:e},o);jQuery.post(ajaxurl,s,function(e){n&&n(e)}).fail(function(e){t&&t(e)})}var settings={facebook_for_woocommerce:1},pixel_settings={facebook_for_woocommerce:1};function facebookConfig(){window.sendToFacebook=openPopup(),window.diaConfig={clientSetup:window.facebookAdsToolboxConfig}}function fb_flush(){return console.log("Removing all FBIDs from all products!"),ajax("ajax_reset_all_fb_products",{_ajax_nonce:wc_facebook_settings_jsx.nonce},null,function(){console.log("Failed to reset all FB products")})}function sync_confirm(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:null,o="";switch(e){case"fb_force_resync":o=facebook_for_woocommerce_settings_sync.i18n.confirm_resync;break;case"fb_test_product_sync":o=facebook_for_woocommerce_settings_sync.i18n.confirm_sync_test;break;default:o=facebook_for_woocommerce_settings_sync.i18n.confirm_sync}confirm(o)&&(sync_all_products(window.facebookAdsToolboxConfig.feed.hasClientSideFeedUpload,"fb_test_product_sync"==e),window.fb_sync_start_time=(new Date).getTime())}function sync_all_products(){var n=0<arguments.length&&void 0!==arguments[0]&&arguments[0],e=1<arguments.length&&void 0!==arguments[1]&&arguments[1];window.fb_connected=!0,sync_in_progress();var o={};o=n?(window.facebookAdsToolboxConfig.feed.hasClientSideFeedUpload=!0,window.feed_upload=!0,ping_feed_status_queue(),e?{action:"ajax_test_sync_products_using_feed"}:{action:"ajax_sync_all_fb_products_using_feed",_ajax_nonce:wc_facebook_settings_jsx.nonce}):(check_background_processor_status(),{action:"ajax_sync_all_fb_products",_ajax_nonce:wc_facebook_settings_jsx.nonce}),jQuery.post(ajaxurl,o).then(function(e){if(!e&&n||e&&!1===e.success){clearInterval(window.fb_pings),clearInterval(window.fb_feed_pings),jQuery("#woocommerce-facebook-settings-manage-connection, #woocommerce-facebook-settings-sync-products").css("pointer-events","auto");var o=void 0;o=e&&e.data&&e.data.error?e.data.error:facebook_for_woocommerce_settings_sync.i18n.general_error,$("#sync_progress").show().html('<span style="color: #DC3232">'+o+"</span>")}})}function delete_all_settings(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:null,o=1<arguments.length&&void 0!==arguments[1]?arguments[1]:null;return get_pixel_id_box()&&(get_pixel_id_box().value=""),get_pixel_use_pii_id_box()&&(get_pixel_use_pii_id_box().checked=!1),get_page_id_box()&&(get_page_id_box().value=""),jQuery("#woocommerce_facebookcommerce_enable_messenger").prop("checked",!1).trigger("change"),jQuery(".messenger-field").each(function(){void 0!==$(this).data("default")&&$(this).val($(this).data("default")).trigger("change")}),window.facebookAdsToolboxConfig.pixel.pixelId="",window.facebookAdsToolboxConfig.diaSettingId="",window.fb_connected=!1,not_connected(),console.log("Deleting all settings and removing all FBIDs!"),ajax("ajax_delete_fb_settings",{_ajax_nonce:wc_facebook_settings_jsx.nonce},e,o)}function save_settings(){var o=0<arguments.length&&void 0!==arguments[0]?arguments[0]:null,n=1<arguments.length&&void 0!==arguments[1]?arguments[1]:null,e=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null;(e=e||settings)._ajax_nonce=wc_facebook_settings_jsx.nonce,ajax("ajax_save_fb_settings",e,function(e){o&&o(e)},function(e){n&&n(e)})}function save_settings_for_plugin(o,n){save_settings(function(e){e&&e.includes("settings_saved")?(console.log(e),o(e)):(console.log("Fail response on save_settings_and_sync"),n(e))},function(e){console.log("Ajax error while saving settings:"+JSON.stringify(e)),n(e)})}function save_settings_and_sync(o){"api_key"in settings&&save_settings(function(e){e&&e.includes("settings_saved")?(console.log(e),window.sendToFacebook("ack set pixel",o.params),window.sendToFacebook("ack set page access token",o.params),window.sendToFacebook("ack set merchant settings",o.params),sync_all_products(!0)):(window.sendToFacebook("fail save_settings",e),console.log("Fail response on save_settings_and_sync"))},function(e){console.log("Ajax error while saving settings:"+JSON.stringify(e)),window.sendToFacebook("fail save_settings_ajax",JSON.stringify(e))})}function sync_in_progress(){jQuery("#woocommerce-facebook-settings-manage-connection, #woocommerce-facebook-settings-sync-products").css("pointer-events","none"),jQuery("#sync_progress").show().html(facebook_for_woocommerce_settings_sync.i18n.sync_in_progress)}function sync_not_in_progress(){jQuery("#woocommerce-facebook-settings-manage-connection, #woocommerce-facebook-settings-sync-products").css("pointer-events","auto"),jQuery("#sync_progress").empty().hide()}function not_connected(){jQuery("#fbsetup").show(),jQuery("#integration-settings").hide(),jQuery(".woocommerce-save-button").hide()}function addAnEventListener(e,o,n){"addEventListener"in e?e.addEventListener(o,n,!1):"attachEvent"in e&&e.attachEvent("on"+o,n)}function setMerchantSettings(e){if(!e.params.setting_id)return console.error("Facebook Extension Error: got no setting_id",e.params),void window.sendToFacebook("fail set merchant settings",e.params);settings.external_merchant_settings_id=e.params.setting_id,window.facebookAdsToolboxConfig.diaSettingId=e.params.setting_id}function setCatalog(e){if(!e.params.catalog_id)return console.error("Facebook Extension Error: got no catalog_id",e.params),void window.sendToFacebook("fail set catalog",e.params);settings.product_catalog_id=e.params.catalog_id,window.sendToFacebook("ack set catalog",e.params)}function setPixel(o){if(!o.params.pixel_id)return console.error("Facebook Ads Extension Error: got no pixel_id",o.params),void window.sendToFacebook("fail set pixel",o.params);get_pixel_id_box()&&(get_pixel_id_box().value=o.params.pixel_id),settings.pixel_id=o.params.pixel_id,pixel_settings.pixel_id=settings.pixel_id,void 0!==o.params.pixel_use_pii&&(get_pixel_use_pii_id_box()&&(get_pixel_use_pii_id_box().checked=!!o.params.pixel_use_pii),settings.pixel_use_pii=o.params.pixel_use_pii,pixel_settings.pixel_use_pii=settings.pixel_use_pii),save_settings(function(e){e&&e.includes("settings_saved")&&window.sendToFacebook("ack set pixel",o.params)},function(e){console.log(e),window.sendToFacebook("fail set pixel",e)},pixel_settings)}function genFeed(e){}function setAccessTokenAndPageId(e){if(!e.params.page_token)return console.error("Facebook Ads Extension Error: got no page_token",e.params),void window.sendToFacebook("fail set page access token",e.params);get_page_id_box()&&(get_page_id_box().value=e.params.page_id),settings.api_key=e.params.page_token,settings.page_id=e.params.page_id,window.facebookAdsToolboxConfig.tokenExpired=!1,document.querySelector("#connection-message-invalid")&&(document.querySelector("#connection-message-invalid").style.display="none"),document.querySelector("#connection-message-refresh")&&(document.querySelector("#connection-message-refresh").style.display="block")}function setMsgerChatSetup(e){if(e.hasOwnProperty("is_messenger_chat_plugin_enabled")&&(settings.is_messenger_chat_plugin_enabled=e.is_messenger_chat_plugin_enabled,jQuery("#woocommerce_facebookcommerce_enable_messenger").prop("checked",e.is_messenger_chat_plugin_enabled).trigger("change")),e.hasOwnProperty("facebook_jssdk_version")&&(settings.facebook_jssdk_version=e.facebook_jssdk_version),e.hasOwnProperty("page_id")&&(settings.fb_page_id=e.page_id),e.hasOwnProperty("customization")){var o=e.customization;o.hasOwnProperty("greetingTextCode")&&(settings.msger_chat_customization_greeting_text_code=o.greetingTextCode,jQuery("#woocommerce_facebookcommerce_messenger_greeting").val(o.greetingTextCode).trigger("change")),o.hasOwnProperty("locale")&&(settings.msger_chat_customization_locale=o.locale,jQuery("#woocommerce_facebookcommerce_messenger_locale").val(o.locale).trigger("change")),o.hasOwnProperty("themeColorCode")&&(settings.msger_chat_customization_theme_color_code=o.themeColorCode,jQuery("#woocommerce_facebookcommerce_messenger_color_hex").val(o.themeColorCode).trigger("change"))}}function iFrameListener(o){var e=o.origin||o.originalEvent.origin;switch(e!=window.facebookAdsToolboxConfig.popupOrigin&&urlFromSameDomain(e,window.facebookAdsToolboxConfig.popupOrigin)&&(window.facebookAdsToolboxConfig.popupOrigin=e),o.data.type){case"reset":delete_all_settings(function(e){e&&o.data.params?"Settings Deleted"===e?window.sendToFacebook("ack reset",o.data.params):(console.log(e),alert(e)):console.log("Got no response from delete_all_settings")},function(e){console.error(e)});break;case"get dia settings":window.sendToFacebook("dia settings",window.diaConfig);break;case"set merchant settings":setMerchantSettings(o.data);break;case"set catalog":setCatalog(o.data);break;case"set pixel":setPixel(o.data);break;case"gen feed":genFeed();break;case"set page access token":setAccessTokenAndPageId(o.data),save_settings_and_sync(o.data),jQuery("#fbsetup").hide(),jQuery("#integration-settings").show(),jQuery(".woocommerce-save-button").show();break;case"set msger chat":setMsgerChatSetup(o.data.params),save_settings_for_plugin(function(e){window.sendToFacebook("ack msger chat",o.data)},function(e){window.sendToFacebook("fail ack msger chat",o.data)})}}function urlFromSameDomain(e,o){if(!e.startsWith("http")||!o.startsWith("http"))return!1;var n=parseURL(e),t=parseURL(o),s=n.host.replace(/^\w+\./,"www."),i=t.host.replace(/^\w+\./,"www.");return n.protocol===t.protocol&&s===i}function parseURL(e){var o=document.createElement("a");return o.href=e,o}function check_background_processor_status(){window.facebookAdsToolboxConfig.feed.hasClientSideFeedUpload||(clearInterval(window.fb_pings),window.fb_pings=setInterval(function(){console.log("Pinging queue..."),check_queues()},1e4))}function ping_feed_status_queue(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:0;clearInterval(window.fb_feed_pings),window.fb_feed_pings=setInterval(function(){console.log("Pinging feed uploading queue..."),check_feed_upload_queue(e)},3e4*(1<<e))}function product_sync_complete(e){sync_not_in_progress(),e.empty().hide(),clearInterval(window.fb_pings)}function check_queues(){ajax("ajax_fb_background_check_queue",{request_time:(new Date).getTime(),_ajax_nonce:wc_facebook_settings_jsx.nonce},function(e){if(window.feed_upload)clearInterval(window.fb_pings);else{var o=jQuery("#sync_progress"),n=parse_response_check_connection(e);if(n){if(fb_sync_no_response_count=0,n){n.background||(console.log("No background sync found, disabling pings"),clearInterval(window.fb_pings));var t=!!n.processing,s=n.remaining;if(t){var i="";i=1===s?facebook_for_woocommerce_settings_sync.i18n.sync_remaining_items_singular:facebook_for_woocommerce_settings_sync.i18n.sync_remaining_items_plural,o.show().html(i.replace("{count}",s)),0===s&&product_sync_complete(o)}else{if(window.fb_sync_start_time&&n.request_time){var c=new Date(parseInt(n.request_time));if(window.fb_sync_start_time>c)return void console.log("OLD PING")}0===s&&product_sync_complete(o)}}}else 5<fb_sync_no_response_count++&&clearInterval(window.fb_pings)}})}function parse_response_check_connection(e){if(e){console.log(e);var o=e.substring(e.indexOf("{"));return(o=JSON.parse(o)).connected||window.fb_connected?o:(not_connected(),null)}return null}function check_feed_upload_queue(t){ajax("ajax_check_feed_upload_status",{_ajax_nonce:wc_facebook_settings_jsx.nonce},function(e){var o=jQuery("#sync_progress"),n=parse_response_check_connection(e);if(clearInterval(window.fb_feed_pings),n)switch(n.status){case"complete":window.feed_upload=!1,window.is_test?display_test_result():product_sync_complete(o);break;case"in progress":o.show().html(facebook_for_woocommerce_settings_sync.i18n.sync_in_progress),ping_feed_status_queue(t+1);break;default:jQuery("#woocommerce-facebook-settings-manage-connection, #woocommerce-facebook-settings-sync-products").css("pointer-events","auto"),$("#sync_progress").show().html('<span style="color: #DC3232">'+facebook_for_woocommerce_settings_sync.i18n.feed_upload_error+"</span>"),window.feed_upload=!1,window.is_test&&display_test_result()}})}function display_test_result(){ajax("ajax_display_test_result",{_ajax_nonce:wc_facebook_settings_jsx.nonce},function(e){var o=jQuery("#sync_progress"),n=document.querySelector("#sync_complete"),t=parse_response_check_connection(e);if(t)switch(t.pass){case"true":sync_not_in_progress(),n&&(n.style.display="",n.innerHTML=facebook_for_woocommerce_settings_sync.i18n.integration_test_sucessful),o.empty().hide(),window.is_test=!1;break;case"in progress":o.show().html(facebook_for_woocommerce_settings_sync.i18n.integration_test_in_progress),ping_feed_status_queue();break;default:window.debug_info=t.debug_info+"<br/>"+t.stack_trace,n&&(n.style.display="",n.innerHTML=facebook_for_woocommerce_settings_sync.i18n.integration_test_failed),o.empty().hide(),document.querySelector("#debug_info")&&(document.querySelector("#debug_info").style.display=""),window.is_test=!1}})}function show_debug_info(){var e=document.querySelector("#stack_trace");e&&(e.innerHTML=window.debug_info),document.querySelector("#debug_info")&&(document.querySelector("#debug_info").style.display="none"),window.debug_info=""}function fbe_init_nux_messages(){var r=window.jQuery;r(function(){r.each(r(".nux-message"),function(e,o){var n=r(o),t=n.data("target"),s=r("#"+t),i=s.position(),c=s.height()/2,a=s.outerWidth();n.css({top:Math.ceil(i.top+c)+"px",left:Math.ceil(i.left+a)+"px",display:"block"}),r(".nux-message-close-btn",n).click(function(){r(o).hide()})})})}function saveAutoSyncSchedule(){var e=document.getElementsByClassName("autosyncCheck")[0].checked,o=document.getElementsByClassName("autosyncTime")[0],n=(document.getElementsByClassName("autosyncSaveButton")[0],document.getElementsByClassName("autosyncSavedNotice")[0]);e?(o.removeAttribute("disabled"),n.style.transition="",n.style.opacity=1,setTimeout(function(){n.style.opacity=0,n.style.transition="opacity 5s"},3e3)):o.setAttribute("disabled",!0),ajax("ajax_schedule_force_resync",{enabled:e?1:0,time:o.value,_ajax_nonce:wc_facebook_settings_jsx.nonce})}function syncShortDescription(){var e=document.getElementsByClassName("syncShortDescription")[0].checked;ajax("ajax_update_fb_option",{option:"fb_sync_short_description",option_value:e?1:0,_ajax_nonce:wc_facebook_settings_jsx.nonce},null,function(){document.getElementsByClassName("syncShortDescription")[0].checked=!e,console.log("Failed to sync Short Description")})}window.location.href.includes("fb_force_resync")?window.onload=function(){sync_confirm("fb_force_resync")}:window.location.href.includes("fb_test_product_sync")&&(window.is_test=!0,window.onload=function(){sync_confirm("fb_test_product_sync")}),addAnEventListener(window,"message",iFrameListener),jQuery(document).ready(function(e){check_background_processor_status(),e("#woocommerce-facebook-settings-sync-products").click(function(e){e.preventDefault(),sync_confirm()})});
|
1 |
+
"use strict";var fb_sync_no_response_count=0,fb_show_advanced_options=!1;function openPopup(){var e,o=screen.height/2-404,n=screen.width/2-576.5;window.originParam=window.location.protocol+"//"+window.location.host,window.facebookAdsToolboxConfig.popupOrigin.includes("staticxx")&&(window.facebookAdsToolboxConfig.popupOrigin="https://www.facebook.com/"),window.facebookAdsToolboxConfig.popupOrigin=prepend_protocol(window.facebookAdsToolboxConfig.popupOrigin),e=window.facebookAdsToolboxConfig.popupOrigin;var t=window.open(e+"/login.php?display=popup&next="+encodeURIComponent(e+"/ads/dia?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=1153","height=808","top="+o,"left="+n].join(","));return function(e,o){t.postMessage({type:e,params:o},window.facebookAdsToolboxConfig.popupOrigin)}}function prepend_protocol(e){return 0===e.indexOf("//www.")&&(e="https:"+e),e}function get_pixel_id_box(){return document.querySelector("#woocommerce_facebookcommerce_facebook_pixel_id")}function get_pixel_use_pii_id_box(){return document.querySelector("#woocommerce_facebookcommerce_enable_advanced_matching")}function get_page_id_box(){return document.querySelector("#woocommerce_facebookcommerce_facebook_page_id")}function ajax(e){var o=1<arguments.length&&void 0!==arguments[1]?arguments[1]:null,n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null,t=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null,s=Object.assign({},{action:e},o);jQuery.post(ajaxurl,s,function(e){n&&n(e)}).fail(function(e){t&&t(e)})}var settings={facebook_for_woocommerce:1},pixel_settings={facebook_for_woocommerce:1};function facebookConfig(){window.sendToFacebook=openPopup(),window.diaConfig={clientSetup:window.facebookAdsToolboxConfig}}function fb_flush(){return console.log("Removing all FBIDs from all products!"),ajax("ajax_reset_all_fb_products",{_ajax_nonce:wc_facebook_settings_jsx.nonce},null,function(){console.log("Failed to reset all FB products")})}function sync_confirm(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:null,o="";switch(e){case"fb_force_resync":o=facebook_for_woocommerce_settings_sync.i18n.confirm_resync;break;case"fb_test_product_sync":o=facebook_for_woocommerce_settings_sync.i18n.confirm_sync_test;break;default:o=facebook_for_woocommerce_settings_sync.i18n.confirm_sync}confirm(o)&&(sync_all_products(window.facebookAdsToolboxConfig.feed.hasClientSideFeedUpload,"fb_test_product_sync"==e),window.fb_sync_start_time=(new Date).getTime())}function sync_all_products(){var n=0<arguments.length&&void 0!==arguments[0]&&arguments[0],e=1<arguments.length&&void 0!==arguments[1]&&arguments[1];window.fb_connected=!0,sync_in_progress();var o={};o=n?(window.facebookAdsToolboxConfig.feed.hasClientSideFeedUpload=!0,window.feed_upload=!0,ping_feed_status_queue(),e?{action:"ajax_test_sync_products_using_feed"}:{action:"ajax_sync_all_fb_products_using_feed",_ajax_nonce:wc_facebook_settings_jsx.nonce}):(check_background_processor_status(),{action:"ajax_sync_all_fb_products",_ajax_nonce:wc_facebook_settings_jsx.nonce}),jQuery.post(ajaxurl,o).then(function(e){if(!e&&n||e&&!1===e.success){clearInterval(window.fb_pings),clearInterval(window.fb_feed_pings),jQuery("#woocommerce-facebook-settings-manage-connection, #woocommerce-facebook-settings-sync-products").css("pointer-events","auto");var o=void 0;o=e&&e.data&&e.data.error?e.data.error:facebook_for_woocommerce_settings_sync.i18n.general_error,jQuery("#sync_progress").show().html('<span style="color: #DC3232">'+o+"</span>")}})}function delete_all_settings(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:null,o=1<arguments.length&&void 0!==arguments[1]?arguments[1]:null;return get_pixel_id_box()&&(get_pixel_id_box().value=""),get_pixel_use_pii_id_box()&&(get_pixel_use_pii_id_box().checked=!1),get_page_id_box()&&(get_page_id_box().value=""),jQuery("#woocommerce_facebookcommerce_enable_messenger").prop("checked",!1).trigger("change"),jQuery(".messenger-field").each(function(){void 0!==jQuery(this).data("default")&&jQuery(this).val(jQuery(this).data("default")).trigger("change")}),window.facebookAdsToolboxConfig.pixel.pixelId="",window.facebookAdsToolboxConfig.diaSettingId="",window.fb_connected=!1,not_connected(),console.log("Deleting all settings and removing all FBIDs!"),ajax("ajax_delete_fb_settings",{_ajax_nonce:wc_facebook_settings_jsx.nonce},e,o)}function save_settings(){var o=0<arguments.length&&void 0!==arguments[0]?arguments[0]:null,n=1<arguments.length&&void 0!==arguments[1]?arguments[1]:null,e=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null;(e=e||settings)._ajax_nonce=wc_facebook_settings_jsx.nonce,ajax("ajax_save_fb_settings",e,function(e){o&&o(e)},function(e){n&&n(e)})}function save_settings_for_plugin(o,n){save_settings(function(e){e&&!0===e.success?(console.log(e),o(e)):(console.log("Fail response on save_settings_for_plugin"),n(e))},function(e){console.log("Ajax error while saving settings:"+JSON.stringify(e)),n(e)})}function save_settings_and_sync(o){"api_key"in settings&&save_settings(function(e){e&&e.includes("settings_saved")?(console.log(e),window.sendToFacebook("ack set pixel",o.params),window.sendToFacebook("ack set page access token",o.params),window.sendToFacebook("ack set merchant settings",o.params)):(window.sendToFacebook("fail save_settings",e),console.log("Fail response on save_settings_and_sync"))},function(e){console.log("Ajax error while saving settings:"+JSON.stringify(e)),window.sendToFacebook("fail save_settings_ajax",JSON.stringify(e))})}function sync_in_progress(){jQuery("#woocommerce-facebook-settings-manage-connection, #woocommerce-facebook-settings-sync-products").css("pointer-events","none"),jQuery("#sync_progress").show().html(facebook_for_woocommerce_settings_sync.i18n.sync_in_progress)}function sync_not_in_progress(){jQuery("#woocommerce-facebook-settings-manage-connection, #woocommerce-facebook-settings-sync-products").css("pointer-events","auto"),jQuery("#sync_progress").empty().hide()}function not_connected(){jQuery("#fbsetup").show(),jQuery("#integration-settings").hide(),jQuery(".woocommerce-save-button").hide()}function addAnEventListener(e,o,n){"addEventListener"in e?e.addEventListener(o,n,!1):"attachEvent"in e&&e.attachEvent("on"+o,n)}function setMerchantSettings(e){if(!e.params.setting_id)return console.error("Facebook Extension Error: got no setting_id",e.params),void window.sendToFacebook("fail set merchant settings",e.params);settings.external_merchant_settings_id=e.params.setting_id,window.facebookAdsToolboxConfig.diaSettingId=e.params.setting_id}function setCatalog(e){if(!e.params.catalog_id)return console.error("Facebook Extension Error: got no catalog_id",e.params),void window.sendToFacebook("fail set catalog",e.params);settings.product_catalog_id=e.params.catalog_id,window.sendToFacebook("ack set catalog",e.params)}function setPixel(o){if(!o.params.pixel_id)return console.error("Facebook Ads Extension Error: got no pixel_id",o.params),void window.sendToFacebook("fail set pixel",o.params);get_pixel_id_box()&&(get_pixel_id_box().value=o.params.pixel_id),settings.pixel_id=o.params.pixel_id,pixel_settings.pixel_id=settings.pixel_id,void 0!==o.params.pixel_use_pii&&(get_pixel_use_pii_id_box()&&(get_pixel_use_pii_id_box().checked=!!o.params.pixel_use_pii),settings.pixel_use_pii=o.params.pixel_use_pii,pixel_settings.pixel_use_pii=settings.pixel_use_pii),save_settings(function(e){e&&!0===e.success&&window.sendToFacebook("ack set pixel",o.params)},function(e){console.log(e),window.sendToFacebook("fail set pixel",e)},pixel_settings)}function genFeed(t){console.log("generating feed"),jQuery.get(window.facebookAdsToolboxConfig.feedPrepared.feedUrl+"®enerate=true").done(function(e){window.sendToFacebook("ack feed",t.params)}).fail(function(e,o,n){window.sendToFacebook("fail feed",t.params)})}function setAccessTokenAndPageId(e){if(!e.params.page_token)return console.error("Facebook Ads Extension Error: got no page_token",e.params),void window.sendToFacebook("fail set page access token",e.params);get_page_id_box()&&(get_page_id_box().value=e.params.page_id),settings.api_key=e.params.page_token,settings.page_id=e.params.page_id,window.facebookAdsToolboxConfig.tokenExpired=!1,document.querySelector("#connection-message-invalid")&&(document.querySelector("#connection-message-invalid").style.display="none"),document.querySelector("#connection-message-refresh")&&(document.querySelector("#connection-message-refresh").style.display="block")}function setMsgerChatSetup(e){if(e.hasOwnProperty("is_messenger_chat_plugin_enabled")&&(settings.is_messenger_chat_plugin_enabled=e.is_messenger_chat_plugin_enabled,jQuery("#woocommerce_facebookcommerce_enable_messenger").prop("checked",e.is_messenger_chat_plugin_enabled).trigger("change")),e.hasOwnProperty("facebook_jssdk_version")&&(settings.facebook_jssdk_version=e.facebook_jssdk_version),e.hasOwnProperty("page_id")&&(settings.fb_page_id=e.page_id),e.hasOwnProperty("customization")){var o=e.customization;o.hasOwnProperty("greetingTextCode")&&(settings.msger_chat_customization_greeting_text_code=o.greetingTextCode,jQuery("#woocommerce_facebookcommerce_messenger_greeting").val(o.greetingTextCode).trigger("change")),o.hasOwnProperty("locale")&&(settings.msger_chat_customization_locale=o.locale,jQuery("#woocommerce_facebookcommerce_messenger_locale").val(o.locale).trigger("change")),o.hasOwnProperty("themeColorCode")&&(settings.msger_chat_customization_theme_color_code=o.themeColorCode,jQuery("#woocommerce_facebookcommerce_messenger_color_hex").val(o.themeColorCode).trigger("change"))}}function setFeedMigrated(e){if(!e.params.hasOwnProperty("feed_migrated"))return console.error("Facebook Extension Error: feed migrated not received",e.params),void window.sendToFacebook("fail set feed migrated",e.params);settings.feed_migrated=e.params.feed_migrated,window.facebookAdsToolboxConfig.feedPrepared.feedMigrated=e.params.feed_migrated,jQuery("#woocommerce-facebook-settings-sync-products").hide(),jQuery(".notice.wc-facebook-migrate-notice").hide(),save_settings_for_plugin(function(e){window.sendToFacebook("ack set feed migrated",event.data)},function(e){window.sendToFacebook("fail set feed migrated",event.data)})}function iFrameListener(o){var e=o.origin||o.originalEvent.origin;if(e!==window.facebookAdsToolboxConfig.popupOrigin){if(!urlFromSameDomain(e,window.facebookAdsToolboxConfig.popupOrigin))return;window.facebookAdsToolboxConfig.popupOrigin=e}switch(o.data.type){case"reset":delete_all_settings(function(e){e&&o.data.params?"Settings Deleted"===e?window.sendToFacebook("ack reset",o.data.params):(console.log(e),alert(e)):console.log("Got no response from delete_all_settings")},function(e){console.error(e)});break;case"get dia settings":window.sendToFacebook("dia settings",window.diaConfig);break;case"set catalog":setCatalog(o.data);break;case"set feed migrated":setFeedMigrated(o.data);break;case"set pixel":setPixel(o.data);break;case"gen feed":genFeed(o.data);break;case"set page access token":window.sendToFacebook("ack set page access token",o.data.params);break;case"set page":setPage(o.data);break;case"set merchant settings":setMerchantSettings(o.data),save_settings(function(e){console.log(e),e&&!0===e.success?(settings.pixel_id&&window.sendToFacebook("ack set pixel",o.data.params),settings.page_id&&window.sendToFacebook("ack set page",o.data.params),settings.external_merchant_settings_id&&(window.sendToFacebook("ack set merchant settings",o.data.params),jQuery("#fbsetup").hide(),jQuery("#integration-settings").show(),jQuery(".woocommerce-save-button").show())):(window.sendToFacebook("fail save_settings",e),console.log("Fail response on save_settings"))},function(e){console.log("Ajax error while saving settings:"+JSON.stringify(e)),window.sendToFacebook("fail save_settings_ajax",JSON.stringify(e))});break;case"set msger chat":setMsgerChatSetup(o.data.params),save_settings_for_plugin(function(e){window.sendToFacebook("ack msger chat",o.data)},function(e){window.sendToFacebook("fail msger chat",o.data)})}}function setPage(e){if(!e.params.hasOwnProperty("page_id"))return console.error("Facebook Extension Error: page ID not received",e.params),void window.sendToFacebook("fail set page",e.params);settings.page_id=e.params.page_id,jQuery("#woocommerce_facebookcommerce_facebook_page_id").val(settings.page_id)}function urlFromSameDomain(e,o){if(!e.startsWith("http")||!o.startsWith("http"))return!1;var n=parseURL(e),t=parseURL(o),s=n.host.replace(/^\w+\./,"www."),i=t.host.replace(/^\w+\./,"www.");return n.protocol===t.protocol&&s===i}function parseURL(e){var o=document.createElement("a");return o.href=e,o}function check_background_processor_status(){window.facebookAdsToolboxConfig.feed.hasClientSideFeedUpload||(clearInterval(window.fb_pings),window.fb_pings=setInterval(function(){console.log("Pinging queue..."),check_queues()},1e4))}function ping_feed_status_queue(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:0;clearInterval(window.fb_feed_pings),window.fb_feed_pings=setInterval(function(){console.log("Pinging feed uploading queue..."),check_feed_upload_queue(e)},3e4*(1<<e))}function product_sync_complete(e){sync_not_in_progress(),e.empty().hide(),clearInterval(window.fb_pings)}function check_queues(){ajax("ajax_fb_background_check_queue",{request_time:(new Date).getTime(),_ajax_nonce:wc_facebook_settings_jsx.nonce},function(e){if(window.feed_upload)clearInterval(window.fb_pings);else{var o=jQuery("#sync_progress"),n=parse_response_check_connection(e);if(n){if(fb_sync_no_response_count=0,n){n.background||(console.log("No background sync found, disabling pings"),clearInterval(window.fb_pings));var t=!!n.processing,s=n.remaining;if(t){var i="";i=1===s?facebook_for_woocommerce_settings_sync.i18n.sync_remaining_items_singular:facebook_for_woocommerce_settings_sync.i18n.sync_remaining_items_plural,o.show().html(i.replace("{count}",s)),0===s&&product_sync_complete(o)}else{if(window.fb_sync_start_time&&n.request_time){var a=new Date(parseInt(n.request_time));if(window.fb_sync_start_time>a)return void console.log("OLD PING")}0===s&&product_sync_complete(o)}}}else 5<fb_sync_no_response_count++&&clearInterval(window.fb_pings)}})}function parse_response_check_connection(e){if(e){console.log(e);var o=e.substring(e.indexOf("{"));return(o=JSON.parse(o)).connected||window.fb_connected?o:(not_connected(),null)}return null}function check_feed_upload_queue(t){ajax("ajax_check_feed_upload_status",{_ajax_nonce:wc_facebook_settings_jsx.nonce},function(e){var o=jQuery("#sync_progress"),n=parse_response_check_connection(e);if(clearInterval(window.fb_feed_pings),n)switch(n.status){case"complete":window.feed_upload=!1,window.is_test?display_test_result():product_sync_complete(o);break;case"in progress":o.show().html(facebook_for_woocommerce_settings_sync.i18n.sync_in_progress),ping_feed_status_queue(t+1);break;default:jQuery("#woocommerce-facebook-settings-manage-connection, #woocommerce-facebook-settings-sync-products").css("pointer-events","auto"),jQuery("#sync_progress").show().html('<span style="color: #DC3232">'+facebook_for_woocommerce_settings_sync.i18n.feed_upload_error+"</span>"),window.feed_upload=!1,window.is_test&&display_test_result()}})}function display_test_result(){ajax("ajax_display_test_result",{_ajax_nonce:wc_facebook_settings_jsx.nonce},function(e){var o=jQuery("#sync_progress"),n=document.querySelector("#sync_complete"),t=parse_response_check_connection(e);if(t)switch(t.pass){case"true":sync_not_in_progress(),n&&(n.style.display="",n.innerHTML=facebook_for_woocommerce_settings_sync.i18n.integration_test_sucessful),o.empty().hide(),window.is_test=!1;break;case"in progress":o.show().html(facebook_for_woocommerce_settings_sync.i18n.integration_test_in_progress),ping_feed_status_queue();break;default:window.debug_info=t.debug_info+"<br/>"+t.stack_trace,n&&(n.style.display="",n.innerHTML=facebook_for_woocommerce_settings_sync.i18n.integration_test_failed),o.empty().hide(),document.querySelector("#debug_info")&&(document.querySelector("#debug_info").style.display=""),window.is_test=!1}})}function show_debug_info(){var e=document.querySelector("#stack_trace");e&&(e.innerHTML=window.debug_info),document.querySelector("#debug_info")&&(document.querySelector("#debug_info").style.display="none"),window.debug_info=""}function fbe_init_nux_messages(){var r=window.jQuery;r(function(){r.each(r(".nux-message"),function(e,o){var n=r(o),t=n.data("target"),s=r("#"+t),i=s.position(),a=s.height()/2,c=s.outerWidth();n.css({top:Math.ceil(i.top+a)+"px",left:Math.ceil(i.left+c)+"px",display:"block"}),r(".nux-message-close-btn",n).click(function(){r(o).hide()})})})}function saveAutoSyncSchedule(){var e=document.getElementsByClassName("autosyncCheck")[0].checked,o=document.getElementsByClassName("autosyncTime")[0],n=(document.getElementsByClassName("autosyncSaveButton")[0],document.getElementsByClassName("autosyncSavedNotice")[0]);e?(o.removeAttribute("disabled"),n.style.transition="",n.style.opacity=1,setTimeout(function(){n.style.opacity=0,n.style.transition="opacity 5s"},3e3)):o.setAttribute("disabled",!0),ajax("ajax_schedule_force_resync",{enabled:e?1:0,time:o.value,_ajax_nonce:wc_facebook_settings_jsx.nonce})}function syncShortDescription(){var e=document.getElementsByClassName("syncShortDescription")[0].checked;ajax("ajax_update_fb_option",{option:"fb_sync_short_description",option_value:e?1:0,_ajax_nonce:wc_facebook_settings_jsx.nonce},null,function(){document.getElementsByClassName("syncShortDescription")[0].checked=!e,console.log("Failed to sync Short Description")})}addAnEventListener(window,"message",iFrameListener),jQuery(document).ready(function(e){e(".notice .wc-facebook-manage-connection").click(function(e){e.preventDefault(),facebookConfig()}),e("#woocommerce-facebook-settings-sync-products").click(function(e){e.preventDefault(),sync_confirm()})});
|
changelog.txt
CHANGED
@@ -1,5 +1,16 @@
|
|
1 |
*** Facebook for WooCommerce Changelog ***
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
2020.03.17 - version 1.10.2
|
4 |
* Tweak - Add a setting to easily enable debug logging
|
5 |
* Tweak - Allow third party plugins and themes to track an add-to-cart event on added_to_cart JS event
|
1 |
*** Facebook for WooCommerce Changelog ***
|
2 |
|
3 |
+
2020.04.23 - version 1.11.0
|
4 |
+
* Tweak - Sync products using Facebook's feed pull method
|
5 |
+
* Fix - When filtering products by sync enabled status, make sure variable products with sync disabled status do not show up in results
|
6 |
+
* Fix - Make sure that the Facebook sync enabled and catalog visibility columns are properly displayed on narrow screen sizes on some browsers
|
7 |
+
* Fix - Do not show a confirmation modal when saving a variable product that was previously synced but belongs now to a term excluded from sync
|
8 |
+
* Fix - Ensure variable products excluded from sync are not synced in Facebook
|
9 |
+
* Fix - Trigger a modal prompt when attempting to enable sync for variations of a variable product that belongs to a term excluded from sync
|
10 |
+
* Fix - Address potential PHP warnings in the product feed with non-standard product variations introduced by third party plugins
|
11 |
+
* Fix - Fix a JavaScript error triggered on the settings page while trying to excluded terms from sync
|
12 |
+
* Fix - Fix a JavaScript error triggered when saving a product and using checkboxes for tags
|
13 |
+
|
14 |
2020.03.17 - version 1.10.2
|
15 |
* Tweak - Add a setting to easily enable debug logging
|
16 |
* Tweak - Allow third party plugins and themes to track an add-to-cart event on added_to_cart JS event
|
class-wc-facebookcommerce.php
CHANGED
@@ -19,7 +19,7 @@ if ( ! class_exists( 'WC_Facebookcommerce' ) ) :
|
|
19 |
|
20 |
|
21 |
/** @var string the plugin version */
|
22 |
-
const VERSION = '1.
|
23 |
|
24 |
/** @var string for backwards compatibility TODO: remove this in v2.0.0 {CW 2020-02-06} */
|
25 |
const PLUGIN_VERSION = self::VERSION;
|
@@ -46,6 +46,9 @@ if ( ! class_exists( 'WC_Facebookcommerce' ) ) :
|
|
46 |
/** @var \SkyVerge\WooCommerce\Facebook\AJAX Ajax handler instance */
|
47 |
private $ajax;
|
48 |
|
|
|
|
|
|
|
49 |
|
50 |
/**
|
51 |
* Constructs the plugin.
|
@@ -76,14 +79,18 @@ if ( ! class_exists( 'WC_Facebookcommerce' ) ) :
|
|
76 |
if ( \WC_Facebookcommerce_Utils::isWoocommerceIntegration() ) {
|
77 |
|
78 |
if ( ! defined( 'WOOCOMMERCE_FACEBOOK_PLUGIN_SETTINGS_URL' ) ) {
|
79 |
-
define( 'WOOCOMMERCE_FACEBOOK_PLUGIN_SETTINGS_URL',
|
80 |
}
|
81 |
|
82 |
include_once 'facebook-commerce.php';
|
83 |
|
84 |
require_once __DIR__ . '/includes/Products.php';
|
|
|
|
|
85 |
require_once __DIR__ . '/facebook-commerce-messenger-chat.php';
|
86 |
|
|
|
|
|
87 |
if ( is_ajax() ) {
|
88 |
|
89 |
require_once __DIR__ . '/includes/AJAX.php';
|
@@ -112,6 +119,51 @@ if ( ! class_exists( 'WC_Facebookcommerce' ) ) :
|
|
112 |
}
|
113 |
|
114 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
/**
|
116 |
* Adds a Facebook integration to WooCommerce.
|
117 |
*
|
@@ -168,6 +220,19 @@ if ( ! class_exists( 'WC_Facebookcommerce' ) ) :
|
|
168 |
}
|
169 |
|
170 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
171 |
/**
|
172 |
* Gets the integration instance.
|
173 |
*
|
19 |
|
20 |
|
21 |
/** @var string the plugin version */
|
22 |
+
const VERSION = '1.11.0';
|
23 |
|
24 |
/** @var string for backwards compatibility TODO: remove this in v2.0.0 {CW 2020-02-06} */
|
25 |
const PLUGIN_VERSION = self::VERSION;
|
46 |
/** @var \SkyVerge\WooCommerce\Facebook\AJAX Ajax handler instance */
|
47 |
private $ajax;
|
48 |
|
49 |
+
/** @var \SkyVerge\WooCommerce\Facebook\Products\Feed product feed handler */
|
50 |
+
private $product_feed;
|
51 |
+
|
52 |
|
53 |
/**
|
54 |
* Constructs the plugin.
|
79 |
if ( \WC_Facebookcommerce_Utils::isWoocommerceIntegration() ) {
|
80 |
|
81 |
if ( ! defined( 'WOOCOMMERCE_FACEBOOK_PLUGIN_SETTINGS_URL' ) ) {
|
82 |
+
define( 'WOOCOMMERCE_FACEBOOK_PLUGIN_SETTINGS_URL', admin_url( 'admin.php?page=wc-settings&tab=integration§ion=facebookcommerce' ) );
|
83 |
}
|
84 |
|
85 |
include_once 'facebook-commerce.php';
|
86 |
|
87 |
require_once __DIR__ . '/includes/Products.php';
|
88 |
+
require_once __DIR__ . '/includes/Products/Feed.php';
|
89 |
+
require_once __DIR__ . '/includes/fbproductfeed.php';
|
90 |
require_once __DIR__ . '/facebook-commerce-messenger-chat.php';
|
91 |
|
92 |
+
$this->product_feed = new \SkyVerge\WooCommerce\Facebook\Products\Feed();
|
93 |
+
|
94 |
if ( is_ajax() ) {
|
95 |
|
96 |
require_once __DIR__ . '/includes/AJAX.php';
|
119 |
}
|
120 |
|
121 |
|
122 |
+
/**
|
123 |
+
* Adds the plugin admin notices.
|
124 |
+
*
|
125 |
+
* @since 1.11.0
|
126 |
+
*/
|
127 |
+
public function add_admin_notices() {
|
128 |
+
|
129 |
+
parent::add_admin_notices();
|
130 |
+
|
131 |
+
$integration = $this->get_integration();
|
132 |
+
|
133 |
+
// if the feed hasn't been migrated to FBE 1.5 and the access token is bad, display a notice
|
134 |
+
if ( $integration && $integration->is_configured() && ! $integration->is_feed_migrated() && ! $integration->get_page_name() ) {
|
135 |
+
|
136 |
+
$docs_url = 'https://docs.woocommerce.com/document/facebook-for-woocommerce/#faq-security';
|
137 |
+
|
138 |
+
if ( $this->is_plugin_settings() ) {
|
139 |
+
|
140 |
+
$message = sprintf(
|
141 |
+
/* translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s - <a> tag, %4$s - </a> tag, %5$s - <a> tag, %6$s - </a> tag */
|
142 |
+
__( '%1$sHeads up!%2$s Facebook for WooCommerce is migrating to a more secure connection experience. Please %3$sclick here%4$s and go to %1$sAdvanced Options%2$s > %1$sReconnect Catalog%2$s to securely reconnect. %5$sLearn more%6$s.', 'facebook-for-woocommerce' ),
|
143 |
+
'<strong>', '</strong>',
|
144 |
+
'<a href="#" class="wc-facebook-manage-connection">', '</a>',
|
145 |
+
'<a href="' . esc_url( $docs_url ) . '" target="_blank">', '</a>'
|
146 |
+
);
|
147 |
+
|
148 |
+
} else {
|
149 |
+
|
150 |
+
$message = sprintf(
|
151 |
+
/* translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s - <a> tag, %4$s - </a> tag, %5$s - <a> tag, %6$s - </a> tag */
|
152 |
+
__( '%1$sHeads up!%2$s Facebook for WooCommerce is migrating to a more secure connection experience. Please %3$sclick here%4$s and go to %1$sManage Connection%2$s > %1$sAdvanced Options%2$s > %1$sReconnect Catalog%2$s to securely reconnect. %5$sLearn more%6$s.', 'facebook-for-woocommerce' ),
|
153 |
+
'<strong>', '</strong>',
|
154 |
+
'<a href="' . esc_url( $this->get_settings_url() ) . '">', '</a>',
|
155 |
+
'<a href="' . esc_url( $docs_url ) . '" target="_blank">', '</a>'
|
156 |
+
);
|
157 |
+
}
|
158 |
+
|
159 |
+
$this->get_admin_notice_handler()->add_admin_notice( $message, self::PLUGIN_ID . '_migrate_to_v1_5', [
|
160 |
+
'dismissible' => false,
|
161 |
+
'notice_class' => 'notice-info wc-facebook-migrate-notice',
|
162 |
+
] );
|
163 |
+
}
|
164 |
+
}
|
165 |
+
|
166 |
+
|
167 |
/**
|
168 |
* Adds a Facebook integration to WooCommerce.
|
169 |
*
|
220 |
}
|
221 |
|
222 |
|
223 |
+
/**
|
224 |
+
* Gets the product feed handler.
|
225 |
+
*
|
226 |
+
* @since 1.11.0
|
227 |
+
*
|
228 |
+
* @return \SkyVerge\WooCommerce\Facebook\Products\Feed
|
229 |
+
*/
|
230 |
+
public function get_product_feed_handler() {
|
231 |
+
|
232 |
+
return $this->product_feed;
|
233 |
+
}
|
234 |
+
|
235 |
+
|
236 |
/**
|
237 |
* Gets the integration instance.
|
238 |
*
|
facebook-commerce-events-tracker.php
CHANGED
@@ -51,8 +51,8 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
51 |
array( $this, 'inject_search_event' )
|
52 |
);
|
53 |
|
54 |
-
// AddToCart
|
55 |
-
add_action( 'woocommerce_add_to_cart',
|
56 |
// AddToCart while AJAX is enabled
|
57 |
add_action( 'woocommerce_ajax_added_to_cart', [ $this, 'add_filter_for_add_to_cart_fragments' ] );
|
58 |
// AddToCart while using redirect to cart page
|
@@ -62,26 +62,14 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
62 |
add_action( 'woocommerce_after_cart', [ $this, 'inject_add_to_cart_redirect_event' ], 10, 2 );
|
63 |
}
|
64 |
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
);
|
69 |
-
add_action(
|
70 |
-
'woocommerce_thankyou',
|
71 |
-
array( $this, 'inject_gateway_purchase_event' ),
|
72 |
-
self::FB_PRIORITY_HIGH
|
73 |
-
);
|
74 |
-
add_action(
|
75 |
-
'woocommerce_payment_complete',
|
76 |
-
array( $this, 'inject_purchase_event' ),
|
77 |
-
self::FB_PRIORITY_HIGH
|
78 |
-
);
|
79 |
-
add_action(
|
80 |
-
'wpcf7_contact_form',
|
81 |
-
array( $this, 'inject_lead_event_hook' ),
|
82 |
-
self::FB_PRIORITY_LOW
|
83 |
-
);
|
84 |
|
|
|
|
|
85 |
}
|
86 |
|
87 |
public function apply_filters() {
|
@@ -177,7 +165,7 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
177 |
}
|
178 |
|
179 |
if ( ! is_admin() && is_search() && get_search_query() !== '' ) {
|
180 |
-
if ( $this->pixel->
|
181 |
return;
|
182 |
}
|
183 |
|
@@ -391,13 +379,15 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
391 |
* @since 1.10.2
|
392 |
*
|
393 |
* @param string $redirect URL redirecting to (usually cart)
|
394 |
-
* @param
|
395 |
* @return string
|
396 |
*/
|
397 |
-
public function set_last_product_added_to_cart_upon_redirect( $redirect, $product ) {
|
398 |
|
399 |
if ( $product instanceof \WC_Product ) {
|
400 |
WC()->session->set( 'facebook_for_woocommerce_last_product_added_to_cart', $product->get_id() );
|
|
|
|
|
401 |
}
|
402 |
|
403 |
return $redirect;
|
@@ -411,9 +401,14 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
411 |
*
|
412 |
* @since 1.10.2
|
413 |
*
|
414 |
-
* @param int $product_id the ID of the product just added to the cart
|
415 |
*/
|
416 |
-
public function set_last_product_added_to_cart_upon_ajax_redirect( $product_id ) {
|
|
|
|
|
|
|
|
|
|
|
417 |
|
418 |
$product = wc_get_product( $product_id );
|
419 |
|
@@ -446,11 +441,13 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
446 |
|
447 |
|
448 |
/**
|
449 |
-
* Triggers InitiateCheckout
|
|
|
|
|
450 |
*/
|
451 |
public function inject_initiate_checkout_event() {
|
452 |
|
453 |
-
if ( ! self::$isEnabled || $this->pixel->
|
454 |
return;
|
455 |
}
|
456 |
|
@@ -465,20 +462,29 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
465 |
|
466 |
|
467 |
/**
|
468 |
-
* Triggers Purchase
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
469 |
*
|
470 |
* @param int $order_id order identifier
|
471 |
*/
|
472 |
public function inject_purchase_event( $order_id ) {
|
473 |
|
474 |
-
if ( ! self::$isEnabled || $this->pixel->
|
475 |
return;
|
476 |
}
|
477 |
|
478 |
-
$
|
479 |
-
|
480 |
-
$order = new \WC_Order( $order_id );
|
481 |
$content_type = 'product';
|
|
|
|
|
482 |
$product_ids = [ [] ];
|
483 |
|
484 |
foreach ( $order->get_items() as $item ) {
|
@@ -490,60 +496,80 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
490 |
if ( 'product_group' !== $content_type && $product->is_type( 'variable' ) ) {
|
491 |
$content_type = 'product_group';
|
492 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
493 |
}
|
494 |
}
|
495 |
|
496 |
-
$product_ids = wp_json_encode( array_merge( ... $product_ids ) );
|
497 |
-
|
498 |
$this->pixel->inject_event( 'Purchase', [
|
499 |
-
'num_items' => $
|
500 |
-
'content_ids' => $product_ids,
|
|
|
501 |
'content_type' => $content_type,
|
502 |
'value' => $order->get_total(),
|
503 |
'currency' => get_woocommerce_currency(),
|
504 |
] );
|
|
|
|
|
505 |
}
|
506 |
|
507 |
|
508 |
/**
|
509 |
-
* Triggers Subscribe
|
510 |
-
*
|
|
|
|
|
|
|
|
|
|
|
511 |
*/
|
512 |
public function inject_subscribe_event( $order_id ) {
|
513 |
-
|
|
|
514 |
return;
|
515 |
}
|
516 |
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
);
|
528 |
}
|
529 |
}
|
530 |
|
|
|
531 |
/**
|
532 |
-
* Triggers Purchase
|
533 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
534 |
*/
|
535 |
public function inject_gateway_purchase_event( $order_id ) {
|
536 |
-
if ( ! self::$isEnabled ||
|
537 |
-
$this->pixel->check_last_event( 'Purchase' ) ) {
|
538 |
-
return;
|
539 |
-
}
|
540 |
|
541 |
-
|
542 |
-
|
543 |
$this->inject_purchase_event( $order_id );
|
544 |
-
$this->inject_subscribe_event( $order_id );
|
545 |
}
|
546 |
|
|
|
547 |
/** Contact Form 7 Support **/
|
548 |
public function inject_lead_event_hook() {
|
549 |
add_action( 'wp_footer', array( $this, 'inject_lead_event' ), 11 );
|
51 |
array( $this, 'inject_search_event' )
|
52 |
);
|
53 |
|
54 |
+
// AddToCart events
|
55 |
+
add_action( 'woocommerce_add_to_cart', [ $this, 'inject_add_to_cart_event' ], 40, 4 );
|
56 |
// AddToCart while AJAX is enabled
|
57 |
add_action( 'woocommerce_ajax_added_to_cart', [ $this, 'add_filter_for_add_to_cart_fragments' ] );
|
58 |
// AddToCart while using redirect to cart page
|
62 |
add_action( 'woocommerce_after_cart', [ $this, 'inject_add_to_cart_redirect_event' ], 10, 2 );
|
63 |
}
|
64 |
|
65 |
+
// InitiateCheckout events
|
66 |
+
add_action( 'woocommerce_after_checkout_form', [ $this, 'inject_initiate_checkout_event' ] );
|
67 |
+
// Purchase and Subscribe events
|
68 |
+
add_action( 'woocommerce_thankyou', [ $this, 'inject_purchase_event' ], 40 );
|
69 |
+
add_action( 'woocommerce_payment_complete', [ $this, 'inject_purchase_event' ], 40 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
|
71 |
+
// TODO move this in some 3rd party plugin integrations handler at some point {FN 2020-03-20}
|
72 |
+
add_action( 'wpcf7_contact_form', [ $this, 'inject_lead_event_hook' ], self::FB_PRIORITY_LOW );
|
73 |
}
|
74 |
|
75 |
public function apply_filters() {
|
165 |
}
|
166 |
|
167 |
if ( ! is_admin() && is_search() && get_search_query() !== '' ) {
|
168 |
+
if ( $this->pixel->is_last_event( 'Search' ) ) {
|
169 |
return;
|
170 |
}
|
171 |
|
379 |
* @since 1.10.2
|
380 |
*
|
381 |
* @param string $redirect URL redirecting to (usually cart)
|
382 |
+
* @param null|\WC_Product $product the product just added to the cart
|
383 |
* @return string
|
384 |
*/
|
385 |
+
public function set_last_product_added_to_cart_upon_redirect( $redirect, $product = null ) {
|
386 |
|
387 |
if ( $product instanceof \WC_Product ) {
|
388 |
WC()->session->set( 'facebook_for_woocommerce_last_product_added_to_cart', $product->get_id() );
|
389 |
+
} else {
|
390 |
+
facebook_for_woocommerce()->log( 'Cannot record AddToCart event because the product cannot be determined. Backtrace: ' . print_r( wp_debug_backtrace_summary(), true ) );
|
391 |
}
|
392 |
|
393 |
return $redirect;
|
401 |
*
|
402 |
* @since 1.10.2
|
403 |
*
|
404 |
+
* @param null|int $product_id the ID of the product just added to the cart
|
405 |
*/
|
406 |
+
public function set_last_product_added_to_cart_upon_ajax_redirect( $product_id = null ) {
|
407 |
+
|
408 |
+
if ( ! $product_id ) {
|
409 |
+
facebook_for_woocommerce()->log( 'Cannot record AddToCart event because the product cannot be determined. Backtrace: ' . print_r( wp_debug_backtrace_summary(), true ) );
|
410 |
+
return;
|
411 |
+
}
|
412 |
|
413 |
$product = wc_get_product( $product_id );
|
414 |
|
441 |
|
442 |
|
443 |
/**
|
444 |
+
* Triggers an InitiateCheckout event when customer reaches checkout page.
|
445 |
+
*
|
446 |
+
* @internal
|
447 |
*/
|
448 |
public function inject_initiate_checkout_event() {
|
449 |
|
450 |
+
if ( ! self::$isEnabled || $this->pixel->is_last_event( 'InitiateCheckout' ) ) {
|
451 |
return;
|
452 |
}
|
453 |
|
462 |
|
463 |
|
464 |
/**
|
465 |
+
* Triggers a Purchase event when checkout is completed.
|
466 |
+
*
|
467 |
+
* This may happen either when:
|
468 |
+
* - WooCommerce signals a payment transaction complete (most gateways)
|
469 |
+
* - Customer reaches Thank You page skipping payment (for gateways that do not require payment, e.g. Cheque, BACS, Cash on delivery...)
|
470 |
+
*
|
471 |
+
* The method checks if the event was not triggered already avoiding a duplicate.
|
472 |
+
* Finally, if the order contains subscriptions, it will also track an associated Subscription event.
|
473 |
+
*
|
474 |
+
* @internal
|
475 |
*
|
476 |
* @param int $order_id order identifier
|
477 |
*/
|
478 |
public function inject_purchase_event( $order_id ) {
|
479 |
|
480 |
+
if ( ! self::$isEnabled || $this->pixel->is_last_event( 'Purchase' ) ) {
|
481 |
return;
|
482 |
}
|
483 |
|
484 |
+
$order = wc_get_order( $order_id );
|
|
|
|
|
485 |
$content_type = 'product';
|
486 |
+
$num_items = 0;
|
487 |
+
$contents = [];
|
488 |
$product_ids = [ [] ];
|
489 |
|
490 |
foreach ( $order->get_items() as $item ) {
|
496 |
if ( 'product_group' !== $content_type && $product->is_type( 'variable' ) ) {
|
497 |
$content_type = 'product_group';
|
498 |
}
|
499 |
+
|
500 |
+
$quantity = $item->get_quantity();
|
501 |
+
$content = new \stdClass();
|
502 |
+
|
503 |
+
$content->id = \WC_Facebookcommerce_Utils::get_fb_retailer_id( $product );
|
504 |
+
$content->quantity = $quantity;
|
505 |
+
|
506 |
+
$contents[] = $content;
|
507 |
+
$num_items += $quantity;
|
508 |
}
|
509 |
}
|
510 |
|
|
|
|
|
511 |
$this->pixel->inject_event( 'Purchase', [
|
512 |
+
'num_items' => $num_items,
|
513 |
+
'content_ids' => wp_json_encode( array_merge( ... $product_ids ) ),
|
514 |
+
'contents' => wp_json_encode( $contents ),
|
515 |
'content_type' => $content_type,
|
516 |
'value' => $order->get_total(),
|
517 |
'currency' => get_woocommerce_currency(),
|
518 |
] );
|
519 |
+
|
520 |
+
$this->inject_subscribe_event( $order_id );
|
521 |
}
|
522 |
|
523 |
|
524 |
/**
|
525 |
+
* Triggers a Subscribe event when a given order contains subscription products.
|
526 |
+
*
|
527 |
+
* @see \WC_Facebookcommerce_EventsTracker::inject_purchase_event()
|
528 |
+
*
|
529 |
+
* @internal
|
530 |
+
*
|
531 |
+
* @param int $order_id order identifier
|
532 |
*/
|
533 |
public function inject_subscribe_event( $order_id ) {
|
534 |
+
|
535 |
+
if ( ! self::$isEnabled || ! function_exists( 'wcs_get_subscriptions_for_order' ) || $this->pixel->is_last_event( 'Subscribe' ) ) {
|
536 |
return;
|
537 |
}
|
538 |
|
539 |
+
foreach ( wcs_get_subscriptions_for_order( $order_id ) as $subscription ) {
|
540 |
+
|
541 |
+
// TODO consider 'StartTrial' event for free trial Subscriptions, which is the same as here (minus sign_up_fee) and tracks "when a person starts a free trial of a product or service" {FN 2020-03-20}
|
542 |
+
|
543 |
+
// TODO consider including (int|float) 'predicted_ltv': "Predicted lifetime value of a subscriber as defined by the advertiser and expressed as an exact value." {FN 2020-03-20}
|
544 |
+
$this->pixel->inject_event( 'Subscribe', [
|
545 |
+
'sign_up_fee' => $subscription->get_sign_up_fee(),
|
546 |
+
'value' => $subscription->get_total(),
|
547 |
+
'currency' => get_woocommerce_currency(),
|
548 |
+
] );
|
|
|
549 |
}
|
550 |
}
|
551 |
|
552 |
+
|
553 |
/**
|
554 |
+
* Triggers a Purchase event.
|
555 |
+
*
|
556 |
+
* Duplicate of {@see \WC_Facebookcommerce_EventsTracker::inject_purchase_event()}
|
557 |
+
*
|
558 |
+
* TODO remove this deprecated method by version 2.0.0 or by March 2020 {FN 2020-03-20}
|
559 |
+
*
|
560 |
+
* @internal
|
561 |
+
* @deprecated since 1.11.0
|
562 |
+
*
|
563 |
+
* @param int $order_id order identifier
|
564 |
*/
|
565 |
public function inject_gateway_purchase_event( $order_id ) {
|
|
|
|
|
|
|
|
|
566 |
|
567 |
+
wc_deprecated_function( __METHOD__, '1.11.0', __CLASS__ . '::inject_purchase_event()' );
|
568 |
+
|
569 |
$this->inject_purchase_event( $order_id );
|
|
|
570 |
}
|
571 |
|
572 |
+
|
573 |
/** Contact Form 7 Support **/
|
574 |
public function inject_lead_event_hook() {
|
575 |
add_action( 'wp_footer', array( $this, 'inject_lead_event' ), 11 );
|
facebook-commerce-pixel-event.php
CHANGED
@@ -184,13 +184,37 @@ if ( ! class_exists( 'WC_Facebookcommerce_Pixel' ) ) :
|
|
184 |
|
185 |
|
186 |
/**
|
187 |
-
*
|
|
|
|
|
|
|
|
|
|
|
188 |
*/
|
189 |
-
public function
|
|
|
190 |
return $event_name === $this->last_event;
|
191 |
}
|
192 |
|
193 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
/**
|
195 |
* Gets the JavaScript code to track an event.
|
196 |
*
|
184 |
|
185 |
|
186 |
/**
|
187 |
+
* Determines if the last event in the current thread matches a given event.
|
188 |
+
*
|
189 |
+
* @since 1.11.0
|
190 |
+
*
|
191 |
+
* @param string $event_name
|
192 |
+
* @return bool
|
193 |
*/
|
194 |
+
public function is_last_event( $event_name ) {
|
195 |
+
|
196 |
return $event_name === $this->last_event;
|
197 |
}
|
198 |
|
199 |
|
200 |
+
/**
|
201 |
+
* Determines if the last event in the current thread matches a given event.
|
202 |
+
*
|
203 |
+
* TODO remove this deprecated method by March 2020 or version 2.0.0 {FN 2020-03-25}
|
204 |
+
*
|
205 |
+
* @deprecated since 1.11.0
|
206 |
+
*
|
207 |
+
* @param string $event_name
|
208 |
+
* @return bool
|
209 |
+
*/
|
210 |
+
public function check_last_event( $event_name ) {
|
211 |
+
|
212 |
+
wc_deprecated_function( __METHOD__, '1.11.0', __CLASS__ . '::has_last_event()' );
|
213 |
+
|
214 |
+
return $this->is_last_event( $event_name );
|
215 |
+
}
|
216 |
+
|
217 |
+
|
218 |
/**
|
219 |
* Gets the JavaScript code to track an event.
|
220 |
*
|
facebook-commerce.php
CHANGED
@@ -10,6 +10,7 @@
|
|
10 |
|
11 |
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
12 |
use SkyVerge\WooCommerce\Facebook\Products;
|
|
|
13 |
|
14 |
if ( ! defined( 'ABSPATH' ) ) {
|
15 |
exit; // Exit if accessed directly
|
@@ -34,6 +35,9 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
34 |
/** @var string the WordPress option name where the feed ID is stored */
|
35 |
const OPTION_FEED_ID = 'wc_facebook_feed_id';
|
36 |
|
|
|
|
|
|
|
37 |
/** @var string the WordPress option name where the JS SDK version is stored */
|
38 |
const OPTION_JS_SDK_VERSION = 'wc_facebook_js_sdk_version';
|
39 |
|
@@ -101,12 +105,18 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
101 |
/** @var string|null the configured feed ID */
|
102 |
public $feed_id;
|
103 |
|
|
|
|
|
|
|
104 |
/** @var string|null the configured pixel install time */
|
105 |
public $pixel_install_time;
|
106 |
|
107 |
/** @var string|null the configured JS SDK version */
|
108 |
private $js_sdk_version;
|
109 |
|
|
|
|
|
|
|
110 |
|
111 |
/** Legacy properties *********************************************************************************************/
|
112 |
|
@@ -324,12 +334,15 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
324 |
self::FB_PRIORITY_MID
|
325 |
);
|
326 |
|
|
|
|
|
|
|
|
|
|
|
|
|
327 |
// Only load product processing hooks if we have completed setup.
|
328 |
if ( $this->get_page_access_token() && $this->get_product_catalog_id() ) {
|
329 |
|
330 |
-
// on_product_save() must run with priority larger than 20 to make sure WooCommerce has a chance to save the submitted product information
|
331 |
-
add_action( 'woocommerce_process_product_meta', [ $this, 'on_product_save' ], 40 );
|
332 |
-
|
333 |
add_action(
|
334 |
'woocommerce_product_quick_edit_save',
|
335 |
array( $this, 'on_quick_and_bulk_edit_save' ),
|
@@ -344,6 +357,8 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
344 |
1 // Args passed to on_quick_and_bulk_edit_save ('product')
|
345 |
);
|
346 |
|
|
|
|
|
347 |
add_action(
|
348 |
'before_delete_post',
|
349 |
array( $this, 'on_product_delete' ),
|
@@ -375,11 +390,6 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
375 |
array( $this, 'ajax_delete_fb_product' )
|
376 |
);
|
377 |
|
378 |
-
add_filter(
|
379 |
-
'woocommerce_duplicate_product_exclude_meta',
|
380 |
-
array( $this, 'fb_duplicate_product_reset_meta' )
|
381 |
-
);
|
382 |
-
|
383 |
add_action(
|
384 |
'pmxi_after_xml_import',
|
385 |
array( $this, 'wp_all_import_compat' )
|
@@ -407,6 +417,9 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
407 |
// Must be outside of admin for cron to schedule correctly.
|
408 |
add_action( 'sync_all_fb_products_using_feed', [ $this, 'handle_scheduled_resync_action' ], self::FB_PRIORITY_MID );
|
409 |
|
|
|
|
|
|
|
410 |
if ( $this->get_facebook_pixel_id() ) {
|
411 |
$user_info = WC_Facebookcommerce_Utils::get_user_info( $this->is_advanced_matching_enabled() );
|
412 |
$this->events_tracker = new WC_Facebookcommerce_EventsTracker( $user_info );
|
@@ -620,6 +633,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
620 |
}
|
621 |
|
622 |
?>
|
|
|
623 |
<?php echo esc_html__( 'Visible:', 'facebook-for-woocommerce' ); ?>
|
624 |
<input name="<?php echo esc_attr( Products::VISIBILITY_META_KEY ); ?>"
|
625 |
type="checkbox"
|
@@ -627,6 +641,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
627 |
<?php echo checked( ! $woo_product->woo_product instanceof \WC_Product || Products::is_product_visible( $woo_product->woo_product ) ); ?>/>
|
628 |
|
629 |
<p/>
|
|
|
630 |
<input name="is_product_page" type="hidden" value="1"/>
|
631 |
|
632 |
<p/>
|
@@ -736,14 +751,16 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
736 |
},
|
737 |
feed: {
|
738 |
totalVisibleProducts: '<?php echo esc_js( $this->get_product_count() ); ?>',
|
739 |
-
hasClientSideFeedUpload: '<?php echo esc_js( ! ! $this->get_feed_id() ); ?>'
|
|
|
|
|
740 |
},
|
741 |
feedPrepared: {
|
742 |
-
feedUrl: '',
|
743 |
feedPingUrl: '',
|
|
|
744 |
samples: <?php echo $this->get_sample_product_feed(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
745 |
},
|
746 |
-
tokenExpired: '<?php echo $this->get_page_access_token() && ! $this->get_page_name(); ?>',
|
747 |
excludedCategoryIDs: <?php echo json_encode( $this->get_excluded_product_category_ids() ); ?>,
|
748 |
excludedTagIDs: <?php echo json_encode( $this->get_excluded_product_tag_ids() ); ?>,
|
749 |
messengerGreetingMaxCharacters: <?php echo esc_js( $this->get_messenger_greeting_max_characters() ); ?>
|
@@ -797,7 +814,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
797 |
|
798 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
799 |
$sync_enabled = ! empty( $_POST['fb_sync_enabled'] );
|
800 |
-
$is_visible = ! empty( $_POST[
|
801 |
|
802 |
if ( ! $product->is_type( 'variable' ) ) {
|
803 |
|
@@ -813,9 +830,10 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
813 |
}
|
814 |
}
|
815 |
|
816 |
-
|
|
|
817 |
|
818 |
-
if ( $sync_enabled ) {
|
819 |
|
820 |
switch ( $product->get_type() ) {
|
821 |
|
@@ -836,6 +854,8 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
836 |
break;
|
837 |
}
|
838 |
}
|
|
|
|
|
839 |
}
|
840 |
|
841 |
|
@@ -871,6 +891,25 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
871 |
}
|
872 |
|
873 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
874 |
/**
|
875 |
* Deletes a product from Facebook.
|
876 |
*
|
@@ -887,7 +926,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
887 |
}
|
888 |
|
889 |
// skip if not enabled for sync
|
890 |
-
if ( ! $woo_product->woo_product instanceof \WC_Product || !
|
891 |
return;
|
892 |
}
|
893 |
|
@@ -916,12 +955,21 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
916 |
$pg_result = $this->fbgraph->delete_product_group( $fb_product_group_id );
|
917 |
WC_Facebookcommerce_Utils::log( $pg_result );
|
918 |
}
|
|
|
|
|
919 |
}
|
920 |
|
|
|
921 |
/**
|
922 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
923 |
*/
|
924 |
-
function fb_change_product_published_status( $new_status, $old_status, $post ) {
|
925 |
global $post;
|
926 |
|
927 |
if ( ! $post ) {
|
@@ -933,19 +981,19 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
933 |
$product = wc_get_product( $post->ID );
|
934 |
|
935 |
// bail if this product isn't enabled for sync
|
936 |
-
if ( ! $product instanceof \WC_Product || ! Products::
|
937 |
return;
|
938 |
}
|
939 |
|
940 |
-
// change from publish status -> unpublish status
|
941 |
// change from trash status -> publish status
|
942 |
// no need to update for change from trash <-> unpublish status
|
943 |
-
if ( ( $old_status
|
944 |
-
( $old_status == 'trash' && $new_status == 'publish' ) ) {
|
945 |
$this->update_fb_visibility( $post->ID, $visibility );
|
946 |
}
|
947 |
}
|
948 |
|
|
|
949 |
/**
|
950 |
* Generic function for use with any product publishing.
|
951 |
*
|
@@ -956,14 +1004,19 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
956 |
*/
|
957 |
public function on_product_publish( $wp_id ) {
|
958 |
|
959 |
-
if
|
|
|
|
|
|
|
|
|
|
|
960 |
return;
|
961 |
}
|
962 |
|
963 |
-
$woo_product
|
964 |
|
965 |
// skip if not enabled for sync
|
966 |
-
if ( ! $woo_product->woo_product instanceof \WC_Product || !
|
967 |
return;
|
968 |
}
|
969 |
|
@@ -974,6 +1027,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
974 |
}
|
975 |
}
|
976 |
|
|
|
977 |
/**
|
978 |
* If the user has opt-in to remove products that are out of stock,
|
979 |
* this function will delete the product from FB Page as well.
|
@@ -1071,7 +1125,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1071 |
}
|
1072 |
|
1073 |
// skip if not enabled for sync
|
1074 |
-
if ( ! $woo_product->woo_product instanceof \WC_Product || !
|
1075 |
return;
|
1076 |
}
|
1077 |
|
@@ -1210,11 +1264,13 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1210 |
$fb_product_group_id
|
1211 |
);
|
1212 |
|
|
|
1213 |
$this->display_success_message(
|
1214 |
'Created product group <a href="https://facebook.com/' .
|
1215 |
$fb_product_group_id . '" target="_blank">' .
|
1216 |
$fb_product_group_id . '</a> on Facebook.'
|
1217 |
);
|
|
|
1218 |
|
1219 |
return $fb_product_group_id;
|
1220 |
}
|
@@ -1249,11 +1305,13 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1249 |
$fb_product_item_id
|
1250 |
);
|
1251 |
|
|
|
1252 |
$this->display_success_message(
|
1253 |
'Created product item <a href="https://facebook.com/' .
|
1254 |
$fb_product_item_id . '" target="_blank">' .
|
1255 |
$fb_product_item_id . '</a> on Facebook.'
|
1256 |
);
|
|
|
1257 |
|
1258 |
return $fb_product_item_id;
|
1259 |
}
|
@@ -1300,6 +1358,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1300 |
)
|
1301 |
);
|
1302 |
|
|
|
1303 |
if ( $result ) {
|
1304 |
$this->display_success_message(
|
1305 |
'Updated product group <a href="https://facebook.com/' .
|
@@ -1307,6 +1366,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1307 |
'</a> on Facebook.'
|
1308 |
);
|
1309 |
}
|
|
|
1310 |
}
|
1311 |
|
1312 |
/**
|
@@ -1327,12 +1387,14 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1327 |
)
|
1328 |
);
|
1329 |
|
|
|
1330 |
if ( $result ) {
|
1331 |
$this->display_success_message(
|
1332 |
'Updated product <a href="https://facebook.com/' . $fb_product_item_id .
|
1333 |
'" target="_blank">' . $fb_product_item_id . '</a> on Facebook.'
|
1334 |
);
|
1335 |
}
|
|
|
1336 |
}
|
1337 |
|
1338 |
/**
|
@@ -1352,6 +1414,19 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1352 |
return;
|
1353 |
}
|
1354 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1355 |
if ( isset( $_REQUEST['api_key'] ) ) {
|
1356 |
|
1357 |
$api_key = sanitize_text_field( wp_unslash( $_REQUEST['api_key'] ) );
|
@@ -1361,6 +1436,15 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1361 |
}
|
1362 |
}
|
1363 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1364 |
if ( isset( $_REQUEST['product_catalog_id'] ) ) {
|
1365 |
|
1366 |
$product_catalog_id = sanitize_text_field( wp_unslash( $_REQUEST['product_catalog_id'] ) );
|
@@ -1382,7 +1466,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1382 |
if ( ctype_digit( $pixel_id ) ) {
|
1383 |
|
1384 |
// to prevent race conditions with pixel-only settings, only save a pixel if we already have an access token
|
1385 |
-
if ( $this->
|
1386 |
|
1387 |
if ( $this->get_facebook_pixel_id() !== $pixel_id ) {
|
1388 |
$this->update_pixel_install_time( time() );
|
@@ -1393,9 +1477,8 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1393 |
} else {
|
1394 |
|
1395 |
WC_Facebookcommerce_Utils::log( 'Got pixel-only settings, doing nothing' );
|
1396 |
-
echo 'Not saving pixel-only settings';
|
1397 |
|
1398 |
-
|
1399 |
}
|
1400 |
}
|
1401 |
}
|
@@ -1413,15 +1496,6 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1413 |
}
|
1414 |
}
|
1415 |
|
1416 |
-
if ( isset( $_REQUEST['external_merchant_settings_id'] ) ) {
|
1417 |
-
|
1418 |
-
$external_merchant_settings_id = sanitize_text_field( wp_unslash( $_REQUEST['external_merchant_settings_id'] ) );
|
1419 |
-
|
1420 |
-
if ( ctype_digit( $external_merchant_settings_id ) ) {
|
1421 |
-
$this->update_external_merchant_settings_id( $external_merchant_settings_id );
|
1422 |
-
}
|
1423 |
-
}
|
1424 |
-
|
1425 |
if ( isset( $_REQUEST['is_messenger_chat_plugin_enabled'] ) ) {
|
1426 |
$this->settings[ self::SETTING_ENABLE_MESSENGER ] = wc_bool_to_string( wc_clean( wp_unslash( $_REQUEST['is_messenger_chat_plugin_enabled'] ) ) );
|
1427 |
}
|
@@ -1446,9 +1520,8 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1446 |
update_option( $this->get_option_key(), apply_filters( 'woocommerce_settings_api_sanitized_fields_' . $this->id, $this->settings ) );
|
1447 |
|
1448 |
WC_Facebookcommerce_Utils::log( 'Settings saved!' );
|
1449 |
-
echo 'settings_saved';
|
1450 |
|
1451 |
-
|
1452 |
}
|
1453 |
|
1454 |
/**
|
@@ -1484,6 +1557,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1484 |
$this->init_settings();
|
1485 |
$this->update_page_access_token( '' );
|
1486 |
$this->update_product_catalog_id( '' );
|
|
|
1487 |
|
1488 |
$this->settings[ self::SETTING_FACEBOOK_PIXEL_ID ] = '';
|
1489 |
$this->settings[ self::SETTING_ENABLE_ADVANCED_MATCHING ] = 'no';
|
@@ -1497,7 +1571,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1497 |
$this->update_external_merchant_settings_id( '' );
|
1498 |
$this->update_pixel_install_time( 0 );
|
1499 |
$this->update_feed_id( '' );
|
1500 |
-
$this->
|
1501 |
$this->settings['upload_end_time'] = '';
|
1502 |
|
1503 |
WC_Facebookcommerce_Pixel::set_pixel_id( 0 );
|
@@ -1528,36 +1602,66 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1528 |
}
|
1529 |
|
1530 |
/**
|
1531 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1532 |
**/
|
1533 |
-
function
|
1534 |
-
|
|
|
|
|
1535 |
check_ajax_referer( 'wc_facebook_settings_jsx' );
|
|
|
1536 |
if ( $this->get_page_access_token() ) {
|
1537 |
-
|
|
|
1538 |
'connected' => true,
|
1539 |
'status' => 'in progress',
|
1540 |
-
|
1541 |
-
|
|
|
|
|
1542 |
if ( ! isset( $this->fbproductfeed ) ) {
|
|
|
1543 |
if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) {
|
1544 |
include_once 'includes/fbproductfeed.php';
|
1545 |
}
|
1546 |
-
|
|
|
1547 |
$this->get_product_catalog_id(),
|
1548 |
$this->fbgraph
|
1549 |
);
|
1550 |
}
|
|
|
1551 |
$status = $this->fbproductfeed->is_upload_complete( $this->settings );
|
1552 |
|
1553 |
$response['status'] = $status;
|
|
|
1554 |
} else {
|
1555 |
-
|
|
|
1556 |
'connected' => true,
|
1557 |
'status' => 'error',
|
1558 |
-
|
1559 |
}
|
1560 |
-
|
|
|
|
|
1561 |
update_option(
|
1562 |
$this->get_option_key(),
|
1563 |
apply_filters(
|
@@ -1566,11 +1670,12 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1566 |
)
|
1567 |
);
|
1568 |
}
|
|
|
1569 |
} else {
|
1570 |
-
|
1571 |
-
|
1572 |
-
);
|
1573 |
}
|
|
|
1574 |
printf( json_encode( $response ) );
|
1575 |
wp_die();
|
1576 |
}
|
@@ -1810,7 +1915,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1810 |
}
|
1811 |
|
1812 |
// check required fields
|
1813 |
-
if ( ! $this->
|
1814 |
|
1815 |
$message = sprintf(
|
1816 |
/* translators: Placeholders %1$s - opening strong HTML tag, %2$s - closing strong HTML tag, %3$s - opening link HTML tag, %4$s - closing link HTML tag */
|
@@ -2316,8 +2421,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
2316 |
}
|
2317 |
|
2318 |
$this->update_feed_id( $this->fbproductfeed->feed_id );
|
2319 |
-
|
2320 |
-
$this->settings['fb_upload_id'] = $this->fbproductfeed->upload_id;
|
2321 |
|
2322 |
update_option(
|
2323 |
$this->get_option_key(),
|
@@ -2447,6 +2551,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
2447 |
/** @see \WC_Facebookcommerce_Integration::generate_product_sync_title_html() */
|
2448 |
[
|
2449 |
'type' => 'product_sync_title',
|
|
|
2450 |
],
|
2451 |
|
2452 |
self::SETTING_ENABLE_PRODUCT_SYNC => [
|
@@ -2497,11 +2602,11 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
2497 |
|
2498 |
/** @see \WC_Facebookcommerce_Integration::generate_resync_schedule_html() */
|
2499 |
/** @see \WC_Facebookcommerce_Integration::validate_resync_schedule_field() */
|
2500 |
-
self::SETTING_SCHEDULED_RESYNC_OFFSET => [
|
2501 |
-
|
2502 |
-
|
2503 |
-
|
2504 |
-
],
|
2505 |
|
2506 |
[
|
2507 |
'title' => __( 'Messenger', 'facebook-for-woocommerce' ),
|
@@ -2601,7 +2706,9 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
2601 |
onclick="facebookConfig();"
|
2602 |
><?php esc_html_e( 'Manage connection', 'facebook-for-woocommerce' ); ?></a>
|
2603 |
</h3>
|
2604 |
-
<?php if ( empty( $this->get_page_name() ) ) : ?>
|
|
|
|
|
2605 |
<div id="connection-message-invalid">
|
2606 |
<p style="color: #DC3232;">
|
2607 |
<?php esc_html_e( 'Your connection has expired.', 'facebook-for-woocommerce' ); ?>
|
@@ -2618,7 +2725,9 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
2618 |
</strong>
|
2619 |
</p>
|
2620 |
</div>
|
2621 |
-
|
|
|
|
|
2622 |
<table class="form-table">
|
2623 |
<?php
|
2624 |
|
@@ -2640,12 +2749,12 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
2640 |
protected function generate_facebook_page_name_html( $key, array $args = [] ) {
|
2641 |
|
2642 |
$key = $this->get_field_key( $key );
|
2643 |
-
$page_name = $this->get_page_name();
|
2644 |
-
$page_url = $this->get_page_url();
|
2645 |
|
2646 |
ob_start();
|
2647 |
|
2648 |
-
|
2649 |
<tr valign="top">
|
2650 |
<th scope="row" class="titledesc">
|
2651 |
<?php esc_html_e( 'Facebook page', 'facebook-for-woocommerce' ); ?>
|
@@ -2676,16 +2785,17 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
2676 |
|
2677 |
—
|
2678 |
|
2679 |
-
<?php endif
|
2680 |
<input
|
2681 |
type="hidden"
|
2682 |
name="<?php echo esc_attr( $key ); ?>"
|
2683 |
id="<?php echo esc_attr( $key ); ?>"
|
2684 |
value="<?php echo esc_attr( $this->get_facebook_page_id() ); ?>"
|
2685 |
/>
|
|
|
2686 |
</td>
|
2687 |
</tr>
|
2688 |
-
<?php
|
2689 |
|
2690 |
return ob_get_clean();
|
2691 |
}
|
@@ -2787,13 +2897,18 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
2787 |
?>
|
2788 |
</table>
|
2789 |
<h3 class="wc-settings-sub-title" id="<?php echo esc_attr( $key ); ?>">
|
|
|
2790 |
<?php esc_html_e( 'Product sync', 'facebook-for-woocommerce' ); ?>
|
2791 |
-
|
2792 |
-
|
2793 |
-
|
2794 |
-
|
2795 |
-
|
2796 |
-
|
|
|
|
|
|
|
|
|
2797 |
</h3>
|
2798 |
<div><p id="sync_progress" style="display: none"></p></div>
|
2799 |
<table class="form-table">
|
@@ -3170,7 +3285,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3170 |
* @param string $page_access_token Facebook page access token
|
3171 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
3172 |
*/
|
3173 |
-
return (string) apply_filters( 'wc_facebook_page_access_token', $this->page_access_token, $this );
|
3174 |
}
|
3175 |
|
3176 |
|
@@ -3258,6 +3373,34 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3258 |
}
|
3259 |
|
3260 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3261 |
/**
|
3262 |
* Gets the Facebook pixel install time in UTC seconds.
|
3263 |
*
|
@@ -3615,6 +3758,21 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3615 |
}
|
3616 |
|
3617 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3618 |
/**
|
3619 |
* Updates the Facebook pixel install time.
|
3620 |
*
|
@@ -3661,6 +3819,21 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3661 |
}
|
3662 |
|
3663 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3664 |
/** Conditional methods *******************************************************************************************/
|
3665 |
|
3666 |
|
@@ -3673,7 +3846,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3673 |
*/
|
3674 |
public function is_configured() {
|
3675 |
|
3676 |
-
return
|
3677 |
}
|
3678 |
|
3679 |
|
@@ -3782,6 +3955,26 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3782 |
}
|
3783 |
|
3784 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3785 |
/**
|
3786 |
* Gets message HTML.
|
3787 |
*
|
@@ -3875,7 +4068,8 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3875 |
*/
|
3876 |
public function get_page_name() {
|
3877 |
|
3878 |
-
if ( $this->is_configured() ) {
|
|
|
3879 |
$page_name = $this->fbgraph->get_page_name( $this->get_facebook_page_id(), $this->get_page_access_token() );
|
3880 |
} else {
|
3881 |
$page_name = '';
|
@@ -4052,7 +4246,14 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
4052 |
* Helper function to update FB visibility.
|
4053 |
*/
|
4054 |
function update_fb_visibility( $wp_id, $visibility ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
4055 |
$woo_product = new WC_Facebook_Product( $wp_id );
|
|
|
4056 |
if ( ! $woo_product->exists() ) {
|
4057 |
// This function can be called for non-woo products.
|
4058 |
return;
|
@@ -4089,23 +4290,30 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
4089 |
}
|
4090 |
}
|
4091 |
|
4092 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4093 |
|
4094 |
// bail if not a product or product is not enabled for sync
|
4095 |
-
if ( ! $product instanceof \WC_Product || ! Products::
|
4096 |
return;
|
4097 |
}
|
4098 |
|
4099 |
$wp_id = $product->get_id();
|
4100 |
-
$visibility = get_post_status( $wp_id ) === 'publish'
|
4101 |
-
|
4102 |
-
: self::FB_SHOP_PRODUCT_HIDDEN;
|
4103 |
-
// case 1: new status is 'publish' regardless of old status, sync to FB
|
4104 |
if ( $visibility === self::FB_SHOP_PRODUCT_VISIBLE ) {
|
|
|
4105 |
$this->on_product_publish( $wp_id );
|
4106 |
} else {
|
4107 |
-
//
|
4108 |
-
//
|
4109 |
$this->update_fb_visibility( $wp_id, $visibility );
|
4110 |
}
|
4111 |
}
|
@@ -4365,4 +4573,34 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
4365 |
}
|
4366 |
|
4367 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4368 |
}
|
10 |
|
11 |
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
12 |
use SkyVerge\WooCommerce\Facebook\Products;
|
13 |
+
use SkyVerge\WooCommerce\Facebook\Products\Feed;
|
14 |
|
15 |
if ( ! defined( 'ABSPATH' ) ) {
|
16 |
exit; // Exit if accessed directly
|
35 |
/** @var string the WordPress option name where the feed ID is stored */
|
36 |
const OPTION_FEED_ID = 'wc_facebook_feed_id';
|
37 |
|
38 |
+
/** @var string the WordPress option name where the upload ID is stored */
|
39 |
+
const OPTION_UPLOAD_ID = 'wc_facebook_upload_id';
|
40 |
+
|
41 |
/** @var string the WordPress option name where the JS SDK version is stored */
|
42 |
const OPTION_JS_SDK_VERSION = 'wc_facebook_js_sdk_version';
|
43 |
|
105 |
/** @var string|null the configured feed ID */
|
106 |
public $feed_id;
|
107 |
|
108 |
+
/** @var string|null the configured upload ID */
|
109 |
+
private $upload_id;
|
110 |
+
|
111 |
/** @var string|null the configured pixel install time */
|
112 |
public $pixel_install_time;
|
113 |
|
114 |
/** @var string|null the configured JS SDK version */
|
115 |
private $js_sdk_version;
|
116 |
|
117 |
+
/** @var bool|null whether the feed has been migrated from FBE 1 to FBE 1.5 */
|
118 |
+
private $feed_migrated;
|
119 |
+
|
120 |
|
121 |
/** Legacy properties *********************************************************************************************/
|
122 |
|
334 |
self::FB_PRIORITY_MID
|
335 |
);
|
336 |
|
337 |
+
// on_product_save() must run with priority larger than 20 to make sure WooCommerce has a chance to save the submitted product information
|
338 |
+
add_action( 'woocommerce_process_product_meta', [ $this, 'on_product_save' ], 40 );
|
339 |
+
|
340 |
+
// don't duplicate product FBID meta
|
341 |
+
add_filter( 'woocommerce_duplicate_product_exclude_meta', [ $this, 'fb_duplicate_product_reset_meta' ] );
|
342 |
+
|
343 |
// Only load product processing hooks if we have completed setup.
|
344 |
if ( $this->get_page_access_token() && $this->get_product_catalog_id() ) {
|
345 |
|
|
|
|
|
|
|
346 |
add_action(
|
347 |
'woocommerce_product_quick_edit_save',
|
348 |
array( $this, 'on_quick_and_bulk_edit_save' ),
|
357 |
1 // Args passed to on_quick_and_bulk_edit_save ('product')
|
358 |
);
|
359 |
|
360 |
+
add_action( 'trashed_post', [ $this, 'on_product_trash' ] );
|
361 |
+
|
362 |
add_action(
|
363 |
'before_delete_post',
|
364 |
array( $this, 'on_product_delete' ),
|
390 |
array( $this, 'ajax_delete_fb_product' )
|
391 |
);
|
392 |
|
|
|
|
|
|
|
|
|
|
|
393 |
add_action(
|
394 |
'pmxi_after_xml_import',
|
395 |
array( $this, 'wp_all_import_compat' )
|
417 |
// Must be outside of admin for cron to schedule correctly.
|
418 |
add_action( 'sync_all_fb_products_using_feed', [ $this, 'handle_scheduled_resync_action' ], self::FB_PRIORITY_MID );
|
419 |
|
420 |
+
// handle the special background feed generation action
|
421 |
+
add_action( 'wc_facebook_generate_product_catalog_feed', [ $this, 'handle_generate_product_catalog_feed' ] );
|
422 |
+
|
423 |
if ( $this->get_facebook_pixel_id() ) {
|
424 |
$user_info = WC_Facebookcommerce_Utils::get_user_info( $this->is_advanced_matching_enabled() );
|
425 |
$this->events_tracker = new WC_Facebookcommerce_EventsTracker( $user_info );
|
633 |
}
|
634 |
|
635 |
?>
|
636 |
+
<?php /* ?>
|
637 |
<?php echo esc_html__( 'Visible:', 'facebook-for-woocommerce' ); ?>
|
638 |
<input name="<?php echo esc_attr( Products::VISIBILITY_META_KEY ); ?>"
|
639 |
type="checkbox"
|
641 |
<?php echo checked( ! $woo_product->woo_product instanceof \WC_Product || Products::is_product_visible( $woo_product->woo_product ) ); ?>/>
|
642 |
|
643 |
<p/>
|
644 |
+
<?php */ ?>
|
645 |
<input name="is_product_page" type="hidden" value="1"/>
|
646 |
|
647 |
<p/>
|
751 |
},
|
752 |
feed: {
|
753 |
totalVisibleProducts: '<?php echo esc_js( $this->get_product_count() ); ?>',
|
754 |
+
hasClientSideFeedUpload: '<?php echo esc_js( ! ! $this->get_feed_id() ); ?>',
|
755 |
+
enabled: true,
|
756 |
+
format: 'csv'
|
757 |
},
|
758 |
feedPrepared: {
|
759 |
+
feedUrl: '<?php echo esc_url_raw( Feed::get_feed_data_url() ); ?>',
|
760 |
feedPingUrl: '',
|
761 |
+
feedMigrated: <?php echo $this->is_feed_migrated() ? 'true' : 'false'; ?>,
|
762 |
samples: <?php echo $this->get_sample_product_feed(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
763 |
},
|
|
|
764 |
excludedCategoryIDs: <?php echo json_encode( $this->get_excluded_product_category_ids() ); ?>,
|
765 |
excludedTagIDs: <?php echo json_encode( $this->get_excluded_product_tag_ids() ); ?>,
|
766 |
messengerGreetingMaxCharacters: <?php echo esc_js( $this->get_messenger_greeting_max_characters() ); ?>
|
814 |
|
815 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
816 |
$sync_enabled = ! empty( $_POST['fb_sync_enabled'] );
|
817 |
+
$is_visible = ! empty( $_POST[ Products::VISIBILITY_META_KEY ] );
|
818 |
|
819 |
if ( ! $product->is_type( 'variable' ) ) {
|
820 |
|
830 |
}
|
831 |
}
|
832 |
|
833 |
+
// do not attempt to update product visibility during FBE 1.5: the Visible setting was removed so it always seems as if the visibility had been disabled
|
834 |
+
// $this->update_fb_visibility( $product->get_id(), $is_visible ? self::FB_SHOP_PRODUCT_VISIBLE : self::FB_SHOP_PRODUCT_HIDDEN );
|
835 |
|
836 |
+
if ( $sync_enabled && $this->get_page_access_token() && $this->get_product_catalog_id() ) {
|
837 |
|
838 |
switch ( $product->get_type() ) {
|
839 |
|
854 |
break;
|
855 |
}
|
856 |
}
|
857 |
+
|
858 |
+
$this->enable_product_sync_delay_admin_notice();
|
859 |
}
|
860 |
|
861 |
|
891 |
}
|
892 |
|
893 |
|
894 |
+
/**
|
895 |
+
* Enables product sync delay notice when a post is moved to the trash.
|
896 |
+
*
|
897 |
+
* @internal
|
898 |
+
*
|
899 |
+
* @since 1.11.0
|
900 |
+
*
|
901 |
+
* @param int $post_id the post ID
|
902 |
+
*/
|
903 |
+
public function on_product_trash( $post_id ) {
|
904 |
+
|
905 |
+
$product = wc_get_product( $post_id );
|
906 |
+
|
907 |
+
if ( $product instanceof \WC_Product ) {
|
908 |
+
$this->enable_product_sync_delay_admin_notice();
|
909 |
+
}
|
910 |
+
}
|
911 |
+
|
912 |
+
|
913 |
/**
|
914 |
* Deletes a product from Facebook.
|
915 |
*
|
926 |
}
|
927 |
|
928 |
// skip if not enabled for sync
|
929 |
+
if ( ! $woo_product->woo_product instanceof \WC_Product || ! Products::product_should_be_synced( $woo_product->woo_product ) ) {
|
930 |
return;
|
931 |
}
|
932 |
|
955 |
$pg_result = $this->fbgraph->delete_product_group( $fb_product_group_id );
|
956 |
WC_Facebookcommerce_Utils::log( $pg_result );
|
957 |
}
|
958 |
+
|
959 |
+
$this->enable_product_sync_delay_admin_notice();
|
960 |
}
|
961 |
|
962 |
+
|
963 |
/**
|
964 |
+
* Updates Facebook Visibility upon trashing and restore.
|
965 |
+
*
|
966 |
+
* @internal
|
967 |
+
*
|
968 |
+
* @param string $new_status
|
969 |
+
* @param string $old_status
|
970 |
+
* @param \WP_post $post
|
971 |
*/
|
972 |
+
public function fb_change_product_published_status( $new_status, $old_status, $post ) {
|
973 |
global $post;
|
974 |
|
975 |
if ( ! $post ) {
|
981 |
$product = wc_get_product( $post->ID );
|
982 |
|
983 |
// bail if this product isn't enabled for sync
|
984 |
+
if ( ! $product instanceof \WC_Product || ! Products::product_should_be_synced( $product ) ) {
|
985 |
return;
|
986 |
}
|
987 |
|
988 |
+
// change from publish status -> unpublish status (e.g. trash, draft, etc.)
|
989 |
// change from trash status -> publish status
|
990 |
// no need to update for change from trash <-> unpublish status
|
991 |
+
if ( ( $old_status === 'publish' && $new_status !== 'publish' ) || ( $old_status === 'trash' && $new_status === 'publish' ) ) {
|
|
|
992 |
$this->update_fb_visibility( $post->ID, $visibility );
|
993 |
}
|
994 |
}
|
995 |
|
996 |
+
|
997 |
/**
|
998 |
* Generic function for use with any product publishing.
|
999 |
*
|
1004 |
*/
|
1005 |
public function on_product_publish( $wp_id ) {
|
1006 |
|
1007 |
+
// bail if we don't have a page access token or a catalog ID configured
|
1008 |
+
if ( ! $this->get_page_access_token() || ! $this->get_product_catalog_id() ) {
|
1009 |
+
return;
|
1010 |
+
}
|
1011 |
+
|
1012 |
+
if ( get_post_status( $wp_id ) !== 'publish' ) {
|
1013 |
return;
|
1014 |
}
|
1015 |
|
1016 |
+
$woo_product = new WC_Facebook_Product( $wp_id );
|
1017 |
|
1018 |
// skip if not enabled for sync
|
1019 |
+
if ( ! $woo_product->woo_product instanceof \WC_Product || ! Products::product_should_be_synced( $woo_product->woo_product ) ) {
|
1020 |
return;
|
1021 |
}
|
1022 |
|
1027 |
}
|
1028 |
}
|
1029 |
|
1030 |
+
|
1031 |
/**
|
1032 |
* If the user has opt-in to remove products that are out of stock,
|
1033 |
* this function will delete the product from FB Page as well.
|
1125 |
}
|
1126 |
|
1127 |
// skip if not enabled for sync
|
1128 |
+
if ( ! $woo_product->woo_product instanceof \WC_Product || ! Products::product_should_be_synced( $woo_product->woo_product ) ) {
|
1129 |
return;
|
1130 |
}
|
1131 |
|
1264 |
$fb_product_group_id
|
1265 |
);
|
1266 |
|
1267 |
+
/** TODO: restore when adopting FBE 2.0
|
1268 |
$this->display_success_message(
|
1269 |
'Created product group <a href="https://facebook.com/' .
|
1270 |
$fb_product_group_id . '" target="_blank">' .
|
1271 |
$fb_product_group_id . '</a> on Facebook.'
|
1272 |
);
|
1273 |
+
*/
|
1274 |
|
1275 |
return $fb_product_group_id;
|
1276 |
}
|
1305 |
$fb_product_item_id
|
1306 |
);
|
1307 |
|
1308 |
+
/** TODO: restore when adopting FBE 2.0
|
1309 |
$this->display_success_message(
|
1310 |
'Created product item <a href="https://facebook.com/' .
|
1311 |
$fb_product_item_id . '" target="_blank">' .
|
1312 |
$fb_product_item_id . '</a> on Facebook.'
|
1313 |
);
|
1314 |
+
*/
|
1315 |
|
1316 |
return $fb_product_item_id;
|
1317 |
}
|
1358 |
)
|
1359 |
);
|
1360 |
|
1361 |
+
/** TODO: restore when adopting FBE 2.0
|
1362 |
if ( $result ) {
|
1363 |
$this->display_success_message(
|
1364 |
'Updated product group <a href="https://facebook.com/' .
|
1366 |
'</a> on Facebook.'
|
1367 |
);
|
1368 |
}
|
1369 |
+
*/
|
1370 |
}
|
1371 |
|
1372 |
/**
|
1387 |
)
|
1388 |
);
|
1389 |
|
1390 |
+
/** TODO: restore when adopting FBE 2.0
|
1391 |
if ( $result ) {
|
1392 |
$this->display_success_message(
|
1393 |
'Updated product <a href="https://facebook.com/' . $fb_product_item_id .
|
1394 |
'" target="_blank">' . $fb_product_item_id . '</a> on Facebook.'
|
1395 |
);
|
1396 |
}
|
1397 |
+
*/
|
1398 |
}
|
1399 |
|
1400 |
/**
|
1414 |
return;
|
1415 |
}
|
1416 |
|
1417 |
+
\WC_Facebookcommerce_Utils::log( 'Saving settings via AJAX' );
|
1418 |
+
|
1419 |
+
// listen for a feed migrated event for FBE 1.5
|
1420 |
+
if ( isset( $_REQUEST['feed_migrated'] ) ) {
|
1421 |
+
|
1422 |
+
$this->set_feed_migrated( wc_string_to_bool( $_REQUEST['feed_migrated'] ) );
|
1423 |
+
|
1424 |
+
// don't save anything else if already connected
|
1425 |
+
if ( $this->get_external_merchant_settings_id() ) {
|
1426 |
+
wp_send_json_success();
|
1427 |
+
}
|
1428 |
+
}
|
1429 |
+
|
1430 |
if ( isset( $_REQUEST['api_key'] ) ) {
|
1431 |
|
1432 |
$api_key = sanitize_text_field( wp_unslash( $_REQUEST['api_key'] ) );
|
1436 |
}
|
1437 |
}
|
1438 |
|
1439 |
+
if ( isset( $_REQUEST['external_merchant_settings_id'] ) ) {
|
1440 |
+
|
1441 |
+
$external_merchant_settings_id = sanitize_text_field( wp_unslash( $_REQUEST['external_merchant_settings_id'] ) );
|
1442 |
+
|
1443 |
+
if ( is_numeric( $external_merchant_settings_id ) ) {
|
1444 |
+
$this->update_external_merchant_settings_id( $external_merchant_settings_id );
|
1445 |
+
}
|
1446 |
+
}
|
1447 |
+
|
1448 |
if ( isset( $_REQUEST['product_catalog_id'] ) ) {
|
1449 |
|
1450 |
$product_catalog_id = sanitize_text_field( wp_unslash( $_REQUEST['product_catalog_id'] ) );
|
1466 |
if ( ctype_digit( $pixel_id ) ) {
|
1467 |
|
1468 |
// to prevent race conditions with pixel-only settings, only save a pixel if we already have an access token
|
1469 |
+
if ( $this->get_external_merchant_settings_id() ) {
|
1470 |
|
1471 |
if ( $this->get_facebook_pixel_id() !== $pixel_id ) {
|
1472 |
$this->update_pixel_install_time( time() );
|
1477 |
} else {
|
1478 |
|
1479 |
WC_Facebookcommerce_Utils::log( 'Got pixel-only settings, doing nothing' );
|
|
|
1480 |
|
1481 |
+
wp_send_json_error();
|
1482 |
}
|
1483 |
}
|
1484 |
}
|
1496 |
}
|
1497 |
}
|
1498 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1499 |
if ( isset( $_REQUEST['is_messenger_chat_plugin_enabled'] ) ) {
|
1500 |
$this->settings[ self::SETTING_ENABLE_MESSENGER ] = wc_bool_to_string( wc_clean( wp_unslash( $_REQUEST['is_messenger_chat_plugin_enabled'] ) ) );
|
1501 |
}
|
1520 |
update_option( $this->get_option_key(), apply_filters( 'woocommerce_settings_api_sanitized_fields_' . $this->id, $this->settings ) );
|
1521 |
|
1522 |
WC_Facebookcommerce_Utils::log( 'Settings saved!' );
|
|
|
1523 |
|
1524 |
+
wp_send_json_success();
|
1525 |
}
|
1526 |
|
1527 |
/**
|
1557 |
$this->init_settings();
|
1558 |
$this->update_page_access_token( '' );
|
1559 |
$this->update_product_catalog_id( '' );
|
1560 |
+
$this->set_feed_migrated( false );
|
1561 |
|
1562 |
$this->settings[ self::SETTING_FACEBOOK_PIXEL_ID ] = '';
|
1563 |
$this->settings[ self::SETTING_ENABLE_ADVANCED_MATCHING ] = 'no';
|
1571 |
$this->update_external_merchant_settings_id( '' );
|
1572 |
$this->update_pixel_install_time( 0 );
|
1573 |
$this->update_feed_id( '' );
|
1574 |
+
$this->update_upload_id( '' );
|
1575 |
$this->settings['upload_end_time'] = '';
|
1576 |
|
1577 |
WC_Facebookcommerce_Pixel::set_pixel_id( 0 );
|
1602 |
}
|
1603 |
|
1604 |
/**
|
1605 |
+
* Checks the feed upload status (FBE v1.0).
|
1606 |
+
*
|
1607 |
+
* @internal
|
1608 |
+
*/
|
1609 |
+
public function ajax_check_feed_upload_status() {
|
1610 |
+
$response = array(
|
1611 |
+
'connected' => true,
|
1612 |
+
'status' => 'complete',
|
1613 |
+
);
|
1614 |
+
printf( json_encode( $response ) );
|
1615 |
+
wp_die();
|
1616 |
+
}
|
1617 |
+
|
1618 |
+
|
1619 |
+
/**
|
1620 |
+
* Check Feed Upload Status (FBE v2.0)
|
1621 |
+
* TODO: When migrating to FBE v2.0, remove above function and rename
|
1622 |
+
* below function to ajax_check_feed_upload_status()
|
1623 |
**/
|
1624 |
+
public function ajax_check_feed_upload_status_v2() {
|
1625 |
+
|
1626 |
+
\WC_Facebookcommerce_Utils::check_woo_ajax_permissions( 'check feed upload status', true );
|
1627 |
+
|
1628 |
check_ajax_referer( 'wc_facebook_settings_jsx' );
|
1629 |
+
|
1630 |
if ( $this->get_page_access_token() ) {
|
1631 |
+
|
1632 |
+
$response = [
|
1633 |
'connected' => true,
|
1634 |
'status' => 'in progress',
|
1635 |
+
];
|
1636 |
+
|
1637 |
+
if ( ! empty( $this->get_upload_id() ) ) {
|
1638 |
+
|
1639 |
if ( ! isset( $this->fbproductfeed ) ) {
|
1640 |
+
|
1641 |
if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) {
|
1642 |
include_once 'includes/fbproductfeed.php';
|
1643 |
}
|
1644 |
+
|
1645 |
+
$this->fbproductfeed = new \WC_Facebook_Product_Feed(
|
1646 |
$this->get_product_catalog_id(),
|
1647 |
$this->fbgraph
|
1648 |
);
|
1649 |
}
|
1650 |
+
|
1651 |
$status = $this->fbproductfeed->is_upload_complete( $this->settings );
|
1652 |
|
1653 |
$response['status'] = $status;
|
1654 |
+
|
1655 |
} else {
|
1656 |
+
|
1657 |
+
$response = [
|
1658 |
'connected' => true,
|
1659 |
'status' => 'error',
|
1660 |
+
];
|
1661 |
}
|
1662 |
+
|
1663 |
+
if ( 'complete' === $response['status'] ) {
|
1664 |
+
|
1665 |
update_option(
|
1666 |
$this->get_option_key(),
|
1667 |
apply_filters(
|
1670 |
)
|
1671 |
);
|
1672 |
}
|
1673 |
+
|
1674 |
} else {
|
1675 |
+
|
1676 |
+
$response = [ 'connected' => false ];
|
|
|
1677 |
}
|
1678 |
+
|
1679 |
printf( json_encode( $response ) );
|
1680 |
wp_die();
|
1681 |
}
|
1915 |
}
|
1916 |
|
1917 |
// check required fields
|
1918 |
+
if ( ! $this->is_configured() ) {
|
1919 |
|
1920 |
$message = sprintf(
|
1921 |
/* translators: Placeholders %1$s - opening strong HTML tag, %2$s - closing strong HTML tag, %3$s - opening link HTML tag, %4$s - closing link HTML tag */
|
2421 |
}
|
2422 |
|
2423 |
$this->update_feed_id( $this->fbproductfeed->feed_id );
|
2424 |
+
$this->update_upload_id( $this->fbproductfeed->upload_id );
|
|
|
2425 |
|
2426 |
update_option(
|
2427 |
$this->get_option_key(),
|
2551 |
/** @see \WC_Facebookcommerce_Integration::generate_product_sync_title_html() */
|
2552 |
[
|
2553 |
'type' => 'product_sync_title',
|
2554 |
+
'title' => __( 'Product sync', 'facebook-for-woocommerce' ),
|
2555 |
],
|
2556 |
|
2557 |
self::SETTING_ENABLE_PRODUCT_SYNC => [
|
2602 |
|
2603 |
/** @see \WC_Facebookcommerce_Integration::generate_resync_schedule_html() */
|
2604 |
/** @see \WC_Facebookcommerce_Integration::validate_resync_schedule_field() */
|
2605 |
+
//self::SETTING_SCHEDULED_RESYNC_OFFSET => [
|
2606 |
+
// 'title' => __( 'Force daily resync at', 'facebook-for-woocommerce' ),
|
2607 |
+
// 'class' => 'product-sync-field resync-schedule-fieldset',
|
2608 |
+
// 'type' => 'resync_schedule',
|
2609 |
+
//],
|
2610 |
|
2611 |
[
|
2612 |
'title' => __( 'Messenger', 'facebook-for-woocommerce' ),
|
2706 |
onclick="facebookConfig();"
|
2707 |
><?php esc_html_e( 'Manage connection', 'facebook-for-woocommerce' ); ?></a>
|
2708 |
</h3>
|
2709 |
+
<?php // if ( empty( $this->get_page_name() ) ) : ?>
|
2710 |
+
<?php
|
2711 |
+
/**
|
2712 |
<div id="connection-message-invalid">
|
2713 |
<p style="color: #DC3232;">
|
2714 |
<?php esc_html_e( 'Your connection has expired.', 'facebook-for-woocommerce' ); ?>
|
2725 |
</strong>
|
2726 |
</p>
|
2727 |
</div>
|
2728 |
+
*/
|
2729 |
+
?>
|
2730 |
+
<?php // endif; ?>
|
2731 |
<table class="form-table">
|
2732 |
<?php
|
2733 |
|
2749 |
protected function generate_facebook_page_name_html( $key, array $args = [] ) {
|
2750 |
|
2751 |
$key = $this->get_field_key( $key );
|
2752 |
+
// $page_name = $this->get_page_name();
|
2753 |
+
// $page_url = $this->get_page_url();
|
2754 |
|
2755 |
ob_start();
|
2756 |
|
2757 |
+
/*?>
|
2758 |
<tr valign="top">
|
2759 |
<th scope="row" class="titledesc">
|
2760 |
<?php esc_html_e( 'Facebook page', 'facebook-for-woocommerce' ); ?>
|
2785 |
|
2786 |
—
|
2787 |
|
2788 |
+
<?php endif;*/ ?>
|
2789 |
<input
|
2790 |
type="hidden"
|
2791 |
name="<?php echo esc_attr( $key ); ?>"
|
2792 |
id="<?php echo esc_attr( $key ); ?>"
|
2793 |
value="<?php echo esc_attr( $this->get_facebook_page_id() ); ?>"
|
2794 |
/>
|
2795 |
+
<?php /*
|
2796 |
</td>
|
2797 |
</tr>
|
2798 |
+
<?php */
|
2799 |
|
2800 |
return ob_get_clean();
|
2801 |
}
|
2897 |
?>
|
2898 |
</table>
|
2899 |
<h3 class="wc-settings-sub-title" id="<?php echo esc_attr( $key ); ?>">
|
2900 |
+
|
2901 |
<?php esc_html_e( 'Product sync', 'facebook-for-woocommerce' ); ?>
|
2902 |
+
|
2903 |
+
<?php if ( $this->get_page_name() ) : ?>
|
2904 |
+
<a
|
2905 |
+
id="woocommerce-facebook-settings-sync-products"
|
2906 |
+
class="button product-sync-field"
|
2907 |
+
href="#"
|
2908 |
+
style="vertical-align: middle; margin-left: 20px;"
|
2909 |
+
><?php esc_html_e( 'Sync products', 'facebook-for-woocommerce' ); ?></a>
|
2910 |
+
<?php endif; ?>
|
2911 |
+
|
2912 |
</h3>
|
2913 |
<div><p id="sync_progress" style="display: none"></p></div>
|
2914 |
<table class="form-table">
|
3285 |
* @param string $page_access_token Facebook page access token
|
3286 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
3287 |
*/
|
3288 |
+
return (string) apply_filters( 'wc_facebook_page_access_token', ! $this->is_feed_migrated() ? $this->page_access_token : '', $this );
|
3289 |
}
|
3290 |
|
3291 |
|
3373 |
}
|
3374 |
|
3375 |
|
3376 |
+
/***
|
3377 |
+
* Gets the Facebook Upload ID.
|
3378 |
+
*
|
3379 |
+
* @since 1.11.0
|
3380 |
+
*
|
3381 |
+
* @return string
|
3382 |
+
*/
|
3383 |
+
public function get_upload_id() {
|
3384 |
+
|
3385 |
+
if ( ! is_string( $this->upload_id ) ) {
|
3386 |
+
|
3387 |
+
$value = get_option( self::OPTION_UPLOAD_ID, '' );
|
3388 |
+
|
3389 |
+
$this->upload_id = is_string( $value ) ? $value : '';
|
3390 |
+
}
|
3391 |
+
|
3392 |
+
/**
|
3393 |
+
* Filters the Facebook upload ID.
|
3394 |
+
*
|
3395 |
+
* @since 1.11.0
|
3396 |
+
*
|
3397 |
+
* @param string $upload_id Facebook upload ID
|
3398 |
+
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
3399 |
+
*/
|
3400 |
+
return (string) apply_filters( 'wc_facebook_upload_id', $this->upload_id, $this );
|
3401 |
+
}
|
3402 |
+
|
3403 |
+
|
3404 |
/**
|
3405 |
* Gets the Facebook pixel install time in UTC seconds.
|
3406 |
*
|
3758 |
}
|
3759 |
|
3760 |
|
3761 |
+
/**
|
3762 |
+
* Updates the Facebook upload ID.
|
3763 |
+
*
|
3764 |
+
* @since 1.11.0
|
3765 |
+
*
|
3766 |
+
* @param string $value upload ID value
|
3767 |
+
*/
|
3768 |
+
public function update_upload_id( $value ) {
|
3769 |
+
|
3770 |
+
$this->upload_id = $this->sanitize_facebook_credential( $value );
|
3771 |
+
|
3772 |
+
update_option( self::OPTION_UPLOAD_ID, $this->upload_id );
|
3773 |
+
}
|
3774 |
+
|
3775 |
+
|
3776 |
/**
|
3777 |
* Updates the Facebook pixel install time.
|
3778 |
*
|
3819 |
}
|
3820 |
|
3821 |
|
3822 |
+
/**
|
3823 |
+
* Sets whether the feed has been migrated from FBE 1 to FBE 1.5.
|
3824 |
+
*
|
3825 |
+
* @since 1.11.0
|
3826 |
+
*
|
3827 |
+
* @param bool $is_migrated whether the feed has been migrated from FBE 1 to FBE 1.5
|
3828 |
+
*/
|
3829 |
+
private function set_feed_migrated( $is_migrated ) {
|
3830 |
+
|
3831 |
+
$this->feed_migrated = (bool) $is_migrated;
|
3832 |
+
|
3833 |
+
update_option( 'wc_facebook_feed_migrated', wc_bool_to_string( $this->feed_migrated ) );
|
3834 |
+
}
|
3835 |
+
|
3836 |
+
|
3837 |
/** Conditional methods *******************************************************************************************/
|
3838 |
|
3839 |
|
3846 |
*/
|
3847 |
public function is_configured() {
|
3848 |
|
3849 |
+
return (bool) $this->get_external_merchant_settings_id();
|
3850 |
}
|
3851 |
|
3852 |
|
3955 |
}
|
3956 |
|
3957 |
|
3958 |
+
/***
|
3959 |
+
* Determines if the feed has been migrated from FBE 1 to FBE 1.5
|
3960 |
+
*
|
3961 |
+
* @since 1.11.0
|
3962 |
+
*
|
3963 |
+
* @return bool
|
3964 |
+
*/
|
3965 |
+
public function is_feed_migrated() {
|
3966 |
+
|
3967 |
+
if ( ! is_bool( $this->feed_migrated ) ) {
|
3968 |
+
|
3969 |
+
$value = get_option( 'wc_facebook_feed_migrated', 'no' );
|
3970 |
+
|
3971 |
+
$this->feed_migrated = wc_string_to_bool( $value );
|
3972 |
+
}
|
3973 |
+
|
3974 |
+
return $this->feed_migrated;
|
3975 |
+
}
|
3976 |
+
|
3977 |
+
|
3978 |
/**
|
3979 |
* Gets message HTML.
|
3980 |
*
|
4068 |
*/
|
4069 |
public function get_page_name() {
|
4070 |
|
4071 |
+
// TODO: replace with `if ( $this->is_configured() ) {` when access tokens become available again {WV 2020-03-31}
|
4072 |
+
if ( $this->get_facebook_page_id() && $this->get_page_access_token() ) {
|
4073 |
$page_name = $this->fbgraph->get_page_name( $this->get_facebook_page_id(), $this->get_page_access_token() );
|
4074 |
} else {
|
4075 |
$page_name = '';
|
4246 |
* Helper function to update FB visibility.
|
4247 |
*/
|
4248 |
function update_fb_visibility( $wp_id, $visibility ) {
|
4249 |
+
|
4250 |
+
// bail if we don't have a page access token or a catalog ID configured
|
4251 |
+
if ( ! $this->get_page_access_token() || ! $this->get_product_catalog_id() ) {
|
4252 |
+
return;
|
4253 |
+
}
|
4254 |
+
|
4255 |
$woo_product = new WC_Facebook_Product( $wp_id );
|
4256 |
+
|
4257 |
if ( ! $woo_product->exists() ) {
|
4258 |
// This function can be called for non-woo products.
|
4259 |
return;
|
4290 |
}
|
4291 |
}
|
4292 |
|
4293 |
+
|
4294 |
+
/**
|
4295 |
+
* Sync product upon quick or bulk edit save action.
|
4296 |
+
*
|
4297 |
+
* @internal
|
4298 |
+
*
|
4299 |
+
* @param \WC_Product $product product object
|
4300 |
+
*/
|
4301 |
+
public function on_quick_and_bulk_edit_save( $product ) {
|
4302 |
|
4303 |
// bail if not a product or product is not enabled for sync
|
4304 |
+
if ( ! $product instanceof \WC_Product || ! Products::product_should_be_synced( $product ) ) {
|
4305 |
return;
|
4306 |
}
|
4307 |
|
4308 |
$wp_id = $product->get_id();
|
4309 |
+
$visibility = get_post_status( $wp_id ) === 'publish' ? self::FB_SHOP_PRODUCT_VISIBLE : self::FB_SHOP_PRODUCT_HIDDEN;
|
4310 |
+
|
|
|
|
|
4311 |
if ( $visibility === self::FB_SHOP_PRODUCT_VISIBLE ) {
|
4312 |
+
// - new status is 'publish' regardless of old status, sync to Facebook
|
4313 |
$this->on_product_publish( $wp_id );
|
4314 |
} else {
|
4315 |
+
// - product never published to Facebook, new status is not publish
|
4316 |
+
// - product new status is not publish but may have been published before
|
4317 |
$this->update_fb_visibility( $wp_id, $visibility );
|
4318 |
}
|
4319 |
}
|
4573 |
}
|
4574 |
|
4575 |
|
4576 |
+
/**
|
4577 |
+
* Handles the schedule feed generation action, triggered by the REST API.
|
4578 |
+
*
|
4579 |
+
* @since 1.11.0
|
4580 |
+
*/
|
4581 |
+
public function handle_generate_product_catalog_feed() {
|
4582 |
+
|
4583 |
+
$feed_handler = new WC_Facebook_Product_Feed();
|
4584 |
+
|
4585 |
+
try {
|
4586 |
+
|
4587 |
+
$feed_handler->generate_feed();
|
4588 |
+
|
4589 |
+
} catch ( \Exception $exception ) {
|
4590 |
+
|
4591 |
+
WC_Facebookcommerce_Utils::log( 'Error generating product catalog feed. ' . $exception->getMessage() );
|
4592 |
+
}
|
4593 |
+
}
|
4594 |
+
|
4595 |
+
/**
|
4596 |
+
* Enables product sync delay admin notice.
|
4597 |
+
*
|
4598 |
+
* @since 1.11.0
|
4599 |
+
*/
|
4600 |
+
private function enable_product_sync_delay_admin_notice() {
|
4601 |
+
|
4602 |
+
set_transient( 'wc_' . facebook_for_woocommerce()->get_id() . '_show_product_sync_delay_notice_' . get_current_user_id(), true, MINUTE_IN_SECONDS );
|
4603 |
+
}
|
4604 |
+
|
4605 |
+
|
4606 |
}
|
facebook-for-woocommerce.php
CHANGED
@@ -10,11 +10,10 @@
|
|
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.
|
14 |
-
* Woo: 2127297:0ea4fe4c2d7ca6338f8a322fb3e4e187
|
15 |
* Text Domain: facebook-for-woocommerce
|
16 |
* WC requires at least: 3.5.0
|
17 |
-
* WC tested up to: 4.0.
|
18 |
*
|
19 |
* @package FacebookCommerce
|
20 |
*/
|
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.11.0
|
|
|
14 |
* Text Domain: facebook-for-woocommerce
|
15 |
* WC requires at least: 3.5.0
|
16 |
+
* WC tested up to: 4.0.1
|
17 |
*
|
18 |
* @package FacebookCommerce
|
19 |
*/
|
i18n/languages/facebook-for-woocommerce.pot
CHANGED
@@ -2,10 +2,10 @@
|
|
2 |
# This file is distributed under the same license as the Facebook for WooCommerce package.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
-
"Project-Id-Version: Facebook for WooCommerce 1.
|
6 |
"Report-Msgid-Bugs-To: "
|
7 |
"https://woocommerce.com/my-account/marketplace-ticket-form/\n"
|
8 |
-
"POT-Creation-Date: 2020-
|
9 |
"MIME-Version: 1.0\n"
|
10 |
"Content-Type: text/plain; charset=utf-8\n"
|
11 |
"Content-Transfer-Encoding: 8bit\n"
|
@@ -13,48 +13,64 @@ msgstr ""
|
|
13 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
14 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
#. Plugin Name of the plugin/theme
|
17 |
msgid "Facebook for WooCommerce"
|
18 |
msgstr ""
|
19 |
|
20 |
-
#: facebook-commerce.php:
|
21 |
msgid "Facebook Commerce and Dynamic Ads (Pixel) Extension"
|
22 |
msgstr ""
|
23 |
|
24 |
-
#: facebook-commerce.php:
|
25 |
msgid "Facebook ID:"
|
26 |
msgstr ""
|
27 |
|
28 |
-
#: facebook-commerce.php:
|
29 |
msgid "Variant IDs:"
|
30 |
msgstr ""
|
31 |
|
32 |
-
#: facebook-commerce.php:
|
33 |
-
msgid "Visible:"
|
34 |
-
msgstr ""
|
35 |
-
|
36 |
-
#: facebook-commerce.php:634
|
37 |
msgid "Reset Facebook metadata"
|
38 |
msgstr ""
|
39 |
|
40 |
-
#: facebook-commerce.php:
|
41 |
msgid "Delete product(s) on Facebook"
|
42 |
msgstr ""
|
43 |
|
44 |
-
#: facebook-commerce.php:
|
45 |
msgid "This product is not yet synced to Facebook."
|
46 |
msgstr ""
|
47 |
|
48 |
-
#: facebook-commerce.php:
|
49 |
msgid "Nothing to update for product group for %1$s"
|
50 |
msgstr ""
|
51 |
|
52 |
-
#: facebook-commerce.php:
|
53 |
#. translators: Placeholders %1$s - original error message from Facebook API
|
54 |
msgid "There was an issue connecting to the Facebook API: %1$s"
|
55 |
msgstr ""
|
56 |
|
57 |
-
#: facebook-commerce.php:
|
58 |
#. translators: Placeholders %1$s - opening strong HTML tag, %2$s - closing
|
59 |
#. strong HTML tag, %3$s - opening link HTML tag, %4$s - closing link HTML tag
|
60 |
msgid ""
|
@@ -62,43 +78,43 @@ msgid ""
|
|
62 |
"configuration, %3$scomplete the setup steps%4$s."
|
63 |
msgstr ""
|
64 |
|
65 |
-
#: facebook-commerce.php:
|
66 |
#. translators: Placeholders %1$s - WooCommerce version
|
67 |
msgid ""
|
68 |
"Facebook product sync may not work correctly in WooCommerce version %1$s. "
|
69 |
"Please upgrade to WooCommerce 3."
|
70 |
msgstr ""
|
71 |
|
72 |
-
#: facebook-commerce.php:
|
73 |
msgid "Your connection has expired."
|
74 |
msgstr ""
|
75 |
|
76 |
-
#: facebook-commerce.php:
|
77 |
msgid ""
|
78 |
"Please click Manage connection > Advanced Options > Update Token to refresh "
|
79 |
"your connection to Facebook."
|
80 |
msgstr ""
|
81 |
|
82 |
-
#: facebook-commerce.php:
|
83 |
#. translators: Placeholders %s - error message
|
84 |
msgid "There was an error trying to sync the products to Facebook. %s"
|
85 |
msgstr ""
|
86 |
|
87 |
-
#: facebook-commerce.php:
|
88 |
msgid "Product sync is disabled."
|
89 |
msgstr ""
|
90 |
|
91 |
-
#: facebook-commerce.php:
|
92 |
msgid "The page access token or product catalog ID are missing."
|
93 |
msgstr ""
|
94 |
|
95 |
-
#: facebook-commerce.php:
|
96 |
msgid ""
|
97 |
"A product sync is in progress. Please wait until the sync finishes before "
|
98 |
"starting a new one."
|
99 |
msgstr ""
|
100 |
|
101 |
-
#: facebook-commerce.php:
|
102 |
msgid ""
|
103 |
"We've detected that your Facebook Product Catalog is no longer valid. This "
|
104 |
"may happen if it was deleted, but could also be a temporary error. If the "
|
@@ -106,19 +122,19 @@ msgid ""
|
|
106 |
"and setup the plugin again."
|
107 |
msgstr ""
|
108 |
|
109 |
-
#: facebook-commerce.php:
|
110 |
msgid "We couldn't create the feed or upload the product information."
|
111 |
msgstr ""
|
112 |
|
113 |
-
#: facebook-commerce.php:
|
114 |
msgid "Hi! We're here to answer any questions you may have."
|
115 |
msgstr ""
|
116 |
|
117 |
-
#: facebook-commerce.php:
|
118 |
msgid "Use Advanced Matching"
|
119 |
msgstr ""
|
120 |
|
121 |
-
#: facebook-commerce.php:
|
122 |
#. translators: Placeholders: %1$s - opening <a> HTML link tag, %2$s - closing
|
123 |
#. </a> HTML link tag
|
124 |
msgid ""
|
@@ -127,160 +143,144 @@ msgid ""
|
|
127 |
"number). %1$sLearn more%2$s."
|
128 |
msgstr ""
|
129 |
|
130 |
-
#: facebook-commerce.php:
|
|
|
|
|
|
|
|
|
131 |
msgid "Enable product sync"
|
132 |
msgstr ""
|
133 |
|
134 |
-
#: facebook-commerce.php:
|
135 |
msgid "Exclude categories from sync"
|
136 |
msgstr ""
|
137 |
|
138 |
-
#: facebook-commerce.php:
|
139 |
msgid "Products in one or more of these categories will not sync to Facebook."
|
140 |
msgstr ""
|
141 |
|
142 |
-
#: facebook-commerce.php:
|
143 |
msgid "Search for a product category…"
|
144 |
msgstr ""
|
145 |
|
146 |
-
#: facebook-commerce.php:
|
147 |
msgid "Exclude tags from sync"
|
148 |
msgstr ""
|
149 |
|
150 |
-
#: facebook-commerce.php:
|
151 |
msgid "Products with one or more of these tags will not sync to Facebook."
|
152 |
msgstr ""
|
153 |
|
154 |
-
#: facebook-commerce.php:
|
155 |
msgid "Search for a product tag…"
|
156 |
msgstr ""
|
157 |
|
158 |
-
#: facebook-commerce.php:
|
159 |
msgid "Product description sync"
|
160 |
msgstr ""
|
161 |
|
162 |
-
#: facebook-commerce.php:
|
163 |
msgid "Choose which product description to display in the Facebook catalog."
|
164 |
msgstr ""
|
165 |
|
166 |
-
#: facebook-commerce.php:
|
167 |
msgid "Standard description"
|
168 |
msgstr ""
|
169 |
|
170 |
-
#: facebook-commerce.php:
|
171 |
msgid "Short description"
|
172 |
msgstr ""
|
173 |
|
174 |
-
#: facebook-commerce.php:
|
175 |
-
msgid "Force daily resync at"
|
176 |
-
msgstr ""
|
177 |
-
|
178 |
-
#: facebook-commerce.php:2507
|
179 |
msgid "Messenger"
|
180 |
msgstr ""
|
181 |
|
182 |
-
#: facebook-commerce.php:
|
183 |
msgid "Enable Messenger"
|
184 |
msgstr ""
|
185 |
|
186 |
-
#: facebook-commerce.php:
|
187 |
msgid "Enable and customize Facebook Messenger on your store."
|
188 |
msgstr ""
|
189 |
|
190 |
-
#: facebook-commerce.php:
|
191 |
msgid "Language"
|
192 |
msgstr ""
|
193 |
|
194 |
-
#: facebook-commerce.php:
|
195 |
msgid "Greeting"
|
196 |
msgstr ""
|
197 |
|
198 |
-
#: facebook-commerce.php:
|
199 |
msgid "Colors"
|
200 |
msgstr ""
|
201 |
|
202 |
-
#: facebook-commerce.php:
|
203 |
msgid "Debug"
|
204 |
msgstr ""
|
205 |
|
206 |
-
#: facebook-commerce.php:
|
207 |
msgid "Enable debug mode"
|
208 |
msgstr ""
|
209 |
|
210 |
-
#: facebook-commerce.php:
|
211 |
msgid "Log plugin events for debugging"
|
212 |
msgstr ""
|
213 |
|
214 |
-
#: facebook-commerce.php:
|
215 |
msgid "Only enable this if you are experiencing problems with the plugin."
|
216 |
msgstr ""
|
217 |
|
218 |
-
#: facebook-commerce.php:
|
219 |
msgid "Connection"
|
220 |
msgstr ""
|
221 |
|
222 |
-
#: facebook-commerce.php:
|
223 |
msgid "Manage connection"
|
224 |
msgstr ""
|
225 |
|
226 |
-
#: facebook-commerce.php:
|
227 |
-
msgid "Your access token has been updated."
|
228 |
-
msgstr ""
|
229 |
-
|
230 |
-
#: facebook-commerce.php:2617
|
231 |
-
msgid "Please refresh the page."
|
232 |
-
msgstr ""
|
233 |
-
|
234 |
-
#: facebook-commerce.php:2651
|
235 |
-
msgid "Facebook page"
|
236 |
-
msgstr ""
|
237 |
-
|
238 |
-
#: facebook-commerce.php:2715
|
239 |
msgid "Pixel"
|
240 |
msgstr ""
|
241 |
|
242 |
-
#: facebook-commerce.php:
|
243 |
msgid "Create ad"
|
244 |
msgstr ""
|
245 |
|
246 |
-
#: facebook-commerce.php:
|
247 |
-
msgid "Product sync"
|
248 |
-
msgstr ""
|
249 |
-
|
250 |
-
#: facebook-commerce.php:2796
|
251 |
msgid "Sync products"
|
252 |
msgstr ""
|
253 |
|
254 |
-
#: facebook-commerce.php:
|
255 |
msgid "am"
|
256 |
msgstr ""
|
257 |
|
258 |
-
#: facebook-commerce.php:
|
259 |
msgid "pm"
|
260 |
msgstr ""
|
261 |
|
262 |
-
#: facebook-commerce.php:
|
263 |
msgid "The greeting hasn't been updated."
|
264 |
msgstr ""
|
265 |
|
266 |
-
#: facebook-commerce.php:
|
267 |
#. translators: Placeholder: %d - maximum number of allowed characters
|
268 |
msgid "The Messenger greeting must be %d characters or less."
|
269 |
msgstr ""
|
270 |
|
271 |
-
#: facebook-commerce.php:
|
272 |
msgid "Facebook for WooCommerce error:"
|
273 |
msgstr ""
|
274 |
|
275 |
-
#: facebook-commerce.php:
|
276 |
msgid "Get started with Messenger Customer Chat"
|
277 |
msgstr ""
|
278 |
|
279 |
-
#: facebook-commerce.php:
|
280 |
msgid "Get started with Instagram Shopping"
|
281 |
msgstr ""
|
282 |
|
283 |
-
#: facebook-commerce.php:
|
284 |
msgid ""
|
285 |
"You're using Remove HTTP which has incompatibilities with our extension. "
|
286 |
"Please disable it, or select the \"Ignore external links\" option on the "
|
@@ -291,62 +291,62 @@ msgstr ""
|
|
291 |
msgid "Facebook"
|
292 |
msgstr ""
|
293 |
|
294 |
-
#: facebook-commerce.php:
|
295 |
msgid "Control how WooCommerce integrates with your Facebook store."
|
296 |
msgstr ""
|
297 |
|
298 |
-
#: facebook-commerce.php:
|
299 |
msgid "Grow your business on Facebook"
|
300 |
msgstr ""
|
301 |
|
302 |
-
#: facebook-commerce.php:
|
303 |
msgid "Use this WooCommerce and Facebook integration to:"
|
304 |
msgstr ""
|
305 |
|
306 |
-
#: facebook-commerce.php:
|
307 |
msgid "Easily install a tracking pixel"
|
308 |
msgstr ""
|
309 |
|
310 |
-
#: facebook-commerce.php:
|
311 |
msgid "Upload your products and create a shop"
|
312 |
msgstr ""
|
313 |
|
314 |
-
#: facebook-commerce.php:
|
315 |
msgid "Create dynamic ads with your products and pixel"
|
316 |
msgstr ""
|
317 |
|
318 |
-
#: facebook-commerce.php:
|
319 |
msgid "Get Started"
|
320 |
msgstr ""
|
321 |
|
322 |
-
#: facebook-commerce.php:
|
323 |
#. translators: Placeholders %1$s - original error message from Facebook API
|
324 |
msgid "There was an issue connecting to the Facebook API: %s"
|
325 |
msgstr ""
|
326 |
|
327 |
-
#: includes/AJAX.php:
|
328 |
msgid "Hide Product"
|
329 |
msgstr ""
|
330 |
|
331 |
-
#: includes/AJAX.php:
|
332 |
msgid "Do Not Hide Product"
|
333 |
msgstr ""
|
334 |
|
335 |
-
#: includes/AJAX.php:
|
336 |
msgid ""
|
337 |
"This product will no longer be updated in your Facebook catalog. Would you "
|
338 |
"like to hide this product from your Facebook shop?"
|
339 |
msgstr ""
|
340 |
|
341 |
-
#: includes/AJAX.php:
|
342 |
msgid "Go to Settings"
|
343 |
msgstr ""
|
344 |
|
345 |
-
#: includes/AJAX.php:
|
346 |
msgid "Cancel"
|
347 |
msgstr ""
|
348 |
|
349 |
-
#: includes/AJAX.php:
|
350 |
#. translators: Placeholder %s - <br/> tag
|
351 |
msgid ""
|
352 |
"This product belongs to a category or tag that is excluded from the "
|
@@ -355,21 +355,21 @@ msgid ""
|
|
355 |
"or click Cancel and update the product's category / tag assignments."
|
356 |
msgstr ""
|
357 |
|
358 |
-
#: includes/AJAX.php:
|
359 |
msgid "Hide Products"
|
360 |
msgstr ""
|
361 |
|
362 |
-
#: includes/AJAX.php:
|
363 |
msgid "Do Not Hide Products"
|
364 |
msgstr ""
|
365 |
|
366 |
-
#: includes/AJAX.php:
|
367 |
msgid ""
|
368 |
"The selected products will no longer be updated in your Facebook catalog. "
|
369 |
"Would you like to hide these products from your Facebook shop?"
|
370 |
msgstr ""
|
371 |
|
372 |
-
#: includes/AJAX.php:
|
373 |
msgid ""
|
374 |
"One or more of the selected products belongs to a category or tag that is "
|
375 |
"excluded from the Facebook catalog sync. To sync these products to "
|
@@ -377,15 +377,15 @@ msgid ""
|
|
377 |
"settings."
|
378 |
msgstr ""
|
379 |
|
380 |
-
#: includes/AJAX.php:
|
381 |
msgid "Exclude Products"
|
382 |
msgstr ""
|
383 |
|
384 |
-
#: includes/AJAX.php:
|
385 |
msgid "Exclude Products and Hide in Facebook"
|
386 |
msgstr ""
|
387 |
|
388 |
-
#: includes/AJAX.php:
|
389 |
#. translators: Placeholder %s - <br/> tags
|
390 |
msgid ""
|
391 |
"The categories and/or tags that you have selected to exclude from sync "
|
@@ -394,7 +394,7 @@ msgid ""
|
|
394 |
"category / tag exclusion settings, click Cancel."
|
395 |
msgstr ""
|
396 |
|
397 |
-
#: includes/Admin.php:
|
398 |
#. translators: Placeholders %1$s - opening <strong> html tag, %2$s closing
|
399 |
#. </strong> html tag, {count} number of remaining items
|
400 |
msgid "%1$sProgress:%2$s {count} item remaining."
|
@@ -402,16 +402,16 @@ msgid_plural "%1$sProgress:%2$s {count} items remaining."
|
|
402 |
msgstr[0] ""
|
403 |
msgstr[1] ""
|
404 |
|
405 |
-
#: includes/Admin.php:
|
406 |
#. translators: Placeholders %s - html code for a spinner icon
|
407 |
msgid "Your products will now be resynced to Facebook, this may take some time."
|
408 |
msgstr ""
|
409 |
|
410 |
-
#: includes/Admin.php:
|
411 |
msgid "Launch Test?"
|
412 |
msgstr ""
|
413 |
|
414 |
-
#: includes/Admin.php:
|
415 |
msgid ""
|
416 |
"Facebook for WooCommerce automatically syncs your products on "
|
417 |
"create/update. Are you sure you want to force product resync?\n"
|
@@ -421,112 +421,108 @@ msgid ""
|
|
421 |
"did not sync."
|
422 |
msgstr ""
|
423 |
|
424 |
-
#: includes/Admin.php:
|
425 |
msgid "Syncing... Keep this browser open until sync is complete. %s"
|
426 |
msgstr ""
|
427 |
|
428 |
-
#: includes/Admin.php:
|
429 |
#. translators: Placeholders %1$s - opening <strong> html tag, %2$s closing
|
430 |
#. </strong> html tag
|
431 |
msgid "%1$sStatus:%2$s Test Pass."
|
432 |
msgstr ""
|
433 |
|
434 |
-
#: includes/Admin.php:
|
435 |
#. translators: Placeholders %1$s - opening <strong> html tag, %2$s closing
|
436 |
#. </strong> html tag
|
437 |
msgid "%1$sStatus:%2$s Integration test in progress..."
|
438 |
msgstr ""
|
439 |
|
440 |
-
#: includes/Admin.php:
|
441 |
#. translators: Placeholders %1$s - opening <strong> html tag, %2$s closing
|
442 |
#. </strong> html tag
|
443 |
msgid "%1$sStatus:%2$s Test Fail."
|
444 |
msgstr ""
|
445 |
|
446 |
-
#: includes/Admin.php:
|
447 |
msgid "There was an error trying to sync the products to Facebook."
|
448 |
msgstr ""
|
449 |
|
450 |
-
#: includes/Admin.php:
|
451 |
msgid ""
|
452 |
"Something went wrong while uploading the product information, please try "
|
453 |
"again."
|
454 |
msgstr ""
|
455 |
|
456 |
-
#: includes/Admin.php:
|
457 |
msgid "FB Sync Enabled"
|
458 |
msgstr ""
|
459 |
|
460 |
-
#: includes/Admin.php:
|
461 |
-
msgid "FB Catalog Visibility"
|
462 |
-
msgstr ""
|
463 |
-
|
464 |
-
#: includes/Admin.php:177
|
465 |
msgid "Enabled"
|
466 |
msgstr ""
|
467 |
|
468 |
-
#: includes/Admin.php:
|
469 |
msgid "Disabled"
|
470 |
msgstr ""
|
471 |
|
472 |
-
#: includes/Admin.php:
|
473 |
#. translators: Points to a product that was never synced with Facebook
|
474 |
msgid "Never synced with Facebook."
|
475 |
msgstr ""
|
476 |
|
477 |
-
#: includes/Admin.php:
|
478 |
#. translators: Action to hide a product (currently synced with Facebook) from
|
479 |
#. the Facebook catalog
|
480 |
msgid "Hide from Facebook catalog. Currently synced with Facebook."
|
481 |
msgstr ""
|
482 |
|
483 |
-
#: includes/Admin.php:
|
484 |
#. translators: Action to publish a product (currently synced with Facebook) in
|
485 |
#. the Facebook catalog
|
486 |
msgid "Publish in Facebook catalog. Currently synced with Facebook."
|
487 |
msgstr ""
|
488 |
|
489 |
-
#: includes/Admin.php:
|
490 |
#. translators: Action to hide a product (currently not synced with Facebook)
|
491 |
#. from the Facebook catalog
|
492 |
msgid "Hide from Facebook catalog. Not synced with Facebook."
|
493 |
msgstr ""
|
494 |
|
495 |
-
#: includes/Admin.php:
|
496 |
#. translators: Action to publish a product (currently not synced with
|
497 |
#. Facebook) in the Facebook catalog
|
498 |
msgid "Publish in Facebook catalog. Not synced with Facebook."
|
499 |
msgstr ""
|
500 |
|
501 |
-
#: includes/Admin.php:
|
502 |
msgid "Show"
|
503 |
msgstr ""
|
504 |
|
505 |
-
#: includes/Admin.php:
|
506 |
msgid "Hide"
|
507 |
msgstr ""
|
508 |
|
509 |
-
#: includes/Admin.php:
|
510 |
msgid "Filter by Facebook sync setting"
|
511 |
msgstr ""
|
512 |
|
513 |
-
#: includes/Admin.php:
|
514 |
msgid "Facebook sync enabled"
|
515 |
msgstr ""
|
516 |
|
517 |
-
#: includes/Admin.php:
|
518 |
msgid "Facebook sync disabled"
|
519 |
msgstr ""
|
520 |
|
521 |
-
#: includes/Admin.php:
|
522 |
msgid "Include in Facebook sync"
|
523 |
msgstr ""
|
524 |
|
525 |
-
#: includes/Admin.php:
|
526 |
msgid "Exclude from Facebook sync"
|
527 |
msgstr ""
|
528 |
|
529 |
-
#: includes/Admin.php:
|
530 |
#. translators: Placeholders: %1$s - Facebook for Woocommerce, %2$s - opening
|
531 |
#. HTML <a> link tag, %3$s - closing HTML </a> link tag
|
532 |
msgid ""
|
@@ -535,61 +531,86 @@ msgid ""
|
|
535 |
"checkout URLs on Facebook%3$s."
|
536 |
msgstr ""
|
537 |
|
538 |
-
#: includes/Admin.php:579
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
539 |
msgid "Facebook Description"
|
540 |
msgstr ""
|
541 |
|
542 |
-
#: includes/Admin.php:
|
543 |
msgid ""
|
544 |
"Custom (plain-text only) description for product on Facebook. If blank, "
|
545 |
"product description will be used. If product description is blank, "
|
546 |
"shortname will be used."
|
547 |
msgstr ""
|
548 |
|
549 |
-
#: includes/Admin.php:
|
550 |
msgid "Facebook Product Image"
|
551 |
msgstr ""
|
552 |
|
553 |
-
#: includes/Admin.php:
|
554 |
msgid ""
|
555 |
"Choose the product image that should be synced to the Facebook catalog for "
|
556 |
"this product. If using a custom image, please enter an absolute URL (e.g. "
|
557 |
"https://domain.com/image.jpg)."
|
558 |
msgstr ""
|
559 |
|
560 |
-
#: includes/Admin.php:
|
561 |
msgid "Use WooCommerce image"
|
562 |
msgstr ""
|
563 |
|
564 |
-
#: includes/Admin.php:
|
565 |
msgid "Use custom image"
|
566 |
msgstr ""
|
567 |
|
568 |
-
#: includes/Admin.php:
|
569 |
msgid "Custom Image URL"
|
570 |
msgstr ""
|
571 |
|
572 |
-
#: includes/Admin.php:
|
573 |
#. translators: Placeholders %1$s - WC currency symbol
|
574 |
msgid "Facebook Price (%1$s)"
|
575 |
msgstr ""
|
576 |
|
577 |
-
#: includes/Admin.php:
|
578 |
msgid ""
|
579 |
"Custom price for product on Facebook. Please enter in monetary decimal (.) "
|
580 |
"format without thousand separators and currency symbols. If blank, product "
|
581 |
"price will be used."
|
582 |
msgstr ""
|
583 |
|
584 |
-
#: includes/Admin.php:
|
585 |
msgid "Use variation image"
|
586 |
msgstr ""
|
587 |
|
588 |
-
#: includes/Admin.php:
|
589 |
msgid "Use parent image"
|
590 |
msgstr ""
|
591 |
|
592 |
-
#: includes/Admin.php:
|
593 |
msgid "Close modal panel"
|
594 |
msgstr ""
|
595 |
|
@@ -609,6 +630,14 @@ msgstr ""
|
|
609 |
msgid "Dismiss"
|
610 |
msgstr ""
|
611 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
612 |
#: includes/fbwpml.php:105
|
613 |
msgid "Facebook Visibility"
|
614 |
msgstr ""
|
@@ -646,7 +675,7 @@ msgstr ""
|
|
646 |
msgid "https://www.facebook.com/"
|
647 |
msgstr ""
|
648 |
|
649 |
-
#: facebook-commerce-messenger-chat.php:258 facebook-commerce.php:
|
650 |
msgctxt "language"
|
651 |
msgid "English (United States)"
|
652 |
msgstr ""
|
2 |
# This file is distributed under the same license as the Facebook for WooCommerce package.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
+
"Project-Id-Version: Facebook for WooCommerce 1.11.0\n"
|
6 |
"Report-Msgid-Bugs-To: "
|
7 |
"https://woocommerce.com/my-account/marketplace-ticket-form/\n"
|
8 |
+
"POT-Creation-Date: 2020-04-23 23:00:28+00:00\n"
|
9 |
"MIME-Version: 1.0\n"
|
10 |
"Content-Type: text/plain; charset=utf-8\n"
|
11 |
"Content-Transfer-Encoding: 8bit\n"
|
13 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
14 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
15 |
|
16 |
+
#: class-wc-facebookcommerce.php:142
|
17 |
+
#. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
|
18 |
+
#. <a> tag, %4$s - </a> tag, %5$s - <a> tag, %6$s - </a> tag
|
19 |
+
msgid ""
|
20 |
+
"%1$sHeads up!%2$s Facebook for WooCommerce is migrating to a more secure "
|
21 |
+
"connection experience. Please %3$sclick here%4$s and go to %1$sAdvanced "
|
22 |
+
"Options%2$s > %1$sReconnect Catalog%2$s to securely reconnect. %5$sLearn "
|
23 |
+
"more%6$s."
|
24 |
+
msgstr ""
|
25 |
+
|
26 |
+
#: class-wc-facebookcommerce.php:152
|
27 |
+
#. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
|
28 |
+
#. <a> tag, %4$s - </a> tag, %5$s - <a> tag, %6$s - </a> tag
|
29 |
+
msgid ""
|
30 |
+
"%1$sHeads up!%2$s Facebook for WooCommerce is migrating to a more secure "
|
31 |
+
"connection experience. Please %3$sclick here%4$s and go to %1$sManage "
|
32 |
+
"Connection%2$s > %1$sAdvanced Options%2$s > %1$sReconnect Catalog%2$s to "
|
33 |
+
"securely reconnect. %5$sLearn more%6$s."
|
34 |
+
msgstr ""
|
35 |
+
|
36 |
#. Plugin Name of the plugin/theme
|
37 |
msgid "Facebook for WooCommerce"
|
38 |
msgstr ""
|
39 |
|
40 |
+
#: facebook-commerce.php:198
|
41 |
msgid "Facebook Commerce and Dynamic Ads (Pixel) Extension"
|
42 |
msgstr ""
|
43 |
|
44 |
+
#: facebook-commerce.php:598
|
45 |
msgid "Facebook ID:"
|
46 |
msgstr ""
|
47 |
|
48 |
+
#: facebook-commerce.php:609
|
49 |
msgid "Variant IDs:"
|
50 |
msgstr ""
|
51 |
|
52 |
+
#: facebook-commerce.php:649
|
|
|
|
|
|
|
|
|
53 |
msgid "Reset Facebook metadata"
|
54 |
msgstr ""
|
55 |
|
56 |
+
#: facebook-commerce.php:654
|
57 |
msgid "Delete product(s) on Facebook"
|
58 |
msgstr ""
|
59 |
|
60 |
+
#: facebook-commerce.php:662
|
61 |
msgid "This product is not yet synced to Facebook."
|
62 |
msgstr ""
|
63 |
|
64 |
+
#: facebook-commerce.php:1340
|
65 |
msgid "Nothing to update for product group for %1$s"
|
66 |
msgstr ""
|
67 |
|
68 |
+
#: facebook-commerce.php:1788
|
69 |
#. translators: Placeholders %1$s - original error message from Facebook API
|
70 |
msgid "There was an issue connecting to the Facebook API: %1$s"
|
71 |
msgstr ""
|
72 |
|
73 |
+
#: facebook-commerce.php:1922
|
74 |
#. translators: Placeholders %1$s - opening strong HTML tag, %2$s - closing
|
75 |
#. strong HTML tag, %3$s - opening link HTML tag, %4$s - closing link HTML tag
|
76 |
msgid ""
|
78 |
"configuration, %3$scomplete the setup steps%4$s."
|
79 |
msgstr ""
|
80 |
|
81 |
+
#: facebook-commerce.php:1941
|
82 |
#. translators: Placeholders %1$s - WooCommerce version
|
83 |
msgid ""
|
84 |
"Facebook product sync may not work correctly in WooCommerce version %1$s. "
|
85 |
"Please upgrade to WooCommerce 3."
|
86 |
msgstr ""
|
87 |
|
88 |
+
#: facebook-commerce.php:2160
|
89 |
msgid "Your connection has expired."
|
90 |
msgstr ""
|
91 |
|
92 |
+
#: facebook-commerce.php:2160
|
93 |
msgid ""
|
94 |
"Please click Manage connection > Advanced Options > Update Token to refresh "
|
95 |
"your connection to Facebook."
|
96 |
msgstr ""
|
97 |
|
98 |
+
#: facebook-commerce.php:2167
|
99 |
#. translators: Placeholders %s - error message
|
100 |
msgid "There was an error trying to sync the products to Facebook. %s"
|
101 |
msgstr ""
|
102 |
|
103 |
+
#: facebook-commerce.php:2190 facebook-commerce.php:2369
|
104 |
msgid "Product sync is disabled."
|
105 |
msgstr ""
|
106 |
|
107 |
+
#: facebook-commerce.php:2197 facebook-commerce.php:2376
|
108 |
msgid "The page access token or product catalog ID are missing."
|
109 |
msgstr ""
|
110 |
|
111 |
+
#: facebook-commerce.php:2220
|
112 |
msgid ""
|
113 |
"A product sync is in progress. Please wait until the sync finishes before "
|
114 |
"starting a new one."
|
115 |
msgstr ""
|
116 |
|
117 |
+
#: facebook-commerce.php:2232 facebook-commerce.php:2390
|
118 |
msgid ""
|
119 |
"We've detected that your Facebook Product Catalog is no longer valid. This "
|
120 |
"may happen if it was deleted, but could also be a temporary error. If the "
|
122 |
"and setup the plugin again."
|
123 |
msgstr ""
|
124 |
|
125 |
+
#: facebook-commerce.php:2420
|
126 |
msgid "We couldn't create the feed or upload the product information."
|
127 |
msgstr ""
|
128 |
|
129 |
+
#: facebook-commerce.php:2511
|
130 |
msgid "Hi! We're here to answer any questions you may have."
|
131 |
msgstr ""
|
132 |
|
133 |
+
#: facebook-commerce.php:2534
|
134 |
msgid "Use Advanced Matching"
|
135 |
msgstr ""
|
136 |
|
137 |
+
#: facebook-commerce.php:2537
|
138 |
#. translators: Placeholders: %1$s - opening <a> HTML link tag, %2$s - closing
|
139 |
#. </a> HTML link tag
|
140 |
msgid ""
|
143 |
"number). %1$sLearn more%2$s."
|
144 |
msgstr ""
|
145 |
|
146 |
+
#: facebook-commerce.php:2554 facebook-commerce.php:2901
|
147 |
+
msgid "Product sync"
|
148 |
+
msgstr ""
|
149 |
+
|
150 |
+
#: facebook-commerce.php:2558
|
151 |
msgid "Enable product sync"
|
152 |
msgstr ""
|
153 |
|
154 |
+
#: facebook-commerce.php:2566
|
155 |
msgid "Exclude categories from sync"
|
156 |
msgstr ""
|
157 |
|
158 |
+
#: facebook-commerce.php:2570
|
159 |
msgid "Products in one or more of these categories will not sync to Facebook."
|
160 |
msgstr ""
|
161 |
|
162 |
+
#: facebook-commerce.php:2574
|
163 |
msgid "Search for a product category…"
|
164 |
msgstr ""
|
165 |
|
166 |
+
#: facebook-commerce.php:2579
|
167 |
msgid "Exclude tags from sync"
|
168 |
msgstr ""
|
169 |
|
170 |
+
#: facebook-commerce.php:2583
|
171 |
msgid "Products with one or more of these tags will not sync to Facebook."
|
172 |
msgstr ""
|
173 |
|
174 |
+
#: facebook-commerce.php:2587
|
175 |
msgid "Search for a product tag…"
|
176 |
msgstr ""
|
177 |
|
178 |
+
#: facebook-commerce.php:2592
|
179 |
msgid "Product description sync"
|
180 |
msgstr ""
|
181 |
|
182 |
+
#: facebook-commerce.php:2595
|
183 |
msgid "Choose which product description to display in the Facebook catalog."
|
184 |
msgstr ""
|
185 |
|
186 |
+
#: facebook-commerce.php:2598
|
187 |
msgid "Standard description"
|
188 |
msgstr ""
|
189 |
|
190 |
+
#: facebook-commerce.php:2599
|
191 |
msgid "Short description"
|
192 |
msgstr ""
|
193 |
|
194 |
+
#: facebook-commerce.php:2612
|
|
|
|
|
|
|
|
|
195 |
msgid "Messenger"
|
196 |
msgstr ""
|
197 |
|
198 |
+
#: facebook-commerce.php:2617
|
199 |
msgid "Enable Messenger"
|
200 |
msgstr ""
|
201 |
|
202 |
+
#: facebook-commerce.php:2621
|
203 |
msgid "Enable and customize Facebook Messenger on your store."
|
204 |
msgstr ""
|
205 |
|
206 |
+
#: facebook-commerce.php:2626
|
207 |
msgid "Language"
|
208 |
msgstr ""
|
209 |
|
210 |
+
#: facebook-commerce.php:2639
|
211 |
msgid "Greeting"
|
212 |
msgstr ""
|
213 |
|
214 |
+
#: facebook-commerce.php:2651
|
215 |
msgid "Colors"
|
216 |
msgstr ""
|
217 |
|
218 |
+
#: facebook-commerce.php:2662
|
219 |
msgid "Debug"
|
220 |
msgstr ""
|
221 |
|
222 |
+
#: facebook-commerce.php:2667
|
223 |
msgid "Enable debug mode"
|
224 |
msgstr ""
|
225 |
|
226 |
+
#: facebook-commerce.php:2669
|
227 |
msgid "Log plugin events for debugging"
|
228 |
msgstr ""
|
229 |
|
230 |
+
#: facebook-commerce.php:2670
|
231 |
msgid "Only enable this if you are experiencing problems with the plugin."
|
232 |
msgstr ""
|
233 |
|
234 |
+
#: facebook-commerce.php:2700
|
235 |
msgid "Connection"
|
236 |
msgstr ""
|
237 |
|
238 |
+
#: facebook-commerce.php:2707
|
239 |
msgid "Manage connection"
|
240 |
msgstr ""
|
241 |
|
242 |
+
#: facebook-commerce.php:2825
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
243 |
msgid "Pixel"
|
244 |
msgstr ""
|
245 |
|
246 |
+
#: facebook-commerce.php:2871
|
247 |
msgid "Create ad"
|
248 |
msgstr ""
|
249 |
|
250 |
+
#: facebook-commerce.php:2909
|
|
|
|
|
|
|
|
|
251 |
msgid "Sync products"
|
252 |
msgstr ""
|
253 |
|
254 |
+
#: facebook-commerce.php:3111
|
255 |
msgid "am"
|
256 |
msgstr ""
|
257 |
|
258 |
+
#: facebook-commerce.php:3116
|
259 |
msgid "pm"
|
260 |
msgstr ""
|
261 |
|
262 |
+
#: facebook-commerce.php:3236
|
263 |
msgid "The greeting hasn't been updated."
|
264 |
msgstr ""
|
265 |
|
266 |
+
#: facebook-commerce.php:3255
|
267 |
#. translators: Placeholder: %d - maximum number of allowed characters
|
268 |
msgid "The Messenger greeting must be %d characters or less."
|
269 |
msgstr ""
|
270 |
|
271 |
+
#: facebook-commerce.php:4008
|
272 |
msgid "Facebook for WooCommerce error:"
|
273 |
msgstr ""
|
274 |
|
275 |
+
#: facebook-commerce.php:4114
|
276 |
msgid "Get started with Messenger Customer Chat"
|
277 |
msgstr ""
|
278 |
|
279 |
+
#: facebook-commerce.php:4115
|
280 |
msgid "Get started with Instagram Shopping"
|
281 |
msgstr ""
|
282 |
|
283 |
+
#: facebook-commerce.php:4165
|
284 |
msgid ""
|
285 |
"You're using Remove HTTP which has incompatibilities with our extension. "
|
286 |
"Please disable it, or select the \"Ignore external links\" option on the "
|
291 |
msgid "Facebook"
|
292 |
msgstr ""
|
293 |
|
294 |
+
#: facebook-commerce.php:4174
|
295 |
msgid "Control how WooCommerce integrates with your Facebook store."
|
296 |
msgstr ""
|
297 |
|
298 |
+
#: facebook-commerce.php:4188
|
299 |
msgid "Grow your business on Facebook"
|
300 |
msgstr ""
|
301 |
|
302 |
+
#: facebook-commerce.php:4191
|
303 |
msgid "Use this WooCommerce and Facebook integration to:"
|
304 |
msgstr ""
|
305 |
|
306 |
+
#: facebook-commerce.php:4195
|
307 |
msgid "Easily install a tracking pixel"
|
308 |
msgstr ""
|
309 |
|
310 |
+
#: facebook-commerce.php:4196
|
311 |
msgid "Upload your products and create a shop"
|
312 |
msgstr ""
|
313 |
|
314 |
+
#: facebook-commerce.php:4197
|
315 |
msgid "Create dynamic ads with your products and pixel"
|
316 |
msgstr ""
|
317 |
|
318 |
+
#: facebook-commerce.php:4205
|
319 |
msgid "Get Started"
|
320 |
msgstr ""
|
321 |
|
322 |
+
#: facebook-commerce.php:4372
|
323 |
#. translators: Placeholders %1$s - original error message from Facebook API
|
324 |
msgid "There was an issue connecting to the Facebook API: %s"
|
325 |
msgstr ""
|
326 |
|
327 |
+
#: includes/AJAX.php:78
|
328 |
msgid "Hide Product"
|
329 |
msgstr ""
|
330 |
|
331 |
+
#: includes/AJAX.php:82
|
332 |
msgid "Do Not Hide Product"
|
333 |
msgstr ""
|
334 |
|
335 |
+
#: includes/AJAX.php:88
|
336 |
msgid ""
|
337 |
"This product will no longer be updated in your Facebook catalog. Would you "
|
338 |
"like to hide this product from your Facebook shop?"
|
339 |
msgstr ""
|
340 |
|
341 |
+
#: includes/AJAX.php:127 includes/AJAX.php:222
|
342 |
msgid "Go to Settings"
|
343 |
msgstr ""
|
344 |
|
345 |
+
#: includes/AJAX.php:132 includes/AJAX.php:227 includes/AJAX.php:298
|
346 |
msgid "Cancel"
|
347 |
msgstr ""
|
348 |
|
349 |
+
#: includes/AJAX.php:140
|
350 |
#. translators: Placeholder %s - <br/> tag
|
351 |
msgid ""
|
352 |
"This product belongs to a category or tag that is excluded from the "
|
355 |
"or click Cancel and update the product's category / tag assignments."
|
356 |
msgstr ""
|
357 |
|
358 |
+
#: includes/AJAX.php:181
|
359 |
msgid "Hide Products"
|
360 |
msgstr ""
|
361 |
|
362 |
+
#: includes/AJAX.php:185
|
363 |
msgid "Do Not Hide Products"
|
364 |
msgstr ""
|
365 |
|
366 |
+
#: includes/AJAX.php:191
|
367 |
msgid ""
|
368 |
"The selected products will no longer be updated in your Facebook catalog. "
|
369 |
"Would you like to hide these products from your Facebook shop?"
|
370 |
msgstr ""
|
371 |
|
372 |
+
#: includes/AJAX.php:233
|
373 |
msgid ""
|
374 |
"One or more of the selected products belongs to a category or tag that is "
|
375 |
"excluded from the Facebook catalog sync. To sync these products to "
|
377 |
"settings."
|
378 |
msgstr ""
|
379 |
|
380 |
+
#: includes/AJAX.php:286
|
381 |
msgid "Exclude Products"
|
382 |
msgstr ""
|
383 |
|
384 |
+
#: includes/AJAX.php:292
|
385 |
msgid "Exclude Products and Hide in Facebook"
|
386 |
msgstr ""
|
387 |
|
388 |
+
#: includes/AJAX.php:306
|
389 |
#. translators: Placeholder %s - <br/> tags
|
390 |
msgid ""
|
391 |
"The categories and/or tags that you have selected to exclude from sync "
|
394 |
"category / tag exclusion settings, click Cancel."
|
395 |
msgstr ""
|
396 |
|
397 |
+
#: includes/Admin.php:121
|
398 |
#. translators: Placeholders %1$s - opening <strong> html tag, %2$s closing
|
399 |
#. </strong> html tag, {count} number of remaining items
|
400 |
msgid "%1$sProgress:%2$s {count} item remaining."
|
402 |
msgstr[0] ""
|
403 |
msgstr[1] ""
|
404 |
|
405 |
+
#: includes/Admin.php:129
|
406 |
#. translators: Placeholders %s - html code for a spinner icon
|
407 |
msgid "Your products will now be resynced to Facebook, this may take some time."
|
408 |
msgstr ""
|
409 |
|
410 |
+
#: includes/Admin.php:130
|
411 |
msgid "Launch Test?"
|
412 |
msgstr ""
|
413 |
|
414 |
+
#: includes/Admin.php:131
|
415 |
msgid ""
|
416 |
"Facebook for WooCommerce automatically syncs your products on "
|
417 |
"create/update. Are you sure you want to force product resync?\n"
|
421 |
"did not sync."
|
422 |
msgstr ""
|
423 |
|
424 |
+
#: includes/Admin.php:132
|
425 |
msgid "Syncing... Keep this browser open until sync is complete. %s"
|
426 |
msgstr ""
|
427 |
|
428 |
+
#: includes/Admin.php:136
|
429 |
#. translators: Placeholders %1$s - opening <strong> html tag, %2$s closing
|
430 |
#. </strong> html tag
|
431 |
msgid "%1$sStatus:%2$s Test Pass."
|
432 |
msgstr ""
|
433 |
|
434 |
+
#: includes/Admin.php:138
|
435 |
#. translators: Placeholders %1$s - opening <strong> html tag, %2$s closing
|
436 |
#. </strong> html tag
|
437 |
msgid "%1$sStatus:%2$s Integration test in progress..."
|
438 |
msgstr ""
|
439 |
|
440 |
+
#: includes/Admin.php:140
|
441 |
#. translators: Placeholders %1$s - opening <strong> html tag, %2$s closing
|
442 |
#. </strong> html tag
|
443 |
msgid "%1$sStatus:%2$s Test Fail."
|
444 |
msgstr ""
|
445 |
|
446 |
+
#: includes/Admin.php:141
|
447 |
msgid "There was an error trying to sync the products to Facebook."
|
448 |
msgstr ""
|
449 |
|
450 |
+
#: includes/Admin.php:142
|
451 |
msgid ""
|
452 |
"Something went wrong while uploading the product information, please try "
|
453 |
"again."
|
454 |
msgstr ""
|
455 |
|
456 |
+
#: includes/Admin.php:162
|
457 |
msgid "FB Sync Enabled"
|
458 |
msgstr ""
|
459 |
|
460 |
+
#: includes/Admin.php:186
|
|
|
|
|
|
|
|
|
461 |
msgid "Enabled"
|
462 |
msgstr ""
|
463 |
|
464 |
+
#: includes/Admin.php:188
|
465 |
msgid "Disabled"
|
466 |
msgstr ""
|
467 |
|
468 |
+
#: includes/Admin.php:206
|
469 |
#. translators: Points to a product that was never synced with Facebook
|
470 |
msgid "Never synced with Facebook."
|
471 |
msgstr ""
|
472 |
|
473 |
+
#: includes/Admin.php:218
|
474 |
#. translators: Action to hide a product (currently synced with Facebook) from
|
475 |
#. the Facebook catalog
|
476 |
msgid "Hide from Facebook catalog. Currently synced with Facebook."
|
477 |
msgstr ""
|
478 |
|
479 |
+
#: includes/Admin.php:220
|
480 |
#. translators: Action to publish a product (currently synced with Facebook) in
|
481 |
#. the Facebook catalog
|
482 |
msgid "Publish in Facebook catalog. Currently synced with Facebook."
|
483 |
msgstr ""
|
484 |
|
485 |
+
#: includes/Admin.php:223
|
486 |
#. translators: Action to hide a product (currently not synced with Facebook)
|
487 |
#. from the Facebook catalog
|
488 |
msgid "Hide from Facebook catalog. Not synced with Facebook."
|
489 |
msgstr ""
|
490 |
|
491 |
+
#: includes/Admin.php:225
|
492 |
#. translators: Action to publish a product (currently not synced with
|
493 |
#. Facebook) in the Facebook catalog
|
494 |
msgid "Publish in Facebook catalog. Not synced with Facebook."
|
495 |
msgstr ""
|
496 |
|
497 |
+
#: includes/Admin.php:236
|
498 |
msgid "Show"
|
499 |
msgstr ""
|
500 |
|
501 |
+
#: includes/Admin.php:244
|
502 |
msgid "Hide"
|
503 |
msgstr ""
|
504 |
|
505 |
+
#: includes/Admin.php:272
|
506 |
msgid "Filter by Facebook sync setting"
|
507 |
msgstr ""
|
508 |
|
509 |
+
#: includes/Admin.php:273
|
510 |
msgid "Facebook sync enabled"
|
511 |
msgstr ""
|
512 |
|
513 |
+
#: includes/Admin.php:274
|
514 |
msgid "Facebook sync disabled"
|
515 |
msgstr ""
|
516 |
|
517 |
+
#: includes/Admin.php:458 includes/Admin.php:692 includes/Admin.php:784
|
518 |
msgid "Include in Facebook sync"
|
519 |
msgstr ""
|
520 |
|
521 |
+
#: includes/Admin.php:459
|
522 |
msgid "Exclude from Facebook sync"
|
523 |
msgstr ""
|
524 |
|
525 |
+
#: includes/Admin.php:546
|
526 |
#. translators: Placeholders: %1$s - Facebook for Woocommerce, %2$s - opening
|
527 |
#. HTML <a> link tag, %3$s - closing HTML </a> link tag
|
528 |
msgid ""
|
531 |
"checkout URLs on Facebook%3$s."
|
532 |
msgstr ""
|
533 |
|
534 |
+
#: includes/Admin.php:579
|
535 |
+
#. translators: Placeholders: %1$s - opening HTML <strong> tag, %2$s - closing
|
536 |
+
#. HTML </strong> tag, %3$s - opening HTML <a> tag, %4$s - closing HTML </a>
|
537 |
+
#. tag
|
538 |
+
msgid ""
|
539 |
+
"%1$sHeads up!%2$s Product sync is temporarily changed as we migrate to a "
|
540 |
+
"more secure experience. An automated sync from Facebook will run every hour "
|
541 |
+
"to update the catalog with any changes you've made. %3$sLearn more%4$s"
|
542 |
+
msgstr ""
|
543 |
+
|
544 |
+
#: includes/Admin.php:586
|
545 |
+
msgid "Don't show this notice again"
|
546 |
+
msgstr ""
|
547 |
+
|
548 |
+
#: includes/Admin.php:632
|
549 |
+
#. translators: Placeholders: %1$s - opening HTML <strong> tag, %2$s - closing
|
550 |
+
#. HTML </strong> tag, %3$s - opening HTML <a> tag, %4$s - closing HTML </a>
|
551 |
+
#. tag
|
552 |
+
msgid ""
|
553 |
+
"%1$sHeads up!%2$s Catalog visibility settings have been temporarily removed "
|
554 |
+
"as we migrate to a more secure experience. To remove products from your "
|
555 |
+
"Facebook catalog, please disable syncing to Facebook for the product. "
|
556 |
+
"%3$sLearn more%4$s"
|
557 |
+
msgstr ""
|
558 |
+
|
559 |
+
#: includes/Admin.php:698 includes/Admin.php:793
|
560 |
msgid "Facebook Description"
|
561 |
msgstr ""
|
562 |
|
563 |
+
#: includes/Admin.php:700 includes/Admin.php:795
|
564 |
msgid ""
|
565 |
"Custom (plain-text only) description for product on Facebook. If blank, "
|
566 |
"product description will be used. If product description is blank, "
|
567 |
"shortname will be used."
|
568 |
msgstr ""
|
569 |
|
570 |
+
#: includes/Admin.php:709 includes/Admin.php:806
|
571 |
msgid "Facebook Product Image"
|
572 |
msgstr ""
|
573 |
|
574 |
+
#: includes/Admin.php:711 includes/Admin.php:808
|
575 |
msgid ""
|
576 |
"Choose the product image that should be synced to the Facebook catalog for "
|
577 |
"this product. If using a custom image, please enter an absolute URL (e.g. "
|
578 |
"https://domain.com/image.jpg)."
|
579 |
msgstr ""
|
580 |
|
581 |
+
#: includes/Admin.php:713
|
582 |
msgid "Use WooCommerce image"
|
583 |
msgstr ""
|
584 |
|
585 |
+
#: includes/Admin.php:714 includes/Admin.php:812
|
586 |
msgid "Use custom image"
|
587 |
msgstr ""
|
588 |
|
589 |
+
#: includes/Admin.php:723 includes/Admin.php:822
|
590 |
msgid "Custom Image URL"
|
591 |
msgstr ""
|
592 |
|
593 |
+
#: includes/Admin.php:732 includes/Admin.php:833
|
594 |
#. translators: Placeholders %1$s - WC currency symbol
|
595 |
msgid "Facebook Price (%1$s)"
|
596 |
msgstr ""
|
597 |
|
598 |
+
#: includes/Admin.php:736 includes/Admin.php:837
|
599 |
msgid ""
|
600 |
"Custom price for product on Facebook. Please enter in monetary decimal (.) "
|
601 |
"format without thousand separators and currency symbols. If blank, product "
|
602 |
"price will be used."
|
603 |
msgstr ""
|
604 |
|
605 |
+
#: includes/Admin.php:810
|
606 |
msgid "Use variation image"
|
607 |
msgstr ""
|
608 |
|
609 |
+
#: includes/Admin.php:811
|
610 |
msgid "Use parent image"
|
611 |
msgstr ""
|
612 |
|
613 |
+
#: includes/Admin.php:942
|
614 |
msgid "Close modal panel"
|
615 |
msgstr ""
|
616 |
|
630 |
msgid "Dismiss"
|
631 |
msgstr ""
|
632 |
|
633 |
+
#: includes/fbproductfeed.php:432
|
634 |
+
msgid "Could not create product catalog feed directory"
|
635 |
+
msgstr ""
|
636 |
+
|
637 |
+
#: includes/fbproductfeed.php:498
|
638 |
+
msgid "Could not open the product catalog feed file for writing"
|
639 |
+
msgstr ""
|
640 |
+
|
641 |
#: includes/fbwpml.php:105
|
642 |
msgid "Facebook Visibility"
|
643 |
msgstr ""
|
675 |
msgid "https://www.facebook.com/"
|
676 |
msgstr ""
|
677 |
|
678 |
+
#: facebook-commerce-messenger-chat.php:258 facebook-commerce.php:2507
|
679 |
msgctxt "language"
|
680 |
msgid "English (United States)"
|
681 |
msgstr ""
|
includes/AJAX.php
CHANGED
@@ -51,15 +51,17 @@ class AJAX {
|
|
51 |
check_ajax_referer( 'set-product-sync-prompt', 'security' );
|
52 |
|
53 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
54 |
-
$product_id
|
55 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
56 |
-
$sync_enabled
|
57 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
58 |
-
$
|
|
|
|
|
59 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
60 |
-
$product_tags
|
61 |
|
62 |
-
if ( $product_id > 0 && in_array( $sync_enabled, [ 'enabled', 'disabled' ], true ) ) {
|
63 |
|
64 |
$product = wc_get_product( $product_id );
|
65 |
|
@@ -87,7 +89,7 @@ class AJAX {
|
|
87 |
'buttons' => $buttons,
|
88 |
] );
|
89 |
|
90 |
-
} elseif ( 'enabled' === $sync_enabled ) {
|
91 |
|
92 |
$has_excluded_terms = false;
|
93 |
|
@@ -282,10 +284,13 @@ class AJAX {
|
|
282 |
id="facebook-for-woocommerce-confirm-settings-change"
|
283 |
class="button button-large button-primary facebook-for-woocommerce-confirm-settings-change"
|
284 |
><?php esc_html_e( 'Exclude Products', 'facebook-for-woocommerce' ); ?></button>
|
|
|
|
|
285 |
<button
|
286 |
id="facebook-for-woocommerce-confirm-settings-change-hide-products"
|
287 |
class="button button-large button-primary facebook-for-woocommerce-confirm-settings-change hide-products"
|
288 |
-
><?php esc_html_e( 'Exclude Products and Hide in Facebook', 'facebook-for-woocommerce' ); ?></button>
|
|
|
289 |
<button
|
290 |
id="facebook-for-woocommerce-cancel-settings-change"
|
291 |
class="button button-large button-primary"
|
51 |
check_ajax_referer( 'set-product-sync-prompt', 'security' );
|
52 |
|
53 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
54 |
+
$product_id = isset( $_POST['product'] ) ? (int) $_POST['product'] : 0;
|
55 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
56 |
+
$sync_enabled = isset( $_POST['sync_enabled'] ) ? (string) $_POST['sync_enabled'] : '';
|
57 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
58 |
+
$var_sync_enabled = isset( $_POST['var_sync_enabled'] ) ? (string) $_POST['var_sync_enabled'] : '';
|
59 |
+
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
60 |
+
$product_cats = isset( $_POST['categories'] ) ? (array) $_POST['categories'] : [];
|
61 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
62 |
+
$product_tags = isset( $_POST['tags'] ) ? (array) $_POST['tags'] : [];
|
63 |
|
64 |
+
if ( $product_id > 0 && in_array( $var_sync_enabled, [ 'enabled', 'disabled' ], true ) && in_array( $sync_enabled, [ 'enabled', 'disabled' ], true ) ) {
|
65 |
|
66 |
$product = wc_get_product( $product_id );
|
67 |
|
89 |
'buttons' => $buttons,
|
90 |
] );
|
91 |
|
92 |
+
} elseif ( ( 'enabled' === $sync_enabled && ! $product->is_type( 'variable' ) ) || ( 'enabled' === $var_sync_enabled && $product->is_type( 'variable' ) ) ) {
|
93 |
|
94 |
$has_excluded_terms = false;
|
95 |
|
284 |
id="facebook-for-woocommerce-confirm-settings-change"
|
285 |
class="button button-large button-primary facebook-for-woocommerce-confirm-settings-change"
|
286 |
><?php esc_html_e( 'Exclude Products', 'facebook-for-woocommerce' ); ?></button>
|
287 |
+
|
288 |
+
<!-- TODO: restore for FBE 2.0
|
289 |
<button
|
290 |
id="facebook-for-woocommerce-confirm-settings-change-hide-products"
|
291 |
class="button button-large button-primary facebook-for-woocommerce-confirm-settings-change hide-products"
|
292 |
+
><?php esc_html_e( 'Exclude Products and Hide in Facebook', 'facebook-for-woocommerce' ); ?></button> -->
|
293 |
+
|
294 |
<button
|
295 |
id="facebook-for-woocommerce-cancel-settings-change"
|
296 |
class="button button-large button-primary"
|
includes/Admin.php
CHANGED
@@ -10,6 +10,8 @@
|
|
10 |
|
11 |
namespace SkyVerge\WooCommerce\Facebook;
|
12 |
|
|
|
|
|
13 |
defined( 'ABSPATH' ) or exit;
|
14 |
|
15 |
/**
|
@@ -33,7 +35,7 @@ class Admin {
|
|
33 |
$integration = facebook_for_woocommerce()->get_integration();
|
34 |
|
35 |
// only alter the admin UI if the plugin is connected to Facebook and ready to sync products
|
36 |
-
if ( ! $integration->
|
37 |
return;
|
38 |
}
|
39 |
|
@@ -45,6 +47,13 @@ class Admin {
|
|
45 |
// add admin notification in case of site URL change
|
46 |
add_action( 'admin_notices', [ $this, 'validate_cart_url' ] );
|
47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
// add columns for displaying Facebook sync enabled/disabled and catalog visibility status
|
49 |
add_filter( 'manage_product_posts_columns', [ $this, 'add_product_list_table_columns' ] );
|
50 |
add_action( 'manage_product_posts_custom_column', [ $this, 'add_product_list_table_columns_content' ] );
|
@@ -151,7 +160,7 @@ class Admin {
|
|
151 |
public function add_product_list_table_columns( $columns ) {
|
152 |
|
153 |
$columns['facebook_sync_enabled'] = __( 'FB Sync Enabled', 'facebook-for-woocommerce' );
|
154 |
-
$columns['facebook_catalog_visibility'] = __( 'FB Catalog Visibility', 'facebook-for-woocommerce' );
|
155 |
|
156 |
return $columns;
|
157 |
}
|
@@ -296,13 +305,38 @@ class Admin {
|
|
296 |
|
297 |
$query_vars = $this->add_query_vars_to_find_products_with_sync_enabled( $query_vars );
|
298 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
299 |
} else {
|
300 |
|
301 |
$integration = facebook_for_woocommerce()->get_integration();
|
302 |
$excluded_categories_ids = $integration ? $integration->get_excluded_product_category_ids() : [];
|
303 |
-
$
|
304 |
|
305 |
-
if ( $excluded_categories_ids || $
|
306 |
|
307 |
// find the IDs of products that have sync enabled
|
308 |
$products_query_vars = [
|
@@ -523,6 +557,91 @@ class Admin {
|
|
523 |
}
|
524 |
|
525 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
526 |
/**
|
527 |
* Adds a new tab to the Product edit page.
|
528 |
*
|
@@ -665,7 +784,7 @@ class Admin {
|
|
665 |
'label' => __( 'Include in Facebook sync', 'facebook-for-woocommerce' ),
|
666 |
'value' => wc_bool_to_string( 'no' !== $sync_enabled ),
|
667 |
'class' => 'checkbox js-variable-fb-sync-toggle',
|
668 |
-
'wrapper_class' => 'fb-sync-enabled-field'
|
669 |
] );
|
670 |
|
671 |
woocommerce_wp_textarea_input( [
|
@@ -703,7 +822,7 @@ class Admin {
|
|
703 |
'label' => __( 'Custom Image URL', 'facebook-for-woocommerce' ),
|
704 |
'value' => $image_url,
|
705 |
'class' => sprintf( 'enable-if-sync-enabled product-image-source-field show-if-product-image-source-%s', Products::PRODUCT_IMAGE_SOURCE_CUSTOM ),
|
706 |
-
'wrapper_class' => 'form-row form-row-full'
|
707 |
] );
|
708 |
|
709 |
woocommerce_wp_text_input( [
|
10 |
|
11 |
namespace SkyVerge\WooCommerce\Facebook;
|
12 |
|
13 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4\SV_WC_Helper;
|
14 |
+
|
15 |
defined( 'ABSPATH' ) or exit;
|
16 |
|
17 |
/**
|
35 |
$integration = facebook_for_woocommerce()->get_integration();
|
36 |
|
37 |
// only alter the admin UI if the plugin is connected to Facebook and ready to sync products
|
38 |
+
if ( ! $integration->get_product_catalog_id() ) {
|
39 |
return;
|
40 |
}
|
41 |
|
47 |
// add admin notification in case of site URL change
|
48 |
add_action( 'admin_notices', [ $this, 'validate_cart_url' ] );
|
49 |
|
50 |
+
// add admin notice to inform that product sync has changed
|
51 |
+
add_action( 'admin_notices', [ $this, 'add_product_sync_delay_notice' ] );
|
52 |
+
// add admin notice to inform that the catalog visibility setting was removed
|
53 |
+
add_action( 'admin_notices', [ $this, 'add_catalog_visibility_settings_removed_notice' ] );
|
54 |
+
// handle dismissal of special notices
|
55 |
+
add_action( 'wc_' . facebook_for_woocommerce()->get_id(). '_dismiss_notice', [ $this, 'handle_dismiss_notice' ], 10, 2 );
|
56 |
+
|
57 |
// add columns for displaying Facebook sync enabled/disabled and catalog visibility status
|
58 |
add_filter( 'manage_product_posts_columns', [ $this, 'add_product_list_table_columns' ] );
|
59 |
add_action( 'manage_product_posts_custom_column', [ $this, 'add_product_list_table_columns_content' ] );
|
160 |
public function add_product_list_table_columns( $columns ) {
|
161 |
|
162 |
$columns['facebook_sync_enabled'] = __( 'FB Sync Enabled', 'facebook-for-woocommerce' );
|
163 |
+
// $columns['facebook_catalog_visibility'] = __( 'FB Catalog Visibility', 'facebook-for-woocommerce' );
|
164 |
|
165 |
return $columns;
|
166 |
}
|
305 |
|
306 |
$query_vars = $this->add_query_vars_to_find_products_with_sync_enabled( $query_vars );
|
307 |
|
308 |
+
// since we record enabled status on child variations, we may need to query variable products found for their children to exclude them from query results
|
309 |
+
$exclude_products = [];
|
310 |
+
$found_ids = get_posts( array_merge( $query_vars, [ 'fields' => 'ids' ] ) );
|
311 |
+
$found_products = empty( $found_ids ) ? [] : wc_get_products( [
|
312 |
+
'limit' => -1,
|
313 |
+
'type' => 'variable',
|
314 |
+
'include' => $found_ids,
|
315 |
+
] );
|
316 |
+
|
317 |
+
/** @var \WC_Product[] $found_products */
|
318 |
+
foreach ( $found_products as $product ) {
|
319 |
+
|
320 |
+
if ( ! Products::is_sync_enabled_for_product( $product ) ) {
|
321 |
+
$exclude_products[] = $product->get_id();
|
322 |
+
}
|
323 |
+
}
|
324 |
+
|
325 |
+
if ( ! empty( $exclude_products ) ) {
|
326 |
+
if ( ! empty( $query_vars['post__not_in'] ) ) {
|
327 |
+
$query_vars['post__not_in'] = array_merge( $query_vars['post__not_in'], $exclude_products );
|
328 |
+
} else {
|
329 |
+
$query_vars['post__not_in'] = $exclude_products;
|
330 |
+
}
|
331 |
+
}
|
332 |
+
|
333 |
} else {
|
334 |
|
335 |
$integration = facebook_for_woocommerce()->get_integration();
|
336 |
$excluded_categories_ids = $integration ? $integration->get_excluded_product_category_ids() : [];
|
337 |
+
$excluded_tags_ids = $integration ? $integration->get_excluded_product_tag_ids() : [];
|
338 |
|
339 |
+
if ( $excluded_categories_ids || $excluded_tags_ids ) {
|
340 |
|
341 |
// find the IDs of products that have sync enabled
|
342 |
$products_query_vars = [
|
557 |
}
|
558 |
|
559 |
|
560 |
+
/**
|
561 |
+
* Prints a notice on products page to inform users about changes in product sync.
|
562 |
+
*
|
563 |
+
* @internal
|
564 |
+
*
|
565 |
+
* @since 1.11.0
|
566 |
+
*/
|
567 |
+
public function add_product_sync_delay_notice() {
|
568 |
+
global $current_screen;
|
569 |
+
|
570 |
+
$transient_name = 'wc_' . facebook_for_woocommerce()->get_id() . '_show_product_sync_delay_notice_' . get_current_user_id();
|
571 |
+
|
572 |
+
if ( isset( $current_screen->id ) && in_array( $current_screen->id, [ 'edit-product', 'product' ], true ) && get_transient( $transient_name ) ) {
|
573 |
+
|
574 |
+
if ( isset( $_GET['message'] ) || isset( $_GET['trashed'] ) || isset( $_GET['deleted'] ) ) {
|
575 |
+
|
576 |
+
facebook_for_woocommerce()->get_admin_notice_handler()->add_admin_notice(
|
577 |
+
sprintf(
|
578 |
+
/* translators: Placeholders: %1$s - opening HTML <strong> tag, %2$s - closing HTML </strong> tag, %3$s - opening HTML <a> tag, %4$s - closing HTML </a> tag */
|
579 |
+
esc_html__( '%1$sHeads up!%2$s Product sync is temporarily changed as we migrate to a more secure experience. An automated sync from Facebook will run every hour to update the catalog with any changes you\'ve made. %3$sLearn more%4$s', 'facebook-for-woocommerce' ),
|
580 |
+
'<strong>',
|
581 |
+
'</strong>',
|
582 |
+
'<a href="https://docs.woocommerce.com/document/facebook-for-woocommerce/#faq-security" target="_blank">',
|
583 |
+
'</a>'
|
584 |
+
)
|
585 |
+
. '</p><p>' // close notice paragraph and open a new one for the button
|
586 |
+
. '<button class="button notice-dismiss-permanently" type="button">' . esc_html__( "Don't show this notice again", 'facebook-for-woocommerce' ) . '</button>',
|
587 |
+
'wc-' . facebook_for_woocommerce()->get_id_dasherized() . '-product-sync-delay',
|
588 |
+
[ 'notice_class' => 'notice-info' ]
|
589 |
+
);
|
590 |
+
}
|
591 |
+
|
592 |
+
delete_transient( $transient_name );
|
593 |
+
}
|
594 |
+
}
|
595 |
+
|
596 |
+
|
597 |
+
/**
|
598 |
+
* Handles dismissed notices.
|
599 |
+
*
|
600 |
+
* @internal
|
601 |
+
*
|
602 |
+
* @since 1.11.0
|
603 |
+
*
|
604 |
+
* @param string $message_id the dismissed notice ID
|
605 |
+
* @param int $user_id the ID of the user the noticed was dismissed for
|
606 |
+
*/
|
607 |
+
public function handle_dismiss_notice( $message_id, $user_id = null ) {
|
608 |
+
|
609 |
+
// undismiss product sync delay notice unless 'permanently' is included in the request
|
610 |
+
if ( ! SV_WC_Helper::get_requested_value( 'permanently' ) && 'wc-' . facebook_for_woocommerce()->get_id_dasherized() . '-product-sync-delay' === $message_id ) {
|
611 |
+
|
612 |
+
facebook_for_woocommerce()->get_admin_notice_handler()->undismiss_notice( $message_id, $user_id );
|
613 |
+
}
|
614 |
+
}
|
615 |
+
|
616 |
+
|
617 |
+
/**
|
618 |
+
* Prints a notice on products page to inform users that catalog visibility settings were removed.
|
619 |
+
*
|
620 |
+
* @internal
|
621 |
+
*
|
622 |
+
* @since 1.11.0
|
623 |
+
*/
|
624 |
+
public function add_catalog_visibility_settings_removed_notice() {
|
625 |
+
global $current_screen;
|
626 |
+
|
627 |
+
if ( isset( $current_screen->id ) && in_array( $current_screen->id, [ 'edit-product', 'product' ], true ) ) {
|
628 |
+
|
629 |
+
facebook_for_woocommerce()->get_admin_notice_handler()->add_admin_notice(
|
630 |
+
sprintf(
|
631 |
+
/* translators: Placeholders: %1$s - opening HTML <strong> tag, %2$s - closing HTML </strong> tag, %3$s - opening HTML <a> tag, %4$s - closing HTML </a> tag */
|
632 |
+
esc_html__( '%1$sHeads up!%2$s Catalog visibility settings have been temporarily removed as we migrate to a more secure experience. To remove products from your Facebook catalog, please disable syncing to Facebook for the product. %3$sLearn more%4$s', 'facebook-for-woocommerce' ),
|
633 |
+
'<strong>',
|
634 |
+
'</strong>',
|
635 |
+
'<a href="https://docs.woocommerce.com/document/facebook-for-woocommerce/#section-10" target="_blank">', // TODO: add link to FAQ entry {WV 2020-03-30}
|
636 |
+
'</a>'
|
637 |
+
),
|
638 |
+
'wc-' . facebook_for_woocommerce()->get_id_dasherized() . '-catalog-visibility-settings-removed',
|
639 |
+
[ 'notice_class' => 'notice-info' ]
|
640 |
+
);
|
641 |
+
}
|
642 |
+
}
|
643 |
+
|
644 |
+
|
645 |
/**
|
646 |
* Adds a new tab to the Product edit page.
|
647 |
*
|
784 |
'label' => __( 'Include in Facebook sync', 'facebook-for-woocommerce' ),
|
785 |
'value' => wc_bool_to_string( 'no' !== $sync_enabled ),
|
786 |
'class' => 'checkbox js-variable-fb-sync-toggle',
|
787 |
+
'wrapper_class' => 'fb-sync-enabled-field',
|
788 |
] );
|
789 |
|
790 |
woocommerce_wp_textarea_input( [
|
822 |
'label' => __( 'Custom Image URL', 'facebook-for-woocommerce' ),
|
823 |
'value' => $image_url,
|
824 |
'class' => sprintf( 'enable-if-sync-enabled product-image-source-field show-if-product-image-source-%s', Products::PRODUCT_IMAGE_SOURCE_CUSTOM ),
|
825 |
+
'wrapper_class' => 'form-row form-row-full',
|
826 |
] );
|
827 |
|
828 |
woocommerce_wp_text_input( [
|
includes/Lifecycle.php
CHANGED
@@ -38,6 +38,7 @@ class Lifecycle extends Framework\Plugin\Lifecycle {
|
|
38 |
$this->upgrade_versions = [
|
39 |
'1.10.0',
|
40 |
'1.10.1',
|
|
|
41 |
];
|
42 |
}
|
43 |
|
@@ -200,4 +201,20 @@ class Lifecycle extends Framework\Plugin\Lifecycle {
|
|
200 |
}
|
201 |
|
202 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
203 |
}
|
38 |
$this->upgrade_versions = [
|
39 |
'1.10.0',
|
40 |
'1.10.1',
|
41 |
+
'1.11.0',
|
42 |
];
|
43 |
}
|
44 |
|
201 |
}
|
202 |
|
203 |
|
204 |
+
/**
|
205 |
+
* Upgrades to version 1.11.0.
|
206 |
+
*
|
207 |
+
* @since 1.11.0
|
208 |
+
*/
|
209 |
+
protected function upgrade_to_1_11_0() {
|
210 |
+
|
211 |
+
$settings = get_option( 'woocommerce_' . \WC_Facebookcommerce::INTEGRATION_ID . '_settings', [] );
|
212 |
+
|
213 |
+
// moves the upload ID to a standalone option
|
214 |
+
if ( ! empty( $settings['fb_upload_id'] ) ) {
|
215 |
+
$this->get_plugin()->get_integration()->update_upload_id( $settings['fb_upload_id'] );
|
216 |
+
}
|
217 |
+
}
|
218 |
+
|
219 |
+
|
220 |
}
|
includes/Products/Feed.php
ADDED
@@ -0,0 +1,251 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\Products;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* The main product feed handler.
|
19 |
+
*
|
20 |
+
* This will eventually replace \WC_Facebook_Product_Feed as we refactor and move its functionality here.
|
21 |
+
*
|
22 |
+
* @since 1.11.0
|
23 |
+
*/
|
24 |
+
class Feed {
|
25 |
+
|
26 |
+
|
27 |
+
/** @var string the action callback for generating a feed */
|
28 |
+
const GENERATE_FEED_ACTION = 'wc_facebook_regenerate_feed';
|
29 |
+
|
30 |
+
/** @var string the action slug for getting the product feed */
|
31 |
+
const REQUEST_FEED_ACTION = 'wc_facebook_get_feed_data';
|
32 |
+
|
33 |
+
/** @var string the WordPress option name where the secret included in the feed URL is stored */
|
34 |
+
const OPTION_FEED_URL_SECRET = 'wc_facebook_feed_url_secret';
|
35 |
+
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Feed constructor.
|
39 |
+
*
|
40 |
+
* @since 1.11.0
|
41 |
+
*/
|
42 |
+
public function __construct() {
|
43 |
+
|
44 |
+
// add the necessary action and filter hooks
|
45 |
+
$this->add_hooks();
|
46 |
+
}
|
47 |
+
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Adds the necessary action and filter hooks.
|
51 |
+
*
|
52 |
+
* @since 1.11.0
|
53 |
+
*/
|
54 |
+
private function add_hooks() {
|
55 |
+
|
56 |
+
// schedule the recurring feed generation
|
57 |
+
add_action( 'init', [ $this, 'schedule_feed_generation' ] );
|
58 |
+
|
59 |
+
// regenerate the product feed
|
60 |
+
add_action( self::GENERATE_FEED_ACTION, [ $this, 'regenerate_feed' ] );
|
61 |
+
|
62 |
+
// handle the feed data request
|
63 |
+
add_action( 'woocommerce_api_' . self::REQUEST_FEED_ACTION, [ $this, 'handle_feed_data_request' ] );
|
64 |
+
}
|
65 |
+
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Handles the feed data request.
|
69 |
+
*
|
70 |
+
* @internal
|
71 |
+
*
|
72 |
+
* @since 1.11.0
|
73 |
+
*/
|
74 |
+
public function handle_feed_data_request() {
|
75 |
+
|
76 |
+
\WC_Facebookcommerce_Utils::log( 'Facebook is requesting the product feed.' );
|
77 |
+
|
78 |
+
$feed_handler = new \WC_Facebook_Product_Feed();
|
79 |
+
$file_path = $feed_handler->get_file_path();
|
80 |
+
|
81 |
+
// regenerate if the file doesn't exist
|
82 |
+
if ( ! empty( $_GET['regenerate'] ) || ! file_exists( $file_path ) ) {
|
83 |
+
$feed_handler->generate_feed();
|
84 |
+
}
|
85 |
+
|
86 |
+
try {
|
87 |
+
|
88 |
+
// bail early if the feed secret is not included or is not valid
|
89 |
+
if ( Feed::get_feed_secret() !== Framework\SV_WC_Helper::get_requested_value( 'secret' ) ) {
|
90 |
+
throw new Framework\SV_WC_Plugin_Exception( 'Invalid feed secret provided.', 401 );
|
91 |
+
}
|
92 |
+
|
93 |
+
// bail early if the file can't be read
|
94 |
+
if ( ! is_readable( $file_path ) ) {
|
95 |
+
throw new Framework\SV_WC_Plugin_Exception( 'File is not readable.', 404 );
|
96 |
+
}
|
97 |
+
|
98 |
+
// set the download headers
|
99 |
+
header( 'Content-Type: text/csv; charset=utf-8' );
|
100 |
+
header( 'Content-Description: File Transfer' );
|
101 |
+
header( 'Content-Disposition: attachment; filename="' . basename( $file_path ) . '"' );
|
102 |
+
header( 'Expires: 0' );
|
103 |
+
header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
|
104 |
+
header( 'Pragma: public' );
|
105 |
+
header( 'Content-Length:'. filesize( $file_path ) );
|
106 |
+
|
107 |
+
$file = @fopen( $file_path, 'rb' );
|
108 |
+
|
109 |
+
if ( ! $file ) {
|
110 |
+
throw new Framework\SV_WC_Plugin_Exception( 'Could not open feed file.', 500 );
|
111 |
+
}
|
112 |
+
|
113 |
+
// fpassthru might be disabled in some hosts (like Flywheel)
|
114 |
+
if ( $this->is_fpassthru_disabled() || ! @fpassthru( $file ) ) {
|
115 |
+
|
116 |
+
\WC_Facebookcommerce_Utils::log( 'fpassthru is disabled: getting file contents' );
|
117 |
+
|
118 |
+
$contents = @stream_get_contents( $file );
|
119 |
+
|
120 |
+
if ( ! $contents ) {
|
121 |
+
throw new Framework\SV_WC_Plugin_Exception( 'Could not get feed file contents.', 500 );
|
122 |
+
}
|
123 |
+
|
124 |
+
echo $contents;
|
125 |
+
}
|
126 |
+
|
127 |
+
} catch ( \Exception $exception ) {
|
128 |
+
|
129 |
+
\WC_Facebookcommerce_Utils::log( 'Could not serve product feed. ' . $exception->getMessage() . ' (' . $exception->getCode() . ')' );
|
130 |
+
|
131 |
+
status_header( $exception->getCode() );
|
132 |
+
}
|
133 |
+
|
134 |
+
exit;
|
135 |
+
}
|
136 |
+
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Regenerates the product feed.
|
140 |
+
*
|
141 |
+
* @internal
|
142 |
+
*
|
143 |
+
* @since 1.11.0
|
144 |
+
*/
|
145 |
+
public function regenerate_feed() {
|
146 |
+
|
147 |
+
$feed_handler = new \WC_Facebook_Product_Feed();
|
148 |
+
|
149 |
+
$feed_handler->generate_feed();
|
150 |
+
}
|
151 |
+
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Schedules the recurring feed generation.
|
155 |
+
*
|
156 |
+
* @internal
|
157 |
+
*
|
158 |
+
* @since 1.11.0
|
159 |
+
*/
|
160 |
+
public function schedule_feed_generation() {
|
161 |
+
|
162 |
+
$integration = facebook_for_woocommerce()->get_integration();
|
163 |
+
|
164 |
+
// only schedule if configured
|
165 |
+
if ( ! $integration || ! $integration->is_configured() || ! $integration->is_product_sync_enabled() ) {
|
166 |
+
as_unschedule_all_actions( self::GENERATE_FEED_ACTION );
|
167 |
+
return;
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Filters the frequency with which the product feed data is generated.
|
172 |
+
*
|
173 |
+
* @since 1.11.0
|
174 |
+
*
|
175 |
+
* @param int $interval the frequency with which the product feed data is generated, in seconds. Defaults to every 15 minutes.
|
176 |
+
*/
|
177 |
+
$interval = apply_filters( 'wc_facebook_feed_generation_interval', MINUTE_IN_SECONDS * 15 );
|
178 |
+
|
179 |
+
if ( ! as_next_scheduled_action( self::GENERATE_FEED_ACTION ) ) {
|
180 |
+
as_schedule_recurring_action( time(), max( 2, $interval ), self::GENERATE_FEED_ACTION, [], facebook_for_woocommerce()->get_id_dasherized() );
|
181 |
+
}
|
182 |
+
}
|
183 |
+
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Checks whether fpassthru has been disabled in PHP.
|
187 |
+
*
|
188 |
+
* Helper method, do not open to public.
|
189 |
+
*
|
190 |
+
* @since 1.11.0
|
191 |
+
*
|
192 |
+
* @return bool
|
193 |
+
*/
|
194 |
+
private function is_fpassthru_disabled() {
|
195 |
+
|
196 |
+
$disabled = false;
|
197 |
+
|
198 |
+
if ( function_exists( 'ini_get' ) ) {
|
199 |
+
|
200 |
+
$disabled_functions = @ini_get( 'disable_functions' );
|
201 |
+
|
202 |
+
$disabled = is_string( $disabled_functions ) && in_array( 'fpassthru', explode( ',', $disabled_functions ), false );
|
203 |
+
}
|
204 |
+
|
205 |
+
return $disabled;
|
206 |
+
}
|
207 |
+
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Gets the URL for retrieving the product feed data.
|
211 |
+
*
|
212 |
+
* @since 1.11.0
|
213 |
+
*
|
214 |
+
* @return string
|
215 |
+
*/
|
216 |
+
public static function get_feed_data_url() {
|
217 |
+
|
218 |
+
$query_args = [
|
219 |
+
'wc-api' => self::REQUEST_FEED_ACTION,
|
220 |
+
'secret' => self::get_feed_secret(),
|
221 |
+
];
|
222 |
+
|
223 |
+
return add_query_arg( $query_args, home_url( '/' ) );
|
224 |
+
}
|
225 |
+
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Gets the secret value that should be included in the Feed URL.
|
229 |
+
*
|
230 |
+
* Generates a new secret and stores it in the database if no value is set.
|
231 |
+
*
|
232 |
+
* @since 1.11.0
|
233 |
+
*
|
234 |
+
* @return string
|
235 |
+
*/
|
236 |
+
public static function get_feed_secret() {
|
237 |
+
|
238 |
+
$secret = get_option( self::OPTION_FEED_URL_SECRET, '' );
|
239 |
+
|
240 |
+
if ( ! $secret ) {
|
241 |
+
|
242 |
+
$secret = wp_hash( 'products-feed-' . time() );
|
243 |
+
|
244 |
+
update_option( self::OPTION_FEED_URL_SECRET, $secret );
|
245 |
+
}
|
246 |
+
|
247 |
+
return $secret;
|
248 |
+
}
|
249 |
+
|
250 |
+
|
251 |
+
}
|
includes/fbproduct.php
CHANGED
@@ -611,50 +611,54 @@ if ( ! class_exists( 'WC_Facebook_Product' ) ) :
|
|
611 |
|
612 |
|
613 |
/**
|
614 |
-
*
|
615 |
-
|
|
|
|
|
|
|
616 |
public function prepare_variants_for_item( &$product_data ) {
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
|
|
|
|
621 |
}
|
622 |
|
623 |
-
$attributes = $
|
|
|
624 |
if ( ! $attributes ) {
|
625 |
-
return;
|
626 |
}
|
627 |
|
628 |
$variant_names = array_keys( $attributes );
|
629 |
-
$
|
630 |
|
631 |
// Loop through variants (size, color, etc) if they exist
|
632 |
// For each product field type, pull the single variant
|
633 |
-
foreach ( $variant_names as $
|
|
|
634 |
// Retrieve label name for attribute
|
635 |
-
$label = wc_attribute_label( $
|
636 |
|
637 |
// Clean up variant name (e.g. pa_color should be color)
|
638 |
// Replace "custom_data:foo" with just "foo" so we can use the key
|
639 |
// Product item API expects "custom_data" instead of "custom_data:foo"
|
640 |
-
$new_name = str_replace(
|
641 |
-
'custom_data:',
|
642 |
-
'',
|
643 |
-
WC_Facebookcommerce_Utils::sanitize_variant_name( $orig_name )
|
644 |
-
);
|
645 |
|
646 |
// Sometimes WC returns an array, sometimes it's an assoc array, depending
|
647 |
// on what type of taxonomy it's using. array_values will guarantee we
|
648 |
// only get a flat array of values.
|
649 |
-
$options = $this->get_variant_option_name(
|
650 |
-
|
651 |
-
$attributes[ $orig_name ]
|
652 |
-
);
|
653 |
-
if ( isset( $options ) ) {
|
654 |
if ( is_array( $options ) ) {
|
|
|
655 |
$option_values = array_values( $options );
|
|
|
656 |
} else {
|
657 |
-
|
|
|
|
|
658 |
// If this attribute has value 'any', options will be empty strings
|
659 |
// Redirect to product page to select variants.
|
660 |
// Reset checkout url since checkout_url (build from query data will
|
@@ -664,148 +668,160 @@ if ( ! class_exists( 'WC_Facebook_Product' ) ) :
|
|
664 |
$product_data['checkout_url'] = $product_data['url'];
|
665 |
}
|
666 |
}
|
667 |
-
|
|
|
|
|
668 |
// If we can't validate the gender, this will be null.
|
669 |
-
$product_data[ $new_name ] =
|
670 |
-
WC_Facebookcommerce_Utils::validateGender( $option_values[0] );
|
671 |
}
|
672 |
|
673 |
switch ( $new_name ) {
|
674 |
-
|
675 |
-
case WC_Facebookcommerce_Utils::
|
676 |
-
case WC_Facebookcommerce_Utils::
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
$product_data[ $new_name ] = $option_values[0];
|
686 |
-
|
687 |
-
|
|
|
|
|
|
|
688 |
// If we can't validate the GENDER field, we'll fall through to the
|
689 |
// default case and set the gender into custom data.
|
690 |
if ( $product_data[ $new_name ] ) {
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
)
|
698 |
-
);
|
699 |
-
break;
|
700 |
}
|
701 |
|
|
|
|
|
702 |
default:
|
|
|
703 |
// This is for any custom_data.
|
704 |
if ( ! isset( $product_data['custom_data'] ) ) {
|
705 |
-
$product_data['custom_data'] =
|
706 |
}
|
707 |
-
|
708 |
-
|
709 |
-
|
|
|
710 |
}
|
|
|
711 |
} else {
|
712 |
-
|
713 |
-
|
714 |
-
);
|
715 |
continue;
|
716 |
}
|
717 |
}
|
718 |
-
|
|
|
719 |
}
|
720 |
|
|
|
721 |
/**
|
722 |
-
*
|
723 |
-
|
|
|
|
|
|
|
724 |
public function prepare_variants_for_group( $feed_data = false ) {
|
725 |
-
if ( ! WC_Facebookcommerce_Utils::is_variable_type(
|
726 |
-
$this->get_type()
|
727 |
-
) ) {
|
728 |
-
WC_Facebookcommerce_Utils::fblog(
|
729 |
-
'prepare_variants_for_group called on non-variable product'
|
730 |
-
);
|
731 |
-
return;
|
732 |
-
}
|
733 |
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
}
|
738 |
-
$final_variants = array();
|
739 |
|
740 |
-
|
741 |
-
foreach ( $attrs as $name ) {
|
742 |
-
$label = wc_attribute_label( $name, $this );
|
743 |
|
744 |
-
if (
|
745 |
-
|
746 |
-
} else {
|
747 |
-
// variation_attributes keys are labels for custom attrs for some reason
|
748 |
-
$key = $label;
|
749 |
}
|
750 |
|
751 |
-
|
752 |
-
WC_Facebookcommerce_Utils::fblog(
|
753 |
-
"Critical error: can't get attribute name or label!"
|
754 |
-
);
|
755 |
-
return;
|
756 |
-
}
|
757 |
|
758 |
-
if (
|
759 |
-
|
760 |
-
$option_values = $variation_attributes[ $key ];
|
761 |
-
} else {
|
762 |
-
WC_Facebookcommerce_Utils::log(
|
763 |
-
$this->get_id() . ': No options for ' . $name
|
764 |
-
);
|
765 |
-
continue; // Skip variations without valid attribute options
|
766 |
}
|
767 |
|
768 |
-
|
769 |
-
// If it's being used, show it as the first option on Facebook.
|
770 |
-
$first_option = $this->get_variation_default_attribute( $key );
|
771 |
-
if ( $first_option ) {
|
772 |
-
$idx = array_search( $first_option, $option_values );
|
773 |
-
unset( $option_values[ $idx ] );
|
774 |
-
array_unshift( $option_values, $first_option );
|
775 |
-
}
|
776 |
|
777 |
-
|
778 |
-
function_exists( 'taxonomy_is_product_attribute' ) &&
|
779 |
-
taxonomy_is_product_attribute( $name )
|
780 |
-
) {
|
781 |
-
$option_values = $this->get_grouped_product_option_names(
|
782 |
-
$key,
|
783 |
-
$option_values
|
784 |
-
);
|
785 |
-
}
|
786 |
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
|
|
|
|
791 |
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
799 |
'product_field' => $name,
|
800 |
'label' => $label,
|
801 |
'options' => $option_values,
|
802 |
-
|
803 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
804 |
}
|
805 |
|
806 |
return $final_variants;
|
807 |
-
|
808 |
}
|
|
|
|
|
809 |
}
|
810 |
|
811 |
endif;
|
611 |
|
612 |
|
613 |
/**
|
614 |
+
* Normalizes variant data for Facebook.
|
615 |
+
*
|
616 |
+
* @param array $product_data variation product data
|
617 |
+
* @return array
|
618 |
+
*/
|
619 |
public function prepare_variants_for_item( &$product_data ) {
|
620 |
+
|
621 |
+
/** @var \WC_Product_Variation $product */
|
622 |
+
$product = $this;
|
623 |
+
|
624 |
+
if ( ! $product->is_type( 'variation' ) ) {
|
625 |
+
return [];
|
626 |
}
|
627 |
|
628 |
+
$attributes = $product->get_variation_attributes();
|
629 |
+
|
630 |
if ( ! $attributes ) {
|
631 |
+
return [];
|
632 |
}
|
633 |
|
634 |
$variant_names = array_keys( $attributes );
|
635 |
+
$variant_data = [];
|
636 |
|
637 |
// Loop through variants (size, color, etc) if they exist
|
638 |
// For each product field type, pull the single variant
|
639 |
+
foreach ( $variant_names as $original_variant_name ) {
|
640 |
+
|
641 |
// Retrieve label name for attribute
|
642 |
+
$label = wc_attribute_label( $original_variant_name, $product );
|
643 |
|
644 |
// Clean up variant name (e.g. pa_color should be color)
|
645 |
// Replace "custom_data:foo" with just "foo" so we can use the key
|
646 |
// Product item API expects "custom_data" instead of "custom_data:foo"
|
647 |
+
$new_name = str_replace( 'custom_data:', '', \WC_Facebookcommerce_Utils::sanitize_variant_name( $original_variant_name ) );
|
|
|
|
|
|
|
|
|
648 |
|
649 |
// Sometimes WC returns an array, sometimes it's an assoc array, depending
|
650 |
// on what type of taxonomy it's using. array_values will guarantee we
|
651 |
// only get a flat array of values.
|
652 |
+
if ( $options = $this->get_variant_option_name( $label, $attributes[ $original_variant_name ] ) ) {
|
653 |
+
|
|
|
|
|
|
|
654 |
if ( is_array( $options ) ) {
|
655 |
+
|
656 |
$option_values = array_values( $options );
|
657 |
+
|
658 |
} else {
|
659 |
+
|
660 |
+
$option_values = [ $options ];
|
661 |
+
|
662 |
// If this attribute has value 'any', options will be empty strings
|
663 |
// Redirect to product page to select variants.
|
664 |
// Reset checkout url since checkout_url (build from query data will
|
668 |
$product_data['checkout_url'] = $product_data['url'];
|
669 |
}
|
670 |
}
|
671 |
+
|
672 |
+
if ( \WC_Facebookcommerce_Utils::FB_VARIANT_GENDER === $new_name ) {
|
673 |
+
|
674 |
// If we can't validate the gender, this will be null.
|
675 |
+
$product_data[ $new_name ] = \WC_Facebookcommerce_Utils::validateGender( $option_values[0] );
|
|
|
676 |
}
|
677 |
|
678 |
switch ( $new_name ) {
|
679 |
+
|
680 |
+
case \WC_Facebookcommerce_Utils::FB_VARIANT_SIZE:
|
681 |
+
case \WC_Facebookcommerce_Utils::FB_VARIANT_COLOR:
|
682 |
+
case \WC_Facebookcommerce_Utils::FB_VARIANT_PATTERN:
|
683 |
+
|
684 |
+
$variant_data[] = [
|
685 |
+
'product_field' => $new_name,
|
686 |
+
'label' => $label,
|
687 |
+
'options' => $option_values,
|
688 |
+
];
|
689 |
+
|
690 |
$product_data[ $new_name ] = $option_values[0];
|
691 |
+
|
692 |
+
break;
|
693 |
+
|
694 |
+
case \WC_Facebookcommerce_Utils::FB_VARIANT_GENDER:
|
695 |
+
|
696 |
// If we can't validate the GENDER field, we'll fall through to the
|
697 |
// default case and set the gender into custom data.
|
698 |
if ( $product_data[ $new_name ] ) {
|
699 |
+
|
700 |
+
$variant_data[] = [
|
701 |
+
'product_field' => $new_name,
|
702 |
+
'label' => $label,
|
703 |
+
'options' => $option_values,
|
704 |
+
];
|
|
|
|
|
|
|
705 |
}
|
706 |
|
707 |
+
break;
|
708 |
+
|
709 |
default:
|
710 |
+
|
711 |
// This is for any custom_data.
|
712 |
if ( ! isset( $product_data['custom_data'] ) ) {
|
713 |
+
$product_data['custom_data'] = [];
|
714 |
}
|
715 |
+
|
716 |
+
$product_data['custom_data'][ $new_name ] = urldecode( $option_values[0] );
|
717 |
+
|
718 |
+
break;
|
719 |
}
|
720 |
+
|
721 |
} else {
|
722 |
+
|
723 |
+
\WC_Facebookcommerce_Utils::log( $product->get_id() . ': No options for ' . $original_variant_name );
|
|
|
724 |
continue;
|
725 |
}
|
726 |
}
|
727 |
+
|
728 |
+
return $variant_data;
|
729 |
}
|
730 |
|
731 |
+
|
732 |
/**
|
733 |
+
* Normalizes variable product variations data for Facebook.
|
734 |
+
*
|
735 |
+
* @param bool $feed_data whether this is used for feed data
|
736 |
+
* @return array
|
737 |
+
*/
|
738 |
public function prepare_variants_for_group( $feed_data = false ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
739 |
|
740 |
+
/** @var \WC_Product_Variable $product */
|
741 |
+
$product = $this;
|
742 |
+
$final_variants = [];
|
|
|
|
|
743 |
|
744 |
+
try {
|
|
|
|
|
745 |
|
746 |
+
if ( ! $product->is_type( 'variable' ) ) {
|
747 |
+
throw new \Exception( 'prepare_variants_for_group called on non-variable product' );
|
|
|
|
|
|
|
748 |
}
|
749 |
|
750 |
+
$variation_attributes = $product->get_variation_attributes();
|
|
|
|
|
|
|
|
|
|
|
751 |
|
752 |
+
if ( ! $variation_attributes ) {
|
753 |
+
return [];
|
|
|
|
|
|
|
|
|
|
|
|
|
754 |
}
|
755 |
|
756 |
+
foreach ( array_keys( $product->get_attributes() ) as $name ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
757 |
|
758 |
+
$label = wc_attribute_label( $name, $product );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
759 |
|
760 |
+
if ( taxonomy_is_product_attribute( $name ) ) {
|
761 |
+
$key = $name;
|
762 |
+
} else {
|
763 |
+
// variation_attributes keys are labels for custom attrs for some reason
|
764 |
+
$key = $label;
|
765 |
+
}
|
766 |
|
767 |
+
if ( ! $key ) {
|
768 |
+
throw new \Exception( "Critical error: can't get attribute name or label!" );
|
769 |
+
}
|
770 |
+
|
771 |
+
if ( isset( $variation_attributes[ $key ] ) ) {
|
772 |
+
// array of the options (e.g. small, medium, large)
|
773 |
+
$option_values = $variation_attributes[ $key ];
|
774 |
+
} else {
|
775 |
+
// skip variations without valid attribute options
|
776 |
+
\WC_Facebookcommerce_Utils::log( $product->get_id() . ': No options for ' . $name );
|
777 |
+
continue;
|
778 |
+
}
|
779 |
+
|
780 |
+
// If this is a variable product, check default attribute.
|
781 |
+
// If it's being used, show it as the first option on Facebook.
|
782 |
+
if ( $first_option = $product->get_variation_default_attribute( $key ) ) {
|
783 |
+
|
784 |
+
$index = array_search( $first_option, $option_values, false );
|
785 |
+
|
786 |
+
unset( $option_values[ $index ] );
|
787 |
+
|
788 |
+
array_unshift( $option_values, $first_option );
|
789 |
+
}
|
790 |
+
|
791 |
+
if ( function_exists( 'taxonomy_is_product_attribute' ) && taxonomy_is_product_attribute( $name ) ) {
|
792 |
+
$option_values = $this->get_grouped_product_option_names( $key, $option_values );
|
793 |
+
}
|
794 |
+
|
795 |
+
/**
|
796 |
+
* For API approach, product_field need to start with 'custom_data:'
|
797 |
+
* @link https://developers.facebook.com/docs/marketing-api/reference/product-variant/
|
798 |
+
* Clean up variant name (e.g. pa_color should be color):
|
799 |
+
*/
|
800 |
+
$name = \WC_Facebookcommerce_Utils::sanitize_variant_name( $name );
|
801 |
+
|
802 |
+
// for feed uploading, product field should remove prefix 'custom_data:'
|
803 |
+
if ( $feed_data ) {
|
804 |
+
$name = str_replace( 'custom_data:', '', $name );
|
805 |
+
}
|
806 |
+
|
807 |
+
$final_variants[] = [
|
808 |
'product_field' => $name,
|
809 |
'label' => $label,
|
810 |
'options' => $option_values,
|
811 |
+
];
|
812 |
+
}
|
813 |
+
|
814 |
+
} catch ( \Exception $e ) {
|
815 |
+
|
816 |
+
\WC_Facebookcommerce_Utils::fblog( $e->getMessage() );
|
817 |
+
|
818 |
+
return [];
|
819 |
}
|
820 |
|
821 |
return $final_variants;
|
|
|
822 |
}
|
823 |
+
|
824 |
+
|
825 |
}
|
826 |
|
827 |
endif;
|
includes/fbproductfeed.php
CHANGED
@@ -12,6 +12,9 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
12 |
exit;
|
13 |
}
|
14 |
|
|
|
|
|
|
|
15 |
if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
16 |
|
17 |
/**
|
@@ -19,6 +22,17 @@ if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
|
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.';
|
@@ -28,32 +42,307 @@ if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
|
28 |
private $has_default_product_count = 0;
|
29 |
private $no_default_product_count = 0;
|
30 |
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
|
|
|
|
|
|
|
|
|
|
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 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
|
|
50 |
|
51 |
-
if ( ! $this->generate_productfeed_file() ) {
|
52 |
$this->log_feed_progress(
|
53 |
-
'Failure - Sync all products using feed
|
54 |
);
|
55 |
return false;
|
56 |
}
|
|
|
57 |
$this->log_feed_progress( 'Sync all products using feed, feed file generated' );
|
58 |
|
59 |
if ( ! $this->feed_id ) {
|
@@ -84,11 +373,6 @@ if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
|
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 =
|
@@ -110,34 +394,112 @@ if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
|
110 |
return true;
|
111 |
}
|
112 |
|
113 |
-
|
114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
$post_ids = $this->get_product_wpid();
|
116 |
$all_parent_product = array_map(
|
117 |
function( $post_id ) {
|
118 |
-
if ( get_post_type( $post_id )
|
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 |
-
|
126 |
-
return
|
127 |
}
|
128 |
|
129 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
|
131 |
try {
|
132 |
|
133 |
-
$feed_file =
|
134 |
-
fopen(
|
135 |
-
dirname( __FILE__ ) . DIRECTORY_SEPARATOR .
|
136 |
-
( self::FACEBOOK_CATALOG_FEED_FILENAME ),
|
137 |
-
'w'
|
138 |
-
);
|
139 |
|
140 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
|
142 |
$product_group_attribute_variants = array();
|
143 |
|
@@ -154,7 +516,7 @@ if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
|
154 |
}
|
155 |
|
156 |
// skip if not enabled for sync
|
157 |
-
if ( $woo_product->woo_product instanceof \WC_Product && !
|
158 |
continue;
|
159 |
}
|
160 |
|
@@ -162,15 +524,28 @@ if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
|
162 |
$woo_product,
|
163 |
$product_group_attribute_variants
|
164 |
);
|
165 |
-
|
|
|
|
|
|
|
166 |
}
|
167 |
-
|
168 |
wp_reset_postdata();
|
169 |
-
|
|
|
|
|
170 |
} catch ( Exception $e ) {
|
|
|
171 |
WC_Facebookcommerce_Utils::log( json_encode( $e->getMessage() ) );
|
172 |
-
|
|
|
173 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
}
|
175 |
|
176 |
public function get_product_feed_header_row() {
|
@@ -180,44 +555,57 @@ if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
|
180 |
'visibility,default_product,variant' . PHP_EOL;
|
181 |
}
|
182 |
|
|
|
183 |
/**
|
184 |
-
*
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
|
|
|
|
|
|
189 |
$product_data = $woo_product->prepare_product( null, true );
|
190 |
$item_group_id = $product_data['retailer_id'];
|
|
|
191 |
// prepare variant column for variable products
|
192 |
$product_data['variant'] = '';
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
$parent_id = $woo_product->get_parent_id();
|
197 |
|
198 |
if ( ! isset( $attribute_variants[ $parent_id ] ) ) {
|
199 |
-
|
200 |
-
|
201 |
-
$gallery_urls
|
202 |
-
$variation_id
|
203 |
-
$variants_for_group
|
204 |
-
$parent_attribute_values
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
|
|
209 |
foreach ( $variants_for_group as $variant ) {
|
210 |
-
|
211 |
-
|
|
|
212 |
}
|
|
|
213 |
// cache product group variants
|
214 |
$attribute_variants[ $parent_id ] = $parent_attribute_values;
|
|
|
|
|
|
|
|
|
215 |
}
|
216 |
-
|
217 |
-
$variants_for_item
|
218 |
-
$
|
219 |
-
|
220 |
foreach ( $variants_for_item as $variant_array ) {
|
|
|
221 |
static::format_variant_for_feed(
|
222 |
$variant_array['product_field'],
|
223 |
$variant_array['options'][0],
|
@@ -225,8 +613,11 @@ if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
|
225 |
$variant_feed_column
|
226 |
);
|
227 |
}
|
228 |
-
|
|
|
|
|
229 |
foreach ( $product_data['custom_data'] as $product_field => $value ) {
|
|
|
230 |
static::format_variant_for_feed(
|
231 |
$product_field,
|
232 |
$value,
|
@@ -235,29 +626,23 @@ if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
|
235 |
);
|
236 |
}
|
237 |
}
|
|
|
238 |
if ( ! empty( $variant_feed_column ) ) {
|
239 |
-
$product_data['variant'] =
|
240 |
-
'"' . implode( ',', $variant_feed_column ) . '"';
|
241 |
}
|
|
|
242 |
if ( isset( $parent_attribute_values['gallery_urls'] ) ) {
|
243 |
-
$product_data['additional_image_urls'] =
|
244 |
-
array_merge(
|
245 |
-
$product_data['additional_image_urls'],
|
246 |
-
$parent_attribute_values['gallery_urls']
|
247 |
-
);
|
248 |
}
|
|
|
249 |
if ( isset( $parent_attribute_values['item_group_id'] ) ) {
|
250 |
$item_group_id = $parent_attribute_values['item_group_id'];
|
251 |
}
|
252 |
|
253 |
-
$product_data['default_product'] =
|
254 |
-
$parent_attribute_values['default_variant_id'] == $woo_product->id
|
255 |
-
? 'default'
|
256 |
-
: '';
|
257 |
|
258 |
// If this group has default variant value, log this product item
|
259 |
-
if ( isset( $parent_attribute_values['default_variant_id'] ) &&
|
260 |
-
! empty( $parent_attribute_values['default_variant_id'] ) ) {
|
261 |
$this->has_default_product_count++;
|
262 |
} else {
|
263 |
$this->no_default_product_count++;
|
@@ -266,7 +651,9 @@ if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
|
266 |
|
267 |
// log simple product
|
268 |
if ( ! isset( $product_data['default_product'] ) ) {
|
|
|
269 |
$this->no_default_product_count++;
|
|
|
270 |
$product_data['default_product'] = '';
|
271 |
}
|
272 |
|
@@ -299,6 +686,7 @@ if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
|
299 |
$product_data['variant'] . PHP_EOL;
|
300 |
}
|
301 |
|
|
|
302 |
private function create_feed() {
|
303 |
$result = $this->fbgraph->create_feed(
|
304 |
$this->facebook_catalog_id,
|
@@ -322,8 +710,7 @@ if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
|
322 |
private function create_upload( $facebook_feed_id ) {
|
323 |
$result = $this->fbgraph->create_upload(
|
324 |
$facebook_feed_id,
|
325 |
-
|
326 |
-
( self::FACEBOOK_CATALOG_FEED_FILENAME )
|
327 |
);
|
328 |
if ( is_null( $result ) || ! isset( $result['id'] ) || ! $result['id'] ) {
|
329 |
$this->log_feed_progress( json_encode( $result ) );
|
@@ -386,9 +773,14 @@ if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
|
386 |
* @return string
|
387 |
*/
|
388 |
public function is_upload_complete( &$settings ) {
|
389 |
-
|
|
|
|
|
|
|
390 |
if ( is_wp_error( $result ) || ! isset( $result['body'] ) ) {
|
|
|
391 |
$this->log_feed_progress( json_encode( $result ) );
|
|
|
392 |
return 'error';
|
393 |
}
|
394 |
|
12 |
exit;
|
13 |
}
|
14 |
|
15 |
+
use SkyVerge\WooCommerce\Facebook\Products\Feed;
|
16 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
17 |
+
|
18 |
if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
19 |
|
20 |
/**
|
22 |
*/
|
23 |
class WC_Facebook_Product_Feed {
|
24 |
|
25 |
+
|
26 |
+
/** @var string transient name for storing the average feed generation time */
|
27 |
+
const TRANSIENT_AVERAGE_FEED_GENERATION_TIME = 'wc_facebook_average_feed_generation_time';
|
28 |
+
|
29 |
+
/** @var string product catalog feed file directory inside the uploads folder */
|
30 |
+
const UPLOADS_DIRECTORY = 'facebook_for_woocommerce';
|
31 |
+
|
32 |
+
/** @var string product catalog feed file name - %s will be replaced with a hash */
|
33 |
+
const FILE_NAME = 'product_catalog_%s.csv';
|
34 |
+
|
35 |
+
|
36 |
const FACEBOOK_CATALOG_FEED_FILENAME = 'fae_product_catalog.csv';
|
37 |
const FB_ADDITIONAL_IMAGES_FOR_FEED = 5;
|
38 |
const FEED_NAME = 'Initial product sync from WooCommerce. DO NOT DELETE.';
|
42 |
private $has_default_product_count = 0;
|
43 |
private $no_default_product_count = 0;
|
44 |
|
45 |
+
/**
|
46 |
+
* WC_Facebook_Product_Feed constructor.
|
47 |
+
*
|
48 |
+
* @param string|null $facebook_catalog_id Facebook catalog ID, if any
|
49 |
+
* @param \WC_Facebookcommerce_Graph_API|null $fbgraph Facebook Graph API instance
|
50 |
+
* @param string|null $feed_id Facebook feed ID, if any
|
51 |
+
*/
|
52 |
+
public function __construct( $facebook_catalog_id = null, $fbgraph = null, $feed_id = null ) {
|
53 |
+
|
54 |
$this->facebook_catalog_id = $facebook_catalog_id;
|
55 |
$this->fbgraph = $fbgraph;
|
56 |
$this->feed_id = $feed_id;
|
57 |
}
|
58 |
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Schedules a new feed generation.
|
62 |
+
*
|
63 |
+
* @since 1.11.0
|
64 |
+
*/
|
65 |
+
public function schedule_feed_generation() {
|
66 |
+
|
67 |
+
// don't schedule another if one's already scheduled or in progress
|
68 |
+
if ( false !== as_next_scheduled_action( 'wc_facebook_generate_product_catalog_feed', [], 'facebook-for-woocommerce' ) ) {
|
69 |
+
return;
|
70 |
+
}
|
71 |
+
|
72 |
+
\WC_Facebookcommerce_Utils::log( 'Scheduling product catalog feed file generation' );
|
73 |
+
|
74 |
+
// if async priority actions are supported (AS 3.0+)
|
75 |
+
if ( function_exists( 'as_enqueue_async_action' ) ) {
|
76 |
+
as_enqueue_async_action( 'wc_facebook_generate_product_catalog_feed', [], 'facebook-for-woocommerce' );
|
77 |
+
} else {
|
78 |
+
as_schedule_single_action( time(), 'wc_facebook_generate_product_catalog_feed', [], 'facebook-for-woocommerce' );
|
79 |
+
}
|
80 |
+
}
|
81 |
+
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Generates the product catalog feed.
|
85 |
+
*
|
86 |
+
* This replaces any previously generated feed file.
|
87 |
+
*
|
88 |
+
* @since 1.11.0
|
89 |
+
*/
|
90 |
+
public function generate_feed() {
|
91 |
+
|
92 |
+
\WC_Facebookcommerce_Utils::log( 'Generating a fresh product feed file' );
|
93 |
+
|
94 |
+
try {
|
95 |
+
|
96 |
+
$start_time = microtime( true );
|
97 |
+
|
98 |
+
$this->generate_productfeed_file();
|
99 |
+
|
100 |
+
$generation_time = microtime( true ) - $start_time;
|
101 |
+
|
102 |
+
$this->set_feed_generation_time_with_decay( $generation_time );
|
103 |
+
|
104 |
+
\WC_Facebookcommerce_Utils::log( 'Product feed file generated' );
|
105 |
+
|
106 |
+
} catch ( \Exception $exception ) {
|
107 |
+
|
108 |
+
\WC_Facebookcommerce_Utils::log( $exception->getMessage() );
|
109 |
+
}
|
110 |
+
}
|
111 |
+
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Sets the average feed generation time with a 25% decay.
|
115 |
+
*
|
116 |
+
* @since 1.11.0
|
117 |
+
*
|
118 |
+
* @param float $generation_time last generation time
|
119 |
+
*/
|
120 |
+
private function set_feed_generation_time_with_decay( $generation_time ) {
|
121 |
+
|
122 |
+
// update feed generation time estimate w/ 25% decay.
|
123 |
+
$existing_generation_time = $this->get_average_feed_generation_time();
|
124 |
+
|
125 |
+
if ( $generation_time < $existing_generation_time ) {
|
126 |
+
$generation_time = $generation_time * 0.25 + $existing_generation_time * 0.75;
|
127 |
+
}
|
128 |
+
|
129 |
+
$this->set_average_feed_generation_time( $generation_time );
|
130 |
+
}
|
131 |
+
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Sets the average feed generation time.
|
135 |
+
*
|
136 |
+
* @since 1.11.0
|
137 |
+
*
|
138 |
+
* @param float $time generation time
|
139 |
+
*/
|
140 |
+
private function set_average_feed_generation_time( $time ) {
|
141 |
+
|
142 |
+
set_transient( self::TRANSIENT_AVERAGE_FEED_GENERATION_TIME, $time );
|
143 |
+
}
|
144 |
+
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Gets the estimated feed generation time.
|
148 |
+
*
|
149 |
+
* Performs a dry run and returns either the dry run time or last average estimated time, whichever is higher.
|
150 |
+
*
|
151 |
+
* @since 1.11.0
|
152 |
+
*
|
153 |
+
* @return int
|
154 |
+
*/
|
155 |
+
public function get_estimated_feed_generation_time() {
|
156 |
+
|
157 |
+
$estimate = $this->estimate_generation_time();
|
158 |
+
$average = $this->get_average_feed_generation_time();
|
159 |
+
|
160 |
+
return (int) max( $estimate, $average );
|
161 |
+
}
|
162 |
+
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Estimates the feed generation time.
|
166 |
+
*
|
167 |
+
* Runs a dry-run generation of a subset of products, then extrapolates that out to the full catalog size. Also
|
168 |
+
* adds a bit of buffer time.
|
169 |
+
*
|
170 |
+
* @since 1.11.0
|
171 |
+
*
|
172 |
+
* @return float
|
173 |
+
*/
|
174 |
+
private function estimate_generation_time() {
|
175 |
+
|
176 |
+
$product_ids = $this->get_product_ids();
|
177 |
+
$total_products = count( $product_ids );
|
178 |
+
$sample_size = $this->get_feed_generation_estimate_sample_size();
|
179 |
+
$buffer_time = $this->get_feed_generation_buffer_time();
|
180 |
+
|
181 |
+
if ( $total_products > 0 ) {
|
182 |
+
|
183 |
+
if ( $total_products < $sample_size ) {
|
184 |
+
|
185 |
+
$sample_size = $total_products;
|
186 |
+
|
187 |
+
} else {
|
188 |
+
|
189 |
+
$product_ids = array_slice( $product_ids, 0, $sample_size );
|
190 |
+
}
|
191 |
+
|
192 |
+
$start_time = microtime( true );
|
193 |
+
|
194 |
+
$this->write_product_feed_file( $product_ids, true );
|
195 |
+
|
196 |
+
$end_time = microtime( true );
|
197 |
+
|
198 |
+
$time_spent = $end_time - $start_time;
|
199 |
+
|
200 |
+
// estimated Time = 150% of Linear extrapolation of the time to generate n products + buffer time.
|
201 |
+
$time_estimate = $time_spent * $total_products / $sample_size * 1.5 + $buffer_time;
|
202 |
+
|
203 |
+
} else {
|
204 |
+
|
205 |
+
$time_estimate = $buffer_time;
|
206 |
+
}
|
207 |
+
|
208 |
+
WC_Facebookcommerce_Utils::log( 'Feed Generation Time Estimate: '. $time_estimate );
|
209 |
+
|
210 |
+
return $time_estimate;
|
211 |
+
}
|
212 |
+
|
213 |
+
|
214 |
+
/**
|
215 |
+
* Gets the average feed generation time.
|
216 |
+
*
|
217 |
+
* @since 1.11.0
|
218 |
+
*
|
219 |
+
* @return float
|
220 |
+
*/
|
221 |
+
private function get_average_feed_generation_time() {
|
222 |
+
|
223 |
+
return get_transient( self::TRANSIENT_AVERAGE_FEED_GENERATION_TIME );
|
224 |
+
}
|
225 |
+
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Gets the number of products to use when estimating the feed file generation time.
|
229 |
+
*
|
230 |
+
* @since 1.11.0
|
231 |
+
*
|
232 |
+
* @return int
|
233 |
+
*/
|
234 |
+
private function get_feed_generation_estimate_sample_size() {
|
235 |
+
|
236 |
+
/**
|
237 |
+
* Filters the number of products to use when estimating the feed file generation time.
|
238 |
+
*
|
239 |
+
* @since 1.11.0
|
240 |
+
*
|
241 |
+
* @param int $sample_size number of products to use when estimating the feed file generation time
|
242 |
+
*/
|
243 |
+
$sample_size = (int) apply_filters( 'wc_facebook_product_catalog_feed_generation_estimate_sample_size', 200 );
|
244 |
+
|
245 |
+
return max( $sample_size, 100 );
|
246 |
+
}
|
247 |
+
|
248 |
+
|
249 |
+
/**
|
250 |
+
* Gets the number of seconds to add as a buffer when estimating the feed file generation time.
|
251 |
+
*
|
252 |
+
* @since 1.11.0
|
253 |
+
*
|
254 |
+
* @return int
|
255 |
+
*/
|
256 |
+
private function get_feed_generation_buffer_time() {
|
257 |
+
|
258 |
+
/**
|
259 |
+
* Filters the number of seconds to add as a buffer when estimating the feed file generation time.
|
260 |
+
*
|
261 |
+
* @since 1.11.0
|
262 |
+
*
|
263 |
+
* @param int $time number of seconds to add as a buffer when estimating the feed file generation time
|
264 |
+
*/
|
265 |
+
$buffer_time = (int) apply_filters( 'wc_facebook_product_catalog_feed_generation_buffer_time', 30 );
|
266 |
+
|
267 |
+
return max( $buffer_time, 5 );
|
268 |
+
}
|
269 |
+
|
270 |
+
|
271 |
+
/**
|
272 |
+
* Gets the product catalog feed file path.
|
273 |
+
*
|
274 |
+
* @since 1.11.0
|
275 |
+
*
|
276 |
+
* @return string
|
277 |
+
*/
|
278 |
+
public function get_file_path() {
|
279 |
+
|
280 |
+
/**
|
281 |
+
* Filters the product catalog feed file path.
|
282 |
+
*
|
283 |
+
* @since 1.11.0
|
284 |
+
*
|
285 |
+
* @param string $file_path the file path
|
286 |
+
*/
|
287 |
+
return apply_filters( 'wc_facebook_product_catalog_feed_file_path', "{$this->get_file_directory()}/{$this->get_file_name()}" );
|
288 |
+
}
|
289 |
+
|
290 |
+
|
291 |
+
/**
|
292 |
+
* Gets the product catalog feed file directory.
|
293 |
+
*
|
294 |
+
* @since 1.11.0
|
295 |
+
*
|
296 |
+
* @return string
|
297 |
+
*/
|
298 |
+
public function get_file_directory() {
|
299 |
+
|
300 |
+
$uploads_directory = wp_upload_dir( null, false );
|
301 |
+
|
302 |
+
return trailingslashit( $uploads_directory['basedir'] ) . self::UPLOADS_DIRECTORY;
|
303 |
+
}
|
304 |
+
|
305 |
+
|
306 |
+
/**
|
307 |
+
* Gets the product catalog feed file name.
|
308 |
+
*
|
309 |
+
* @since 1.11.0
|
310 |
+
*
|
311 |
+
* @return string
|
312 |
+
*/
|
313 |
+
public function get_file_name() {
|
314 |
+
|
315 |
+
$file_name = sprintf( self::FILE_NAME, wp_hash( Feed::get_feed_secret() ) );
|
316 |
+
|
317 |
+
/**
|
318 |
+
* Filters the product catalog feed file name.
|
319 |
+
*
|
320 |
+
* @since 1.11.0
|
321 |
+
*
|
322 |
+
* @param string $file_name the file name
|
323 |
+
*/
|
324 |
+
return apply_filters( 'wc_facebook_product_catalog_feed_file_name', $file_name );
|
325 |
+
}
|
326 |
+
|
327 |
+
|
328 |
public function sync_all_products_using_feed() {
|
329 |
$start_time = microtime( true );
|
330 |
$this->log_feed_progress( 'Sync all products using feed' );
|
331 |
|
332 |
+
try {
|
333 |
+
|
334 |
+
if ( ! $this->generate_productfeed_file() ) {
|
335 |
+
throw new Framework\SV_WC_Plugin_Exception( 'Feed file not generated' );
|
336 |
+
}
|
337 |
+
|
338 |
+
} catch ( Framework\SV_WC_Plugin_Exception $exception ) {
|
339 |
|
|
|
340 |
$this->log_feed_progress(
|
341 |
+
'Failure - Sync all products using feed. ' . $exception->getMessage()
|
342 |
);
|
343 |
return false;
|
344 |
}
|
345 |
+
|
346 |
$this->log_feed_progress( 'Sync all products using feed, feed file generated' );
|
347 |
|
348 |
if ( ! $this->feed_id ) {
|
373 |
'Sync all products using feed, facebook upload created'
|
374 |
);
|
375 |
|
|
|
|
|
|
|
|
|
|
|
376 |
$total_product_count =
|
377 |
$this->has_default_product_count + $this->no_default_product_count;
|
378 |
$default_product_percentage =
|
394 |
return true;
|
395 |
}
|
396 |
|
397 |
+
|
398 |
+
/**
|
399 |
+
* Gets the product IDs that will be included in the feed file.
|
400 |
+
*
|
401 |
+
* @since 1.11.0
|
402 |
+
*
|
403 |
+
* @return int[]
|
404 |
+
*/
|
405 |
+
private function get_product_ids() {
|
406 |
+
|
407 |
$post_ids = $this->get_product_wpid();
|
408 |
$all_parent_product = array_map(
|
409 |
function( $post_id ) {
|
410 |
+
if ( 'product_variation' === get_post_type( $post_id ) ) {
|
411 |
return wp_get_post_parent_id( $post_id );
|
412 |
}
|
413 |
},
|
414 |
$post_ids
|
415 |
);
|
416 |
+
|
417 |
$all_parent_product = array_filter( array_unique( $all_parent_product ) );
|
418 |
+
|
419 |
+
return array_diff( $post_ids, $all_parent_product );
|
420 |
}
|
421 |
|
422 |
+
|
423 |
+
/**
|
424 |
+
* Generates the product catalog feed file.
|
425 |
+
*
|
426 |
+
* @return bool
|
427 |
+
* @throws Framework\SV_WC_Plugin_Exception
|
428 |
+
*/
|
429 |
+
public function generate_productfeed_file() {
|
430 |
+
|
431 |
+
if ( ! wp_mkdir_p( $this->get_file_directory() ) ) {
|
432 |
+
throw new Framework\SV_WC_Plugin_Exception( __( 'Could not create product catalog feed directory', 'facebook-for-woocommerce' ), 500 );
|
433 |
+
}
|
434 |
+
|
435 |
+
$this->create_files_to_protect_product_feed_directory();
|
436 |
+
|
437 |
+
return $this->write_product_feed_file( $this->get_product_ids() );
|
438 |
+
}
|
439 |
+
|
440 |
+
|
441 |
+
/**
|
442 |
+
* Creates files in the catalog feed directory to prevent directory listing and hotlinking.
|
443 |
+
*
|
444 |
+
* @since 1.11.0
|
445 |
+
*/
|
446 |
+
private function create_files_to_protect_product_feed_directory() {
|
447 |
+
|
448 |
+
$catalog_feed_directory = trailingslashit( $this->get_file_directory() );
|
449 |
+
|
450 |
+
$files = [
|
451 |
+
[
|
452 |
+
'base' => $catalog_feed_directory,
|
453 |
+
'file' => 'index.html',
|
454 |
+
'content' => '',
|
455 |
+
],
|
456 |
+
[
|
457 |
+
'base' => $catalog_feed_directory,
|
458 |
+
'file' => '.htaccess',
|
459 |
+
'content' => 'deny from all',
|
460 |
+
],
|
461 |
+
];
|
462 |
+
|
463 |
+
foreach ( $files as $file ) {
|
464 |
+
|
465 |
+
if ( wp_mkdir_p( $file['base'] ) && ! file_exists( trailingslashit( $file['base'] ) . $file['file'] ) ) {
|
466 |
+
|
467 |
+
if ( $file_handle = @fopen( trailingslashit( $file['base'] ) . $file['file'], 'w' ) ) {
|
468 |
+
|
469 |
+
fwrite( $file_handle, $file['content'] );
|
470 |
+
fclose( $file_handle );
|
471 |
+
}
|
472 |
+
}
|
473 |
+
}
|
474 |
+
}
|
475 |
+
|
476 |
+
|
477 |
+
/**
|
478 |
+
* Writes the product catalog feed file with data for the given product IDs.
|
479 |
+
*
|
480 |
+
* @since 1.11.0
|
481 |
+
*
|
482 |
+
* @param int[] $wp_ids product IDs
|
483 |
+
* @param bool $is_dry_run whether this is a dry run or the file should be written
|
484 |
+
* @return bool
|
485 |
+
*/
|
486 |
+
public function write_product_feed_file( $wp_ids, $is_dry_run = false ) {
|
487 |
|
488 |
try {
|
489 |
|
|
|
|
|
|
|
|
|
|
|
|
|
490 |
|
491 |
+
if ( ! $is_dry_run ) {
|
492 |
+
|
493 |
+
$file_path = $this->get_file_path();
|
494 |
+
|
495 |
+
$feed_file = @fopen( $this->get_file_path(), 'w' );
|
496 |
+
|
497 |
+
if ( false === $feed_file || ! is_writable( $file_path ) ) {
|
498 |
+
throw new Framework\SV_WC_Plugin_Exception( __( 'Could not open the product catalog feed file for writing', 'facebook-for-woocommerce' ), 500 );
|
499 |
+
}
|
500 |
+
|
501 |
+
fwrite( $feed_file, $this->get_product_feed_header_row() );
|
502 |
+
}
|
503 |
|
504 |
$product_group_attribute_variants = array();
|
505 |
|
516 |
}
|
517 |
|
518 |
// skip if not enabled for sync
|
519 |
+
if ( $woo_product->woo_product instanceof \WC_Product && ! SkyVerge\WooCommerce\Facebook\Products::product_should_be_synced( $woo_product->woo_product ) ) {
|
520 |
continue;
|
521 |
}
|
522 |
|
524 |
$woo_product,
|
525 |
$product_group_attribute_variants
|
526 |
);
|
527 |
+
|
528 |
+
if ( ! empty( $feed_file ) ) {
|
529 |
+
fwrite( $feed_file, $product_data_as_feed_row );
|
530 |
+
}
|
531 |
}
|
532 |
+
|
533 |
wp_reset_postdata();
|
534 |
+
|
535 |
+
$written = true;
|
536 |
+
|
537 |
} catch ( Exception $e ) {
|
538 |
+
|
539 |
WC_Facebookcommerce_Utils::log( json_encode( $e->getMessage() ) );
|
540 |
+
|
541 |
+
$written = false;
|
542 |
}
|
543 |
+
|
544 |
+
if ( ! empty( $feed_file ) ) {
|
545 |
+
fclose( $feed_file );
|
546 |
+
}
|
547 |
+
|
548 |
+
return $written;
|
549 |
}
|
550 |
|
551 |
public function get_product_feed_header_row() {
|
555 |
'visibility,default_product,variant' . PHP_EOL;
|
556 |
}
|
557 |
|
558 |
+
|
559 |
/**
|
560 |
+
* Assembles product payload in feed upload for initial sync.
|
561 |
+
*
|
562 |
+
* @param \WC_Facebook_Product $woo_product WooCommerce product object normalized by Facebook
|
563 |
+
* @param array $attribute_variants passed by reference
|
564 |
+
* @return string product feed line data
|
565 |
+
*/
|
566 |
+
private function prepare_product_for_feed( $woo_product, &$attribute_variants ) {
|
567 |
+
|
568 |
$product_data = $woo_product->prepare_product( null, true );
|
569 |
$item_group_id = $product_data['retailer_id'];
|
570 |
+
|
571 |
// prepare variant column for variable products
|
572 |
$product_data['variant'] = '';
|
573 |
+
|
574 |
+
if ( $woo_product->is_type( 'variation' ) ) {
|
575 |
+
|
576 |
$parent_id = $woo_product->get_parent_id();
|
577 |
|
578 |
if ( ! isset( $attribute_variants[ $parent_id ] ) ) {
|
579 |
+
|
580 |
+
$parent_product = new \WC_Facebook_Product( $parent_id );
|
581 |
+
$gallery_urls = array_filter( $parent_product->get_gallery_urls() );
|
582 |
+
$variation_id = $parent_product->find_matching_product_variation();
|
583 |
+
$variants_for_group = $parent_product->prepare_variants_for_group( true );
|
584 |
+
$parent_attribute_values = [
|
585 |
+
'gallery_urls' => $gallery_urls,
|
586 |
+
'default_variant_id' => $variation_id,
|
587 |
+
'item_group_id' => \WC_Facebookcommerce_Utils::get_fb_retailer_id( $parent_product ),
|
588 |
+
];
|
589 |
+
|
590 |
foreach ( $variants_for_group as $variant ) {
|
591 |
+
if ( isset( $variant['product_field'], $variant['options'] ) ) {
|
592 |
+
$parent_attribute_values[ $variant['product_field'] ] = $variant['options'];
|
593 |
+
}
|
594 |
}
|
595 |
+
|
596 |
// cache product group variants
|
597 |
$attribute_variants[ $parent_id ] = $parent_attribute_values;
|
598 |
+
|
599 |
+
} else {
|
600 |
+
|
601 |
+
$parent_attribute_values = $attribute_variants[ $parent_id ];
|
602 |
}
|
603 |
+
|
604 |
+
$variants_for_item = $woo_product->prepare_variants_for_item( $product_data );
|
605 |
+
$variant_feed_column = [];
|
606 |
+
|
607 |
foreach ( $variants_for_item as $variant_array ) {
|
608 |
+
|
609 |
static::format_variant_for_feed(
|
610 |
$variant_array['product_field'],
|
611 |
$variant_array['options'][0],
|
613 |
$variant_feed_column
|
614 |
);
|
615 |
}
|
616 |
+
|
617 |
+
if ( isset( $product_data['custom_data'] ) && is_array( $product_data['custom_data'] ) ) {
|
618 |
+
|
619 |
foreach ( $product_data['custom_data'] as $product_field => $value ) {
|
620 |
+
|
621 |
static::format_variant_for_feed(
|
622 |
$product_field,
|
623 |
$value,
|
626 |
);
|
627 |
}
|
628 |
}
|
629 |
+
|
630 |
if ( ! empty( $variant_feed_column ) ) {
|
631 |
+
$product_data['variant'] = '"' . implode( ',', $variant_feed_column ) . '"';
|
|
|
632 |
}
|
633 |
+
|
634 |
if ( isset( $parent_attribute_values['gallery_urls'] ) ) {
|
635 |
+
$product_data['additional_image_urls'] = array_merge( $product_data['additional_image_urls'], $parent_attribute_values['gallery_urls'] );
|
|
|
|
|
|
|
|
|
636 |
}
|
637 |
+
|
638 |
if ( isset( $parent_attribute_values['item_group_id'] ) ) {
|
639 |
$item_group_id = $parent_attribute_values['item_group_id'];
|
640 |
}
|
641 |
|
642 |
+
$product_data['default_product'] = $parent_attribute_values['default_variant_id'] == $woo_product->id ? 'default' : '';
|
|
|
|
|
|
|
643 |
|
644 |
// If this group has default variant value, log this product item
|
645 |
+
if ( isset( $parent_attribute_values['default_variant_id'] ) && ! empty( $parent_attribute_values['default_variant_id'] ) ) {
|
|
|
646 |
$this->has_default_product_count++;
|
647 |
} else {
|
648 |
$this->no_default_product_count++;
|
651 |
|
652 |
// log simple product
|
653 |
if ( ! isset( $product_data['default_product'] ) ) {
|
654 |
+
|
655 |
$this->no_default_product_count++;
|
656 |
+
|
657 |
$product_data['default_product'] = '';
|
658 |
}
|
659 |
|
686 |
$product_data['variant'] . PHP_EOL;
|
687 |
}
|
688 |
|
689 |
+
|
690 |
private function create_feed() {
|
691 |
$result = $this->fbgraph->create_feed(
|
692 |
$this->facebook_catalog_id,
|
710 |
private function create_upload( $facebook_feed_id ) {
|
711 |
$result = $this->fbgraph->create_upload(
|
712 |
$facebook_feed_id,
|
713 |
+
$this->get_file_path()
|
|
|
714 |
);
|
715 |
if ( is_null( $result ) || ! isset( $result['id'] ) || ! $result['id'] ) {
|
716 |
$this->log_feed_progress( json_encode( $result ) );
|
773 |
* @return string
|
774 |
*/
|
775 |
public function is_upload_complete( &$settings ) {
|
776 |
+
|
777 |
+
$upload_id = facebook_for_woocommerce()->get_integration()->get_upload_id();
|
778 |
+
$result = $this->fbgraph->get_upload_status( $upload_id );
|
779 |
+
|
780 |
if ( is_wp_error( $result ) || ! isset( $result['body'] ) ) {
|
781 |
+
|
782 |
$this->log_feed_progress( json_encode( $result ) );
|
783 |
+
|
784 |
return 'error';
|
785 |
}
|
786 |
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: facebook, automattic, woothemes
|
|
3 |
Tags: facebook, shop, catalog, advertise, pixel, product
|
4 |
Requires at least: 4.4
|
5 |
Tested up to: 5.3.2
|
6 |
-
Stable tag: 1.
|
7 |
Requires PHP: 5.6 or greater
|
8 |
MySQL: 5.6 or greater
|
9 |
License: GPLv2 or later
|
@@ -39,6 +39,17 @@ When opening a bug on GitHub, please give us as many details as possible.
|
|
39 |
|
40 |
== Changelog ==
|
41 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
= 2020.03.17 - version 1.10.2 =
|
43 |
* Tweak - Add a setting to easily enable debug logging
|
44 |
* Tweak - Allow third party plugins and themes to track an add-to-cart event on added_to_cart JS event
|
3 |
Tags: facebook, shop, catalog, advertise, pixel, product
|
4 |
Requires at least: 4.4
|
5 |
Tested up to: 5.3.2
|
6 |
+
Stable tag: 1.11.0
|
7 |
Requires PHP: 5.6 or greater
|
8 |
MySQL: 5.6 or greater
|
9 |
License: GPLv2 or later
|
39 |
|
40 |
== Changelog ==
|
41 |
|
42 |
+
= 2020.04.23 - version 1.11.0 =
|
43 |
+
* Tweak - Sync products using Facebook's feed pull method
|
44 |
+
* Fix - When filtering products by sync enabled status, make sure variable products with sync disabled status do not show up in results
|
45 |
+
* Fix - Make sure that the Facebook sync enabled and catalog visibility columns are properly displayed on narrow screen sizes on some browsers
|
46 |
+
* Fix - Do not show a confirmation modal when saving a variable product that was previously synced but belongs now to a term excluded from sync
|
47 |
+
* Fix - Ensure variable products excluded from sync are not synced in Facebook
|
48 |
+
* Fix - Trigger a modal prompt when attempting to enable sync for variations of a variable product that belongs to a term excluded from sync
|
49 |
+
* Fix - Address potential PHP warnings in the product feed with non-standard product variations introduced by third party plugins
|
50 |
+
* Fix - Fix a JavaScript error triggered on the settings page while trying to excluded terms from sync
|
51 |
+
* Fix - Fix a JavaScript error triggered when saving a product and using checkboxes for tags
|
52 |
+
|
53 |
= 2020.03.17 - version 1.10.2 =
|
54 |
* Tweak - Add a setting to easily enable debug logging
|
55 |
* Tweak - Allow third party plugins and themes to track an add-to-cart event on added_to_cart JS event
|