Facebook for WooCommerce - Version 1.11.0

Version Description

Download this release

Release Info

Developer SkyVerge
Plugin Icon 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 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
- if ( 'facebook_exclude' === chosenBulkAction || 'facebook_include' === chosenBulkAction ) {
73
74
let products = [];
75
@@ -195,26 +196,34 @@ jQuery( document ).ready( function( $ ) {
195
return true;
196
}
197
198
- let $submitButton = $( this ),
199
$visibleCheckbox = $( 'input[name="fb_visibility"]' ),
200
- productID = parseInt( $( 'input#post_ID' ).val(), 10 ),
201
- productCat = [],
202
- productTag = $( 'textarea[name="tax_input[product_tag]"]' ).val().split( ',' ),
203
- syncEnabled = $( 'input#fb_sync_enabled' ).prop( 'checked' );
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: 'facebook_for_woocommerce_set_product_sync_prompt',
213
- security: facebook_for_woocommerce_products_admin.set_product_sync_prompt_nonce,
214
- sync_enabled: syncEnabled ? 'enabled' : 'disabled',
215
- product: productID,
216
- categories: productCat,
217
- tags: productTag
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(n){var o=window.pagenow.length?window.pagenow:"";window.typenow.length&&window.typenow;if("edit-product"===o){var e=n(".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=n(this).data("action"),c="show"===e?"yes":"no",t=parseInt(n(this).data("product-id"),10);"show"===e?n(this).hide().next("button").show():"hide"===e&&n(this).hide().prev("button").show(),n.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;n("input#doaction, input#doaction2").on("click",function(o){if(i)return!0;o.preventDefault();var e=n(this),c=e.prev("select").val();if("facebook_exclude"===c||"facebook_include"===c){var t=[];n.each(n('input[name="post[]"]:checked'),function(){t.push(parseInt(n(this).val(),10))}),n.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?(n("#wc-backbone-modal-dialog .modal-close").trigger("click"),new n.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:o.data}),n(".facebook-for-woocommerce-toggle-product-visibility").on("click",function(o){blockModal(),n(this).hasClass("hide-products")&&n.each(t,function(){var o=n("#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=n("#fb_sync_enabled"),r=t.closest(".woocommerce_options_panel");t.on("click",function(){c(n(this).prop("checked"),r)}),c(t.prop("checked"),r),n(".woocommerce_variations").on("change",".js-variable-fb-sync-toggle",function(){c(n(this).prop("checked"),n(this).closest(".wc-metabox-content"))}),n("#woocommerce-product-data").on("change",".js-fb-product-image-source",function(){var o=n(this).closest(".woocommerce_options_panel, .wc-metabox-content"),e=n(this).val();o.find(".product-image-source-field").closest(".form-field").hide(),o.find(".show-if-product-image-source-"+e).closest(".form-field").show()}),n(".js-fb-product-image-source:checked").trigger("change"),n("#woocommerce-product-data").on("woocommerce_variations_loaded",function(){n(".js-variable-fb-sync-toggle").trigger("change"),n(".js-fb-product-image-source:checked").trigger("change")});var s=!1;n('form#post input[type="submit"]').on("click",function(o){if(s)return!0;o.preventDefault();var e=n(this),c=n('input[name="fb_visibility"]'),t=parseInt(n("input#post_ID").val(),10),i=[],r=n('textarea[name="tax_input[product_tag]"]').val().split(","),a=n("input#fb_sync_enabled").prop("checked");n('#taxonomy-product_cat input[name="tax_input[product_cat][]"]:checked').each(function(){i.push(parseInt(n(this).val(),10))}),0<t?n.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:a?"enabled":"disabled",product:t,categories:i,tags:r},function(o){o&&!o.success&&(a||!a&&c.length&&c.is(":checked"))?(n("#wc-backbone-modal-dialog .modal-close").trigger("click"),new n.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:o.data}),n(".facebook-for-woocommerce-toggle-product-visibility").on("click",function(o){blockModal(),n(this).hasClass("hide-products")&&c.prop("checked",!1),s=!0,e.trigger("click")})):(s=!0,e.trigger("click"))}):(s=!0,e.trigger("click"))})}});
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
- $ = jQuery;
11
12
- /**
13
- * Determines if the current modal is blocked.
14
- *
15
- * @returns {boolean}
16
- */
17
- function isModalBlocked() {
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
- * Unblocks the current modal.
41
- */
42
- function unBlockModal() {
43
- $( '.wc-backbone-modal-content' ).removeClass( 'processing' ).unblock();
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";function isModalBlocked(){var o=$(".wc-backbone-modal-content");return o.is(".processing")||o.parents(".processing").length}function blockModal(){if(!isModalBlocked())return $(".wc-backbone-modal-content").addClass("processing").block({message:null,overlayCSS:{background:"#fff",opacity:.6}})}function unBlockModal(){$(".wc-backbone-modal-content").removeClass("processing").unblock()}$=jQuery;
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
- // Launch the confirm dialog immediately if the param is in the URL.
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
- $( '#sync_progress' ).show().html( '<span style="color: #DC3232">' + message + '</span>' );
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 $( this ).data( 'default' ) !== 'undefined' ) {
270
- $( this ).val( $( this ).data( 'default' ) ).trigger( 'change' );
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.includes( 'settings_saved' )) {
326
console.log( response );
327
callback( response );
328
} else {
329
- console.log( 'Fail response on save_settings_and_sync' );
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.includes( 'settings_saved' )) {
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
- // no-op
477
}
478
479
function setAccessTokenAndPageId(message) {
@@ -549,12 +561,51 @@ function setMsgerChatSetup( data ) {
549
}
550
}
551
552
- function iFrameListener(event) {
553
- // Fix for web.facebook.com
554
const origin = event.origin || event.originalEvent.origin;
555
- if (origin != window.facebookAdsToolboxConfig.popupOrigin &&
556
- urlFromSameDomain( origin, window.facebookAdsToolboxConfig.popupOrigin )) {
557
- window.facebookAdsToolboxConfig.popupOrigin = origin;
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
- // should be last message received
598
- setAccessTokenAndPageId( event.data );
599
- save_settings_and_sync( event.data );
600
-
601
- // hide Facebook fancy box and show integration settings
602
- jQuery( '#fbsetup' ).hide();
603
- jQuery( '#integration-settings' ).show();
604
- jQuery( '.woocommerce-save-button' ).show();
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 ack msger chat', event.data );
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
- $( '#sync_progress' ).show().html( '<span style="color: #DC3232">' + facebook_for_woocommerce_settings_sync.i18n.feed_upload_error + '</span>' );
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
- // check background processor status in case products are being synced in the background when the page loads
964
- check_background_processor_status();
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 + '&regenerate=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+"&regenerate=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.10.2';
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', get_admin_url() . '/admin.php?page=wc-settings&tab=integration' . '&section=facebookcommerce' );
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&section=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', [ $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,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
- add_action(
66
- 'woocommerce_after_checkout_form',
67
- array( $this, 'inject_initiate_checkout_event' )
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->check_last_event( 'Search' ) ) {
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 \WC_Product $product the product just added to the cart
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 for checkout page.
450
*/
451
public function inject_initiate_checkout_event() {
452
453
- if ( ! self::$isEnabled || $this->pixel->check_last_event( 'InitiateCheckout' ) ) {
454
return;
455
}
456
@@ -465,20 +462,29 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
465
466
467
/**
468
- * Triggers Purchase for payment transaction complete and for the thank you page in cases of delayed payment.
469
*
470
* @param int $order_id order identifier
471
*/
472
public function inject_purchase_event( $order_id ) {
473
474
- if ( ! self::$isEnabled || $this->pixel->check_last_event( 'Purchase' ) ) {
475
return;
476
}
477
478
- $this->inject_subscribe_event( $order_id );
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' => $this->get_cart_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 for payment transaction complete of purchase with
510
- * subscription.
511
*/
512
public function inject_subscribe_event( $order_id ) {
513
- if ( ! function_exists( 'wcs_get_subscriptions_for_order' ) ) {
514
return;
515
}
516
517
- $subscription_ids = wcs_get_subscriptions_for_order( $order_id );
518
- foreach ( $subscription_ids as $subscription_id ) {
519
- $subscription = new WC_Subscription( $subscription_id );
520
- $this->pixel->inject_event(
521
- 'Subscribe',
522
- array(
523
- 'sign_up_fee' => $subscription->get_sign_up_fee(),
524
- 'value' => $subscription->get_total(),
525
- 'currency' => get_woocommerce_currency(),
526
- )
527
- );
528
}
529
}
530
531
/**
532
- * Triggers Purchase for thank you page for COD, BACS CHEQUE payment
533
- * which won't invoke woocommerce_payment_complete.
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
- $order = new WC_Order( $order_id );
542
- $payment = $order->get_payment_method();
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
- * Prevent double-fires by checking the last event
188
*/
189
- public function check_last_event( $event_name ) {
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['fb_visibility'] );
801
802
if ( ! $product->is_type( 'variable' ) ) {
803
@@ -813,9 +830,10 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
813
}
814
}
815
816
- $this->update_fb_visibility( $product->get_id(), $is_visible ? self::FB_SHOP_PRODUCT_VISIBLE : self::FB_SHOP_PRODUCT_HIDDEN );
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 || ! \SkyVerge\WooCommerce\Facebook\Products::product_should_be_synced( $woo_product->woo_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
- * Update FB visibility for trashing and restore.
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::is_sync_enabled_for_product( $product ) ) {
937
return;
938
}
939
940
- // change from publish status -> unpublish status, e.g. trash, draft, etc.
941
// change from trash status -> publish status
942
// no need to update for change from trash <-> unpublish status
943
- if ( ( $old_status == 'publish' && $new_status != 'publish' ) ||
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 ( get_post_status( $wp_id ) != 'publish' ) {
960
return;
961
}
962
963
- $woo_product = new WC_Facebook_Product( $wp_id );
964
965
// skip if not enabled for sync
966
- if ( ! $woo_product->woo_product instanceof \WC_Product || ! \SkyVerge\WooCommerce\Facebook\Products::product_should_be_synced( $woo_product->woo_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 || ! \SkyVerge\WooCommerce\Facebook\Products::product_should_be_synced( $woo_product->woo_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->get_page_access_token() ) {
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
- wp_die();
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
- wp_die();
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->settings['fb_upload_id'] = '';
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
- * Check Feed Upload Status
1532
**/
1533
- function ajax_check_feed_upload_status() {
1534
- WC_Facebookcommerce_Utils::check_woo_ajax_permissions( 'check feed upload status', true );
1535
check_ajax_referer( 'wc_facebook_settings_jsx' );
1536
if ( $this->get_page_access_token() ) {
1537
- $response = array(
1538
'connected' => true,
1539
'status' => 'in progress',
1540
- );
1541
- if ( ! empty( $this->settings['fb_upload_id'] ) ) {
1542
if ( ! isset( $this->fbproductfeed ) ) {
1543
if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) {
1544
include_once 'includes/fbproductfeed.php';
1545
}
1546
- $this->fbproductfeed = new WC_Facebook_Product_Feed(
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
- $response = array(
1556
'connected' => true,
1557
'status' => 'error',
1558
- );
1559
}
1560
- if ( $response['status'] == 'complete' ) {
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
- $response = array(
1571
- 'connected' => false,
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->get_page_access_token() || ! $this->get_product_catalog_id() ) {
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
- 'title' => __( 'Force daily resync at', 'facebook-for-woocommerce' ),
2502
- 'class' => 'product-sync-field resync-schedule-fieldset',
2503
- 'type' => 'resync_schedule',
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
- <?php endif; ?>
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
&mdash;
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
- <a
2792
- id="woocommerce-facebook-settings-sync-products"
2793
- class="button product-sync-field"
2794
- href="#"
2795
- style="vertical-align: middle; margin-left: 20px;"
2796
- ><?php esc_html_e( 'Sync products', 'facebook-for-woocommerce' ); ?></a>
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 $this->get_page_access_token() && $this->get_facebook_page_id();
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
- function on_quick_and_bulk_edit_save( $product ) {
4093
4094
// bail if not a product or product is not enabled for sync
4095
- if ( ! $product instanceof \WC_Product || ! Products::is_sync_enabled_for_product( $product ) ) {
4096
return;
4097
}
4098
4099
$wp_id = $product->get_id();
4100
- $visibility = get_post_status( $wp_id ) === 'publish'
4101
- ? self::FB_SHOP_PRODUCT_VISIBLE
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
- // case 2: product never publish to FB, new status is not publish
4108
- // case 3: product new status is not publish and published before
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
&mdash;
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.10.2
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.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.10.2\n"
6
"Report-Msgid-Bugs-To: "
7
"https://woocommerce.com/my-account/marketplace-ticket-form/\n"
8
- "POT-Creation-Date: 2020-03-18 01:00:59+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,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:188
21
msgid "Facebook Commerce and Dynamic Ads (Pixel) Extension"
22
msgstr ""
23
24
- #: facebook-commerce.php:585
25
msgid "Facebook ID:"
26
msgstr ""
27
28
- #: facebook-commerce.php:596
29
msgid "Variant IDs:"
30
msgstr ""