Facebook for WooCommerce - Version 3.0.5

Version Description

  • 2022-11-30 =
  • Add - Debug tools to help reset settings, delete background options and delete catalog products.
  • Add - Inbox note about Facebook menu moved under the Marketing menu.
  • Dev - Add .nvmrc file.
  • Fix - Facebook Product ID is different from what Facebook ID actually is.
  • Fix - Prevent class redeclaration error for class WC_Facebookcommerce_Utils.
  • Fix - Prevent errors in the disconnection procedure when the user id is missing.
  • Tweak - Remove Facebook Orders sync functionality.
  • Tweak - Update the API version set in the fbAsyncInit script in Advertise tab.
  • Tweak - Update the plugin URI in the plugin file.
Download this release

Release Info

Developer automattic
Plugin Icon Facebook for WooCommerce
Version 3.0.5
Comparing to
See all releases

Code changes from version 3.0.4 to 3.0.5

Files changed (49) hide show
  1. assets/build/admin/orders.asset.php +0 -1
  2. assets/build/admin/orders.js +0 -1
  3. assets/build/admin/product-categories.asset.php +1 -1
  4. assets/build/admin/product-categories.js +1 -1
  5. assets/build/admin/product-sets-admin.asset.php +1 -1
  6. assets/build/admin/product-sets-admin.js +1 -1
  7. assets/build/admin/products-admin.asset.php +1 -1
  8. assets/build/admin/products-admin.js +1 -1
  9. assets/build/admin/settings-commerce.asset.php +1 -1
  10. assets/build/admin/settings-commerce.js +1 -1
  11. assets/build/admin/settings-sync.asset.php +1 -1
  12. assets/build/admin/settings-sync.js +1 -1
  13. assets/js/admin/orders.js +0 -541
  14. changelog.txt +11 -0
  15. class-wc-facebookcommerce.php +32 -0
  16. facebook-commerce.php +1 -1
  17. facebook-for-woocommerce.php +3 -3
  18. i18n/languages/facebook-for-woocommerce.pot +165 -197
  19. includes/AJAX.php +0 -107
  20. includes/API.php +0 -135
  21. includes/API/Orders/Abstract_Request.php +0 -36
  22. includes/API/Orders/Acknowledge/Request.php +0 -65
  23. includes/API/Orders/Cancel/Request.php +0 -69
  24. includes/API/Orders/Fulfillment/Request.php +0 -62
  25. includes/API/Orders/Order.php +0 -168
  26. includes/API/Orders/Read/Request.php +0 -83
  27. includes/API/Orders/Read/Response.php +0 -40
  28. includes/API/Orders/Refund/Request.php +0 -62
  29. includes/API/Orders/Request.php +0 -105
  30. includes/API/Orders/Response.php +0 -48
  31. includes/Admin.php +0 -1
  32. includes/Admin/Notes/SettingsMoved.php +87 -0
  33. includes/Admin/Product_Sync_Meta_Box.php +10 -6
  34. includes/Admin/Settings_Screens/Advertise.php +2 -1
  35. includes/Commerce.php +0 -29
  36. includes/Commerce/Orders.php +0 -903
  37. includes/Handlers/Connection.php +17 -8
  38. includes/Jobs/DeleteProductsFromFBCatalog.php +129 -0
  39. includes/Jobs/JobManager.php +16 -0
  40. includes/Jobs/ResetAllProductsFBSettings.php +120 -0
  41. includes/Utilities/DebugTools.php +124 -0
  42. includes/Utilities/Shipment.php +0 -689
  43. includes/fbutils.php +528 -524
  44. readme.txt +12 -1
  45. vendor/autoload.php +3 -16
  46. vendor/composer/autoload_classmap.php +4 -12
  47. vendor/composer/autoload_real.php +4 -4
  48. vendor/composer/autoload_static.php +8 -16
  49. vendor/composer/installed.php +6 -6
assets/build/admin/orders.asset.php DELETED
@@ -1 +0,0 @@
1
- <?php return array('dependencies' => array('wp-polyfill'), 'version' => '869fc31f506af286cd2b4e213105990a');
 
assets/build/admin/orders.js DELETED
@@ -1 +0,0 @@
1
- !function(e){var o={};function r(c){if(o[c])return o[c].exports;var n=o[c]={i:c,l:!1,exports:{}};return e[c].call(n.exports,n,n.exports,r),n.l=!0,n.exports}r.m=e,r.c=o,r.d=function(e,o,c){r.o(e,o)||Object.defineProperty(e,o,{enumerable:!0,get:c})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,o){if(1&o&&(e=r(e)),8&o)return e;if(4&o&&"object"==typeof e&&e&&e.__esModule)return e;var c=Object.create(null);if(r.r(c),Object.defineProperty(c,"default",{enumerable:!0,value:e}),2&o&&"string"!=typeof e)for(var n in e)r.d(c,n,function(o){return e[o]}.bind(null,n));return c},r.n=function(e){var o=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(o,"a",o),o},r.o=function(e,o){return Object.prototype.hasOwnProperty.call(e,o)},r.p="",r(r.s=7)}({7:function(e,o){jQuery(document).ready((function(e){"use strict";var o=Boolean(wc_facebook_commerce_orders.is_commerce_order),r={restrict_order_statuses:function(e){e.find("option").each((function(e,o){-1===wc_facebook_commerce_orders.allowed_commerce_statuses.indexOf(o.value)&&o.remove()}))},toggle_created_date_fields_status:function(o){r.toggle_field(e("#order_data").find("input[name*=order_date]"),o)},disable_order_status_field:function(e){r.toggle_field(e,!1)},toggle_order_customer_field:function(o){e("#order_data").find(".form-field.wc-customer-user").toggleClass("hidden",o)},toggle_billing_and_shipping_fields:function(o){e("#order_data").find("a.edit_address").toggleClass("hidden",o)},disable_pending_order_related_fields:function(e){r.toggle_created_date_fields_status(!1),r.disable_order_status_field(e),r.toggle_order_customer_field(!0),r.toggle_billing_and_shipping_fields(!0)},maybe_disable_refunds:function(){"completed"!==wc_facebook_commerce_orders.order_status&&e(".wc-order-bulk-actions .refund-items").hide()},toggle_field:function(e,o){e.hasClass("wc-enhanced-select")&&(e=e.next("span.select2-container")),o?e.css("pointer-events","all").css("opacity","1.0"):e.css("pointer-events","none").css("opacity","0.4")}},c=e('form[id="post"]'),n=e("#order_status"),a=n.val(),t=wc_facebook_commerce_orders.shipment_tracking,d="",_="",i="",s="";function l(o){unBlockModal(),e(".facebook-for-woocommerce-modal .wc-backbone-modal-content article").html("<p>"+o+"</p>"),e(".facebook-for-woocommerce-modal .wc-backbone-modal-content footer").remove()}function f(){var o=arguments.length>0&&void 0!==arguments[0]&&arguments[0],r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;if(!r.length)return alert(wc_facebook_commerce_orders.i18n.missing_tracking_number_error),!1;o&&blockModal(),c.find("button[type=submit].save_order").prop("disabled",!0).append('<span class="spinner is-active"></span>'),e.post(ajaxurl,{action:wc_facebook_commerce_orders.complete_order_action,order_id:e("#post_ID").val(),tracking_number:r,carrier_code:n,nonce:wc_facebook_commerce_orders.complete_order_nonce},(function(e){if(o&&unBlockModal(),e&&e.success)c.data("allow-submit",!0).trigger("submit");else{var r=e&&e.data?e.data:wc_facebook_commerce_orders.i18n.unknown_error;alert(r)}})).fail((function(){l(wc_facebook_commerce_orders.i18n.unknown_error)})).always((function(){c.find("button[type=submit].save_order").prop("disabled",!1).find("span.spinner").remove()}))}function m(){var o=e("#refund_reason"),r=e("#wc_facebook_refund_reason").clone().css("width",o.css("width")),c=o.closest("tr"),n=c.clone();c.find("td.total").css("width","16em").end().find("#refund_reason").replaceWith(r.show()).end().find('label[for="refund_reason"]').attr("for","wc_facebook_refund_reason"),c.after(n),u(c,"wc_facebook_refund_reason",wc_facebook_commerce_orders.i18n.refund_reason_label,wc_facebook_commerce_orders.i18n.refund_reason_tooltip),u(n,"refund_reason",wc_facebook_commerce_orders.i18n.refund_description_label,wc_facebook_commerce_orders.i18n.refund_description_tooltip)}function u(e,o,r,c){var n=e.find('label[for="'+o+'"]'),a=n.find(".woocommerce-help-tip").clone();n.text(r),c&&a.length&&(n.prepend(a),a.attr("data-tip",c).tipTip({attribute:"data-tip",fadeIn:50,fadeOut:50,delay:200}))}Array.isArray(t)&&t[0]&&(d=t[0].tracking_number,_=t[0].carrier_code),o&&(r.restrict_order_statuses(n),"pending"===wc_facebook_commerce_orders.order_status&&r.disable_pending_order_related_fields(n),"cancelled"===wc_facebook_commerce_orders.order_status&&r.disable_order_status_field(n),r.maybe_disable_refunds()),o&&(m(),function(){if(void 0!==window.MutationObserver){var o=document.querySelector("#woocommerce-order-items .inside");o&&new MutationObserver((function(o){o.forEach((function(o){Array.prototype.forEach.call(o.addedNodes,(function(o){e(o).is(".wc-order-refund-items")&&m()}))}))})).observe(o,{childList:!0})}}()),c.on("submit",(function(r){if(!e("#post").data("skip-cancel-modal")&&"wc-cancelled"!==a&&o&&"wc-cancelled"===n.val())return function(o){return o.preventDefault(),e("#wc-backbone-modal-dialog .modal-close").trigger("click"),new e.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:{message:wc_facebook_commerce_orders.cancel_modal_message,buttons:wc_facebook_commerce_orders.cancel_modal_buttons}}),e(".facebook-for-woocommerce-modal #btn-ok").off("click.facebook_for_commerce").on("click.facebook_for_commerce",(function(o){o.preventDefault(),o.stopPropagation(),blockModal(),e.post(ajaxurl,{action:wc_facebook_commerce_orders.cancel_order_action,order_id:e("#post_ID").val(),reason_code:e('.facebook-for-woocommerce-modal [name="wc_facebook_cancel_reason"]').val(),security:wc_facebook_commerce_orders.cancel_order_nonce},(function(o){o&&o.success?e("#post").data("skip-cancel-modal",!0).trigger("submit"):l(o&&o.data?o.data:wc_facebook_commerce_orders.i18n.unknown_error)})).fail((function(){l(wc_facebook_commerce_orders.i18n.unknown_error)}))})),!1}(r);if(o&&!c.data("allow-submit")){var t=n.val();"wc-refunded"===t&&a!==t&&function(o){o.preventDefault(),e("#wc-backbone-modal-dialog .modal-close").trigger("click"),new e.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:{message:wc_facebook_commerce_orders.refund_modal_message,buttons:wc_facebook_commerce_orders.refund_modal_buttons}}),e(document.body).off("wc_backbone_modal_response.facebook_for_commerce").on("wc_backbone_modal_response.facebook_for_commerce",(function(){e("#refund_reason").val(e("#wc_facebook_refund_reason_modal").val()),c.data("allow-submit",!0).submit()}))}(r),"wc-completed"===t&&(r.preventDefault(),d||_?f(!1,d,_):(e("#wc-backbone-modal-dialog .modal-close").trigger("click"),(s||i)&&e(document.body).off("wc_backbone_modal_loaded").on("wc_backbone_modal_loaded",(function(){s&&e("#wc_facebook_carrier").val(s),i&&e("#wc_facebook_tracking_number").val(i)})),new e.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:{message:wc_facebook_commerce_orders.complete_modal_message,buttons:wc_facebook_commerce_orders.complete_modal_buttons}}),e(".facebook-for-woocommerce-modal #btn-ok").off("click.facebook_for_commerce").on("click.facebook_for_commerce",(function(o){o.preventDefault(),o.stopPropagation(),s=e("#wc_facebook_carrier").val(),f(!0,i=e("#wc_facebook_tracking_number").val(),s)}))))}}))}))}});
 
assets/build/admin/product-categories.asset.php CHANGED
@@ -1 +1 @@
1
- <?php return array('dependencies' => array('wp-polyfill'), 'version' => '4bedc509a19a74c8c274f145cdaff75a');
1
+ <?php return array('dependencies' => array('wp-polyfill'), 'version' => 'a39cb990e426d83042b927927418be12');
assets/build/admin/product-categories.js CHANGED
@@ -1 +1 @@
1
- !function(e){var o={};function t(r){if(o[r])return o[r].exports;var n=o[r]={i:r,l:!1,exports:{}};return e[r].call(n.exports,n,n.exports,t),n.l=!0,n.exports}t.m=e,t.c=o,t.d=function(e,o,r){t.o(e,o)||Object.defineProperty(e,o,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,o){if(1&o&&(e=t(e)),8&o)return e;if(4&o&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&o&&"string"!=typeof e)for(var n in e)t.d(r,n,function(o){return e[o]}.bind(null,n));return r},t.n=function(e){var o=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(o,"a",o),o},t.o=function(e,o){return Object.prototype.hasOwnProperty.call(e,o)},t.p="",t(t.s=8)}({8:function(e,o){jQuery(document).ready((function(e){var o=e('form[id="edittag"]'),t=e("#wc_facebook_google_product_category_id"),r=t.val();o.on("submit",(function(n){o.data("allow-submit")||t.val()===r||(n.preventDefault(),e("#wc-backbone-modal-dialog .modal-close").trigger("click"),new e.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:{message:facebook_for_woocommerce_product_categories.default_google_product_category_modal_message,buttons:facebook_for_woocommerce_product_categories.default_google_product_category_modal_buttons}}),e(document.body).off("wc_backbone_modal_response.facebook_for_commerce").on("wc_backbone_modal_response.facebook_for_commerce",(function(){o.data("allow-submit",!0).find(":submit").trigger("click")})))}))}))}});
1
+ !function(e){var o={};function t(r){if(o[r])return o[r].exports;var n=o[r]={i:r,l:!1,exports:{}};return e[r].call(n.exports,n,n.exports,t),n.l=!0,n.exports}t.m=e,t.c=o,t.d=function(e,o,r){t.o(e,o)||Object.defineProperty(e,o,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,o){if(1&o&&(e=t(e)),8&o)return e;if(4&o&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&o&&"string"!=typeof e)for(var n in e)t.d(r,n,function(o){return e[o]}.bind(null,n));return r},t.n=function(e){var o=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(o,"a",o),o},t.o=function(e,o){return Object.prototype.hasOwnProperty.call(e,o)},t.p="",t(t.s=7)}({7:function(e,o){jQuery(document).ready((function(e){var o=e('form[id="edittag"]'),t=e("#wc_facebook_google_product_category_id"),r=t.val();o.on("submit",(function(n){o.data("allow-submit")||t.val()===r||(n.preventDefault(),e("#wc-backbone-modal-dialog .modal-close").trigger("click"),new e.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:{message:facebook_for_woocommerce_product_categories.default_google_product_category_modal_message,buttons:facebook_for_woocommerce_product_categories.default_google_product_category_modal_buttons}}),e(document.body).off("wc_backbone_modal_response.facebook_for_commerce").on("wc_backbone_modal_response.facebook_for_commerce",(function(){o.data("allow-submit",!0).find(":submit").trigger("click")})))}))}))}});
assets/build/admin/product-sets-admin.asset.php CHANGED
@@ -1 +1 @@
1
- <?php return array('dependencies' => array('wp-polyfill'), 'version' => '646cbd7ed7e31a6978b8ef073dc8196f');
1
+ <?php return array('dependencies' => array('wp-polyfill'), 'version' => '99baa0c193b4b3b6aaba794ea3f25217');
assets/build/admin/product-sets-admin.js CHANGED
@@ -1 +1 @@
1
- !function(e){var t={};function o(r){if(t[r])return t[r].exports;var n=t[r]={i:r,l:!1,exports:{}};return e[r].call(n.exports,n,n.exports,o),n.l=!0,n.exports}o.m=e,o.c=t,o.d=function(e,t,r){o.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(o.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)o.d(r,n,function(t){return e[t]}.bind(null,n));return r},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,"a",t),t},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.p="",o(o.s=9)}({9:function(e,t){jQuery(document).ready((function(e){jQuery(".select2.wc-facebook").length&&(jQuery(".select2.wc-facebook").select2().addClass("visible").attr("disabled",!1),jQuery(".select2.updating-message").addClass("hidden"),jQuery(document).ajaxSuccess((function(e,t,o){var r=new URLSearchParams(o.data);r.has("action")&&"add-tag"===r.get("action")&&r.has("taxonomy")&&"fb_product_set"===r.get("taxonomy")&&jQuery(".select2.wc-facebook").select2().val(null).trigger("change")}))),e('form[id="addtag"] input[name="submit"]').on("click",(function(t){var o=e("#_wc_facebook_product_cats").val(),r=[];window.facebook_for_woocommerce_product_sets&&window.facebook_for_woocommerce_product_sets.excluded_category_ids&&(r=window.facebook_for_woocommerce_product_sets.excluded_category_ids),o.length>0&&r.length>0&&function(e,t){for(var o=0,r=0;r<t.length;r++)t.includes(t[r])&&o++;return o>0}(0,r)&&alert(facebook_for_woocommerce_product_sets.excluded_category_warning_message)}))}))}});
1
+ !function(e){var t={};function o(r){if(t[r])return t[r].exports;var n=t[r]={i:r,l:!1,exports:{}};return e[r].call(n.exports,n,n.exports,o),n.l=!0,n.exports}o.m=e,o.c=t,o.d=function(e,t,r){o.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(o.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)o.d(r,n,function(t){return e[t]}.bind(null,n));return r},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,"a",t),t},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.p="",o(o.s=8)}({8:function(e,t){jQuery(document).ready((function(e){jQuery(".select2.wc-facebook").length&&(jQuery(".select2.wc-facebook").select2().addClass("visible").attr("disabled",!1),jQuery(".select2.updating-message").addClass("hidden"),jQuery(document).ajaxSuccess((function(e,t,o){var r=new URLSearchParams(o.data);r.has("action")&&"add-tag"===r.get("action")&&r.has("taxonomy")&&"fb_product_set"===r.get("taxonomy")&&jQuery(".select2.wc-facebook").select2().val(null).trigger("change")}))),e('form[id="addtag"] input[name="submit"]').on("click",(function(t){var o=e("#_wc_facebook_product_cats").val(),r=[];window.facebook_for_woocommerce_product_sets&&window.facebook_for_woocommerce_product_sets.excluded_category_ids&&(r=window.facebook_for_woocommerce_product_sets.excluded_category_ids),o.length>0&&r.length>0&&function(e,t){for(var o=0,r=0;r<t.length;r++)t.includes(t[r])&&o++;return o>0}(0,r)&&alert(facebook_for_woocommerce_product_sets.excluded_category_warning_message)}))}))}});
assets/build/admin/products-admin.asset.php CHANGED
@@ -1 +1 @@
1
- <?php return array('dependencies' => array('wp-polyfill'), 'version' => '9a3d46c8f97dbaacd5b0c49075c97e31');
1
+ <?php return array('dependencies' => array('wp-polyfill'), 'version' => '8ef427f8a9af1c8b6c8ab38d603bf1de');
assets/build/admin/products-admin.js CHANGED
@@ -1 +1 @@
1
- !function(o){var e={};function t(c){if(e[c])return e[c].exports;var n=e[c]={i:c,l:!1,exports:{}};return o[c].call(n.exports,n,n.exports,t),n.l=!0,n.exports}t.m=o,t.c=e,t.d=function(o,e,c){t.o(o,e)||Object.defineProperty(o,e,{enumerable:!0,get:c})},t.r=function(o){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(o,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(o,"__esModule",{value:!0})},t.t=function(o,e){if(1&e&&(o=t(o)),8&e)return o;if(4&e&&"object"==typeof o&&o&&o.__esModule)return o;var c=Object.create(null);if(t.r(c),Object.defineProperty(c,"default",{enumerable:!0,value:o}),2&e&&"string"!=typeof o)for(var n in o)t.d(c,n,function(e){return o[e]}.bind(null,n));return c},t.n=function(o){var e=o&&o.__esModule?function(){return o.default}:function(){return o};return t.d(e,"a",e),e},t.o=function(o,e){return Object.prototype.hasOwnProperty.call(o,e)},t.p="",t(t.s=10)}({10:function(o,e){jQuery(document).ready((function(o){var e=window.pagenow.length?window.pagenow:"";if(window.typenow.length&&window.typenow,"edit-product"===e){var t=!1;o("input#doaction, input#doaction2").on("click",(function(e){if(t)return!0;e.preventDefault();var c=o(this),n=c.prev("select").val();if("facebook_include"===n){var r=[];o.each(o('input[name="post[]"]:checked'),(function(){r.push(parseInt(o(this).val(),10))})),o.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:n,products:r},(function(e){e&&!e.success?(closeExistingModal(),new o.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:e.data})):(t=!0,c.trigger("click"))}))}else t=!0,c.trigger("click")}))}if("product"===e){function c(o,e){e.find(".enable-if-sync-enabled").prop("disabled",!o)}function n(o,e){o?(e.find("option[value='sync_and_show']").show(),e.prop("original")&&e.val(e.prop("original"))):(e.find("option[value='sync_and_show']").hide(),"sync_and_show"===e.val()&&e.val("sync_and_hide"))}function r(o,e){var t=e.find("#wc_facebook_commerce_enabled"),c=t.prop("original");t.prop("checked",!!o&&c).prop("disabled",!o),t.trigger("change"),t.prop("original",c),e.find("#product-not-ready-notice, #variable-product-not-ready-notice").hide(),s()&&!i()?e.find("#variable-product-not-ready-notice").show():o||e.find("#product-not-ready-notice").show()}function a(){return!!(s()?i():"sync_disabled"!==v.val())&&!!(s()||(o("#_regular_price").val()||o("#fb_product_price").val()))&&!(!o("#_manage_stock").prop("checked")||!o("#_stock").val())}function i(){var e=o(".js-variable-fb-sync-toggle");return 0===e.length?!!facebook_for_woocommerce_products_admin.is_sync_enabled_for_product:!!e.map((function(e,t){return"sync_disabled"!==o(t).val()?t:null})).length}function s(){var e=o("select#product-type").val();return!(!e||!e.match(/variable/))}function d(o){o.attr("data-original-value",o.val())}function _(e){return e.map((function(e,t){var c=o(t),n=c.val();return!!facebook_for_woocommerce_products_admin.is_product_published&&"sync_disabled"===n&&n!==c.attr("data-original-value")})).toArray().indexOf(!0)>-1}function l(e){return v===e?o("input#post_ID").val():e.closest(".woocommerce_variation").find("input[name^=variable_post_id]").val()}function u(e){closeExistingModal(),m=e,g=l(e),new o.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:{message:facebook_for_woocommerce_products_admin.product_removed_from_sync_confirm_modal_message,buttons:facebook_for_woocommerce_products_admin.product_removed_from_sync_confirm_modal_buttons}})}function f(){o(facebook_for_woocommerce_products_admin.product_removed_from_sync_field_id).val(b.join(","))}function p(o){b=b.filter((function(e){return e!==o})),f()}var m=null,g=null,b=[];o(document.body).on("click","button.button-product-removed-from-sync-delete",(function(){g&&(closeExistingModal(),b.push(g),f())})).on("click","button.button-product-removed-from-sync-cancel",(function(){var o;closeExistingModal(),m&&((o=m).val(o.attr("data-original-value")),m=null),f()})),o("#facebook_options #wc_facebook_commerce_enabled").on("change",(function(){var e=o(this).prop("checked");e?o(".wc_facebook_commerce_fields").show():o(".wc_facebook_commerce_fields").hide(),o(".product_attributes").find(".woocommerce_attribute").length?o(".show_if_has_attributes").show():o(".show_if_has_attributes").hide(),o(this).prop("original",e)})).trigger("change");var v=o("#wc_facebook_sync_mode"),h=v.closest(".woocommerce_options_panel");d(v),v.on("change",(function(){var o,e,t="sync_disabled"!==v.val();c(t,h),o=t,e=h.find(".wc-facebook-commerce-options-group"),o?e.show():e.hide(),t&&p(l(v)),v.prop("original",v.val()),_(v)&&u(v)})).trigger("change"),o("#_virtual").on("change",(function(){n(!o(this).prop("checked"),v)})).trigger("change");var w=o("#woocommerce-product-data");w.on("change","#_regular_price, #_manage_stock, #_stock, #wc_facebook_sync_mode, #fb_product_price",(function(e){setTimeout((function(){r(a(),o("#facebook_options"))}),1)})),o(".woocommerce_variations").on("change",".js-variable-fb-sync-toggle",(function(){var e=o(this),t="sync_disabled"!==e.val();c(t,e.closest(".wc-metabox-content")),r(a(),o("#facebook_options")),t&&p(l(e)),e.prop("original",e.val()),_(e)&&u(e)})),w.on("woocommerce_variations_loaded",(function(){w.find(".js-variable-fb-sync-toggle").each((function(e,t){var n=o(t);c("sync_disabled"!==n.val(),n.closest(".wc-metabox-content")),n.prop("original",n.val()),d(n)})),o(".variable_is_virtual").on("change",(function(){var e=o(this).closest(".wc-metabox-content").find(".js-variable-fb-sync-toggle");n(!o(this).prop("checked"),e)})),r(a(),o("#facebook_options"))})),w.on("change",".js-fb-product-image-source",(function(){var e=o(this).closest(".woocommerce_options_panel, .wc-metabox-content"),t=o(this).val();e.find(".product-image-source-field").closest(".form-field").hide(),e.find(".show-if-product-image-source-".concat(t)).closest(".form-field").show()})),o(".js-fb-product-image-source:checked:visible").trigger("change"),w.on("woocommerce_variations_loaded",(function(){o(".js-variable-fb-sync-toggle:visible").trigger("change"),o(".js-fb-product-image-source:checked:visible").trigger("change"),o(".variable_is_virtual:visible").trigger("change")})),o("#facebook_options").on("click","#product-not-ready-notice-open-modal",(function(e){e.preventDefault(),closeExistingModal(),new o.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:{message:facebook_for_woocommerce_products_admin.product_not_ready_modal_message,buttons:facebook_for_woocommerce_products_admin.product_not_ready_modal_buttons}})})),r(a(),h);var k=!1;o('form#post input[type="submit"]').on("click",(function(e){if(o("#wc_facebook_commerce_enabled").prop("checked")&&a()&&o(".wc_facebook_commerce_fields .wc-facebook-google-product-category-select").map((function(e,t){return o(t).val()?o(t).val():null})).length<2)return e.preventDefault(),alert(facebook_for_woocommerce_products_admin.i18n.missing_google_product_category_message),!1;if(k)return!0;e.preventDefault();var t=o(this),c=parseInt(o("input#post_ID").val(),10),n=[],r=o('textarea[name="tax_input[product_tag]"]').length?o('textarea[name="tax_input[product_tag]"]').val().split(","):[],s="sync_disabled"!==v.val(),d=i();o('#taxonomy-product_cat input[name="tax_input[product_cat][]"]:checked').each((function(){n.push(parseInt(o(this).val(),10))})),o('#taxonomy-product_tag input[name="tax_input[product_tag][]"]:checked').each((function(){r.push(parseInt(o(this).val(),10))})),c>0?o.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:s?"enabled":"disabled",var_sync_enabled:d?"enabled":"disabled",product:c,categories:n,tags:r},(function(e){e&&!e.success&&s?(closeExistingModal(),new o.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:e.data})):(k=!0,t.trigger("click"))})):(k=!0,t.trigger("click"))}))}}))}});
1
+ !function(o){var e={};function t(c){if(e[c])return e[c].exports;var n=e[c]={i:c,l:!1,exports:{}};return o[c].call(n.exports,n,n.exports,t),n.l=!0,n.exports}t.m=o,t.c=e,t.d=function(o,e,c){t.o(o,e)||Object.defineProperty(o,e,{enumerable:!0,get:c})},t.r=function(o){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(o,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(o,"__esModule",{value:!0})},t.t=function(o,e){if(1&e&&(o=t(o)),8&e)return o;if(4&e&&"object"==typeof o&&o&&o.__esModule)return o;var c=Object.create(null);if(t.r(c),Object.defineProperty(c,"default",{enumerable:!0,value:o}),2&e&&"string"!=typeof o)for(var n in o)t.d(c,n,function(e){return o[e]}.bind(null,n));return c},t.n=function(o){var e=o&&o.__esModule?function(){return o.default}:function(){return o};return t.d(e,"a",e),e},t.o=function(o,e){return Object.prototype.hasOwnProperty.call(o,e)},t.p="",t(t.s=9)}({9:function(o,e){jQuery(document).ready((function(o){var e=window.pagenow.length?window.pagenow:"";if(window.typenow.length&&window.typenow,"edit-product"===e){var t=!1;o("input#doaction, input#doaction2").on("click",(function(e){if(t)return!0;e.preventDefault();var c=o(this),n=c.prev("select").val();if("facebook_include"===n){var r=[];o.each(o('input[name="post[]"]:checked'),(function(){r.push(parseInt(o(this).val(),10))})),o.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:n,products:r},(function(e){e&&!e.success?(closeExistingModal(),new o.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:e.data})):(t=!0,c.trigger("click"))}))}else t=!0,c.trigger("click")}))}if("product"===e){function c(o,e){e.find(".enable-if-sync-enabled").prop("disabled",!o)}function n(o,e){o?(e.find("option[value='sync_and_show']").show(),e.prop("original")&&e.val(e.prop("original"))):(e.find("option[value='sync_and_show']").hide(),"sync_and_show"===e.val()&&e.val("sync_and_hide"))}function r(o,e){var t=e.find("#wc_facebook_commerce_enabled"),c=t.prop("original");t.prop("checked",!!o&&c).prop("disabled",!o),t.trigger("change"),t.prop("original",c),e.find("#product-not-ready-notice, #variable-product-not-ready-notice").hide(),s()&&!i()?e.find("#variable-product-not-ready-notice").show():o||e.find("#product-not-ready-notice").show()}function a(){return!!(s()?i():"sync_disabled"!==v.val())&&!!(s()||(o("#_regular_price").val()||o("#fb_product_price").val()))&&!(!o("#_manage_stock").prop("checked")||!o("#_stock").val())}function i(){var e=o(".js-variable-fb-sync-toggle");return 0===e.length?!!facebook_for_woocommerce_products_admin.is_sync_enabled_for_product:!!e.map((function(e,t){return"sync_disabled"!==o(t).val()?t:null})).length}function s(){var e=o("select#product-type").val();return!(!e||!e.match(/variable/))}function d(o){o.attr("data-original-value",o.val())}function _(e){return e.map((function(e,t){var c=o(t),n=c.val();return!!facebook_for_woocommerce_products_admin.is_product_published&&"sync_disabled"===n&&n!==c.attr("data-original-value")})).toArray().indexOf(!0)>-1}function l(e){return v===e?o("input#post_ID").val():e.closest(".woocommerce_variation").find("input[name^=variable_post_id]").val()}function u(e){closeExistingModal(),m=e,g=l(e),new o.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:{message:facebook_for_woocommerce_products_admin.product_removed_from_sync_confirm_modal_message,buttons:facebook_for_woocommerce_products_admin.product_removed_from_sync_confirm_modal_buttons}})}function f(){o(facebook_for_woocommerce_products_admin.product_removed_from_sync_field_id).val(b.join(","))}function p(o){b=b.filter((function(e){return e!==o})),f()}var m=null,g=null,b=[];o(document.body).on("click","button.button-product-removed-from-sync-delete",(function(){g&&(closeExistingModal(),b.push(g),f())})).on("click","button.button-product-removed-from-sync-cancel",(function(){var o;closeExistingModal(),m&&((o=m).val(o.attr("data-original-value")),m=null),f()})),o("#facebook_options #wc_facebook_commerce_enabled").on("change",(function(){var e=o(this).prop("checked");e?o(".wc_facebook_commerce_fields").show():o(".wc_facebook_commerce_fields").hide(),o(".product_attributes").find(".woocommerce_attribute").length?o(".show_if_has_attributes").show():o(".show_if_has_attributes").hide(),o(this).prop("original",e)})).trigger("change");var v=o("#wc_facebook_sync_mode"),h=v.closest(".woocommerce_options_panel");d(v),v.on("change",(function(){var o,e,t="sync_disabled"!==v.val();c(t,h),o=t,e=h.find(".wc-facebook-commerce-options-group"),o?e.show():e.hide(),t&&p(l(v)),v.prop("original",v.val()),_(v)&&u(v)})).trigger("change"),o("#_virtual").on("change",(function(){n(!o(this).prop("checked"),v)})).trigger("change");var w=o("#woocommerce-product-data");w.on("change","#_regular_price, #_manage_stock, #_stock, #wc_facebook_sync_mode, #fb_product_price",(function(e){setTimeout((function(){r(a(),o("#facebook_options"))}),1)})),o(".woocommerce_variations").on("change",".js-variable-fb-sync-toggle",(function(){var e=o(this),t="sync_disabled"!==e.val();c(t,e.closest(".wc-metabox-content")),r(a(),o("#facebook_options")),t&&p(l(e)),e.prop("original",e.val()),_(e)&&u(e)})),w.on("woocommerce_variations_loaded",(function(){w.find(".js-variable-fb-sync-toggle").each((function(e,t){var n=o(t);c("sync_disabled"!==n.val(),n.closest(".wc-metabox-content")),n.prop("original",n.val()),d(n)})),o(".variable_is_virtual").on("change",(function(){var e=o(this).closest(".wc-metabox-content").find(".js-variable-fb-sync-toggle");n(!o(this).prop("checked"),e)})),r(a(),o("#facebook_options"))})),w.on("change",".js-fb-product-image-source",(function(){var e=o(this).closest(".woocommerce_options_panel, .wc-metabox-content"),t=o(this).val();e.find(".product-image-source-field").closest(".form-field").hide(),e.find(".show-if-product-image-source-".concat(t)).closest(".form-field").show()})),o(".js-fb-product-image-source:checked:visible").trigger("change"),w.on("woocommerce_variations_loaded",(function(){o(".js-variable-fb-sync-toggle:visible").trigger("change"),o(".js-fb-product-image-source:checked:visible").trigger("change"),o(".variable_is_virtual:visible").trigger("change")})),o("#facebook_options").on("click","#product-not-ready-notice-open-modal",(function(e){e.preventDefault(),closeExistingModal(),new o.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:{message:facebook_for_woocommerce_products_admin.product_not_ready_modal_message,buttons:facebook_for_woocommerce_products_admin.product_not_ready_modal_buttons}})})),r(a(),h);var k=!1;o('form#post input[type="submit"]').on("click",(function(e){if(o("#wc_facebook_commerce_enabled").prop("checked")&&a()&&o(".wc_facebook_commerce_fields .wc-facebook-google-product-category-select").map((function(e,t){return o(t).val()?o(t).val():null})).length<2)return e.preventDefault(),alert(facebook_for_woocommerce_products_admin.i18n.missing_google_product_category_message),!1;if(k)return!0;e.preventDefault();var t=o(this),c=parseInt(o("input#post_ID").val(),10),n=[],r=o('textarea[name="tax_input[product_tag]"]').length?o('textarea[name="tax_input[product_tag]"]').val().split(","):[],s="sync_disabled"!==v.val(),d=i();o('#taxonomy-product_cat input[name="tax_input[product_cat][]"]:checked').each((function(){n.push(parseInt(o(this).val(),10))})),o('#taxonomy-product_tag input[name="tax_input[product_tag][]"]:checked').each((function(){r.push(parseInt(o(this).val(),10))})),c>0?o.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:s?"enabled":"disabled",var_sync_enabled:d?"enabled":"disabled",product:c,categories:n,tags:r},(function(e){e&&!e.success&&s?(closeExistingModal(),new o.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:e.data})):(k=!0,t.trigger("click"))})):(k=!0,t.trigger("click"))}))}}))}});
assets/build/admin/settings-commerce.asset.php CHANGED
@@ -1 +1 @@
1
- <?php return array('dependencies' => array('wp-polyfill'), 'version' => '9513715b2a35d2eda9c958baf192798e');
1
+ <?php return array('dependencies' => array('wp-polyfill'), 'version' => 'acc6b39098af038366628ba127647abe');
assets/build/admin/settings-commerce.js CHANGED
@@ -1 +1 @@
1
- !function(e){var o={};function t(r){if(o[r])return o[r].exports;var c=o[r]={i:r,l:!1,exports:{}};return e[r].call(c.exports,c,c.exports,t),c.l=!0,c.exports}t.m=e,t.c=o,t.d=function(e,o,r){t.o(e,o)||Object.defineProperty(e,o,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,o){if(1&o&&(e=t(e)),8&o)return e;if(4&o&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&o&&"string"!=typeof e)for(var c in e)t.d(r,c,function(o){return e[o]}.bind(null,c));return r},t.n=function(e){var o=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(o,"a",o),o},t.o=function(e,o){return Object.prototype.hasOwnProperty.call(e,o)},t.p="",t(t.s=11)}({11:function(e,o){jQuery(document).ready((function(e){var o=e("form.wc-facebook-settings"),t=e("#wc_facebook_google_product_category_id"),r=t.val();o.on("submit",(function(c){o.data("allow-submit")||t.val()===r||(c.preventDefault(),e("#wc-backbone-modal-dialog .modal-close").trigger("click"),new e.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:{message:t.val()?facebook_for_woocommerce_settings_commerce.default_google_product_category_modal_message:facebook_for_woocommerce_settings_commerce.default_google_product_category_modal_message_empty,buttons:facebook_for_woocommerce_settings_commerce.default_google_product_category_modal_buttons}}),e(document.body).off("wc_backbone_modal_response.facebook_for_commerce").on("wc_backbone_modal_response.facebook_for_commerce",(function(){o.data("allow-submit",!0).find(":submit").trigger("click")})))})),e(".woocommerce-help-tip").tipTip({attribute:"data-tip",fadeIn:50,fadeOut:50,delay:200})}))}});
1
+ !function(e){var o={};function t(r){if(o[r])return o[r].exports;var c=o[r]={i:r,l:!1,exports:{}};return e[r].call(c.exports,c,c.exports,t),c.l=!0,c.exports}t.m=e,t.c=o,t.d=function(e,o,r){t.o(e,o)||Object.defineProperty(e,o,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,o){if(1&o&&(e=t(e)),8&o)return e;if(4&o&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&o&&"string"!=typeof e)for(var c in e)t.d(r,c,function(o){return e[o]}.bind(null,c));return r},t.n=function(e){var o=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(o,"a",o),o},t.o=function(e,o){return Object.prototype.hasOwnProperty.call(e,o)},t.p="",t(t.s=10)}({10:function(e,o){jQuery(document).ready((function(e){var o=e("form.wc-facebook-settings"),t=e("#wc_facebook_google_product_category_id"),r=t.val();o.on("submit",(function(c){o.data("allow-submit")||t.val()===r||(c.preventDefault(),e("#wc-backbone-modal-dialog .modal-close").trigger("click"),new e.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:{message:t.val()?facebook_for_woocommerce_settings_commerce.default_google_product_category_modal_message:facebook_for_woocommerce_settings_commerce.default_google_product_category_modal_message_empty,buttons:facebook_for_woocommerce_settings_commerce.default_google_product_category_modal_buttons}}),e(document.body).off("wc_backbone_modal_response.facebook_for_commerce").on("wc_backbone_modal_response.facebook_for_commerce",(function(){o.data("allow-submit",!0).find(":submit").trigger("click")})))})),e(".woocommerce-help-tip").tipTip({attribute:"data-tip",fadeIn:50,fadeOut:50,delay:200})}))}});
assets/build/admin/settings-sync.asset.php CHANGED
@@ -1 +1 @@
1
- <?php return array('dependencies' => array('wp-polyfill'), 'version' => 'ca852c21b4cd9d57cc0fce8606957fc3');
1
+ <?php return array('dependencies' => array('wp-polyfill'), 'version' => '09bea6d8423a8a58d4d75974f1745c5c');
assets/build/admin/settings-sync.js CHANGED
@@ -1 +1 @@
1
- !function(e){var o={};function c(n){if(o[n])return o[n].exports;var t=o[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,c),t.l=!0,t.exports}c.m=e,c.c=o,c.d=function(e,o,n){c.o(e,o)||Object.defineProperty(e,o,{enumerable:!0,get:n})},c.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},c.t=function(e,o){if(1&o&&(e=c(e)),8&o)return e;if(4&o&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(c.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&o&&"string"!=typeof e)for(var t in e)c.d(n,t,function(o){return e[o]}.bind(null,t));return n},c.n=function(e){var o=e&&e.__esModule?function(){return e.default}:function(){return e};return c.d(o,"a",o),o},c.o=function(e,o){return Object.prototype.hasOwnProperty.call(e,o)},c.p="",c(c.s=12)}({12:function(e,o){jQuery(document).ready((function(e){function o(o){e(".product-sync-field").each((function(){var c=e(this);e(this).hasClass("wc-enhanced-select")&&(c=e(this).next("span.select2-container")),o?c.css("pointer-events","all").css("opacity","1.0"):c.css("pointer-events","none").css("opacity","0.4")}))}e(".woocommerce-help-tip").tipTip({attribute:"data-tip",fadeIn:50,fadeOut:50,delay:200}),e("form.wc-facebook-settings").hasClass("disconnected")&&o(!1),e("input#wc_facebook_enable_product_sync").on("change",(function(c){e("form.wc-facebook-settings").hasClass("disconnected")?e(this).css("pointer-events","none").css("opacity","0.4"):o(e(this).is(":checked"))})).trigger("change");var c=!1;function n(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;t(e),window.syncStatusInterval||(window.syncStatusInterval=setInterval(r,1e4))}function t(){var c=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;o(!1),e('input#wc_facebook_enable_product_sync, input[name="save_product_sync_settings"]').css("pointer-events","none").css("opacity","0.4");var n=facebook_for_woocommerce_settings_sync.i18n.sync_in_progress;c&&(n=(n+=c>1?facebook_for_woocommerce_settings_sync.i18n.sync_remaining_items_plural:facebook_for_woocommerce_settings_sync.i18n.sync_remaining_items_singular).replace("{count}",c)),e("#sync_progress").show().html(n).css("color","inherit"),facebook_for_woocommerce_settings_sync.sync_in_progress=!0}function s(){var c=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";facebook_for_woocommerce_settings_sync.sync_in_progress=!1,clearInterval(window.syncStatusInterval),window.syncStatusInterval=null,o(!0),e('input#wc_facebook_enable_product_sync, input[name="save_product_sync_settings"]').css("pointer-events","all").css("opacity","1"),c?e("#sync_progress").show().html(c).css("color","#DC3232"):e("#sync_progress").hide()}function r(){facebook_for_woocommerce_settings_sync.sync_in_progress&&e.post(facebook_for_woocommerce_settings_sync.ajax_url,{action:"wc_facebook_get_sync_status",nonce:facebook_for_woocommerce_settings_sync.sync_status_nonce},(function(e){console.log(e),e.success&&(e.data>0?n(e.data):s())}))}e('input[name="save_product_sync_settings"]').on("click",(function(o){if(c)return!0;o.preventDefault();var n,t,s,r,_=e(this),i=(s=e("#wc_facebook_excluded_product_category_ids").val(),r=[],window.facebook_for_woocommerce_settings_sync&&window.facebook_for_woocommerce_settings_sync.excluded_category_ids&&(r=window.facebook_for_woocommerce_settings_sync.excluded_category_ids),e(s).not(r).get()),a=(n=e("#wc_facebook_excluded_product_tag_ids").val(),t=[],window.facebook_for_woocommerce_settings_sync&&window.facebook_for_woocommerce_settings_sync.excluded_tag_ids&&(t=window.facebook_for_woocommerce_settings_sync.excluded_tag_ids),e(n).not(t).get());i.length>0||a.length>0?e.post(facebook_for_woocommerce_settings_sync.ajax_url,{action:"facebook_for_woocommerce_set_excluded_terms_prompt",security:facebook_for_woocommerce_settings_sync.set_excluded_terms_prompt_nonce,categories:i,tags:a},(function(o){o&&!o.success?(e("#wc-backbone-modal-dialog .modal-close").trigger("click"),new e.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:o.data}),e(".facebook-for-woocommerce-confirm-settings-change").on("click",(function(){blockModal(),c=!0,_.trigger("click")}))):(c=!0,_.trigger("click"))})):(c=!0,_.trigger("click"))})),facebook_for_woocommerce_settings_sync.sync_in_progress&&n(),e("#woocommerce-facebook-settings-sync-products").click((function(o){if(o.preventDefault(),confirm(facebook_for_woocommerce_settings_sync.i18n.confirm_sync)){t();var c=Date.now();e.post(facebook_for_woocommerce_settings_sync.ajax_url,{action:"wc_facebook_sync_products",nonce:facebook_for_woocommerce_settings_sync.sync_products_nonce},(function(e){if(console.log(e),e.success)setTimeout(r,Math.max(0,1e4-(Date.now()-c)));else{var o=facebook_for_woocommerce_settings_sync.i18n.general_error;e.data&&e.data.length>0&&(o=e.data),s(o)}})).fail((function(){s(facebook_for_woocommerce_settings_sync.i18n.general_error)}))}}))}))}});
1
+ !function(e){var o={};function c(n){if(o[n])return o[n].exports;var t=o[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,c),t.l=!0,t.exports}c.m=e,c.c=o,c.d=function(e,o,n){c.o(e,o)||Object.defineProperty(e,o,{enumerable:!0,get:n})},c.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},c.t=function(e,o){if(1&o&&(e=c(e)),8&o)return e;if(4&o&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(c.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&o&&"string"!=typeof e)for(var t in e)c.d(n,t,function(o){return e[o]}.bind(null,t));return n},c.n=function(e){var o=e&&e.__esModule?function(){return e.default}:function(){return e};return c.d(o,"a",o),o},c.o=function(e,o){return Object.prototype.hasOwnProperty.call(e,o)},c.p="",c(c.s=11)}({11:function(e,o){jQuery(document).ready((function(e){function o(o){e(".product-sync-field").each((function(){var c=e(this);e(this).hasClass("wc-enhanced-select")&&(c=e(this).next("span.select2-container")),o?c.css("pointer-events","all").css("opacity","1.0"):c.css("pointer-events","none").css("opacity","0.4")}))}e(".woocommerce-help-tip").tipTip({attribute:"data-tip",fadeIn:50,fadeOut:50,delay:200}),e("form.wc-facebook-settings").hasClass("disconnected")&&o(!1),e("input#wc_facebook_enable_product_sync").on("change",(function(c){e("form.wc-facebook-settings").hasClass("disconnected")?e(this).css("pointer-events","none").css("opacity","0.4"):o(e(this).is(":checked"))})).trigger("change");var c=!1;function n(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;t(e),window.syncStatusInterval||(window.syncStatusInterval=setInterval(r,1e4))}function t(){var c=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;o(!1),e('input#wc_facebook_enable_product_sync, input[name="save_product_sync_settings"]').css("pointer-events","none").css("opacity","0.4");var n=facebook_for_woocommerce_settings_sync.i18n.sync_in_progress;c&&(n=(n+=c>1?facebook_for_woocommerce_settings_sync.i18n.sync_remaining_items_plural:facebook_for_woocommerce_settings_sync.i18n.sync_remaining_items_singular).replace("{count}",c)),e("#sync_progress").show().html(n).css("color","inherit"),facebook_for_woocommerce_settings_sync.sync_in_progress=!0}function s(){var c=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";facebook_for_woocommerce_settings_sync.sync_in_progress=!1,clearInterval(window.syncStatusInterval),window.syncStatusInterval=null,o(!0),e('input#wc_facebook_enable_product_sync, input[name="save_product_sync_settings"]').css("pointer-events","all").css("opacity","1"),c?e("#sync_progress").show().html(c).css("color","#DC3232"):e("#sync_progress").hide()}function r(){facebook_for_woocommerce_settings_sync.sync_in_progress&&e.post(facebook_for_woocommerce_settings_sync.ajax_url,{action:"wc_facebook_get_sync_status",nonce:facebook_for_woocommerce_settings_sync.sync_status_nonce},(function(e){console.log(e),e.success&&(e.data>0?n(e.data):s())}))}e('input[name="save_product_sync_settings"]').on("click",(function(o){if(c)return!0;o.preventDefault();var n,t,s,r,_=e(this),i=(s=e("#wc_facebook_excluded_product_category_ids").val(),r=[],window.facebook_for_woocommerce_settings_sync&&window.facebook_for_woocommerce_settings_sync.excluded_category_ids&&(r=window.facebook_for_woocommerce_settings_sync.excluded_category_ids),e(s).not(r).get()),a=(n=e("#wc_facebook_excluded_product_tag_ids").val(),t=[],window.facebook_for_woocommerce_settings_sync&&window.facebook_for_woocommerce_settings_sync.excluded_tag_ids&&(t=window.facebook_for_woocommerce_settings_sync.excluded_tag_ids),e(n).not(t).get());i.length>0||a.length>0?e.post(facebook_for_woocommerce_settings_sync.ajax_url,{action:"facebook_for_woocommerce_set_excluded_terms_prompt",security:facebook_for_woocommerce_settings_sync.set_excluded_terms_prompt_nonce,categories:i,tags:a},(function(o){o&&!o.success?(e("#wc-backbone-modal-dialog .modal-close").trigger("click"),new e.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:o.data}),e(".facebook-for-woocommerce-confirm-settings-change").on("click",(function(){blockModal(),c=!0,_.trigger("click")}))):(c=!0,_.trigger("click"))})):(c=!0,_.trigger("click"))})),facebook_for_woocommerce_settings_sync.sync_in_progress&&n(),e("#woocommerce-facebook-settings-sync-products").click((function(o){if(o.preventDefault(),confirm(facebook_for_woocommerce_settings_sync.i18n.confirm_sync)){t();var c=Date.now();e.post(facebook_for_woocommerce_settings_sync.ajax_url,{action:"wc_facebook_sync_products",nonce:facebook_for_woocommerce_settings_sync.sync_products_nonce},(function(e){if(console.log(e),e.success)setTimeout(r,Math.max(0,1e4-(Date.now()-c)));else{var o=facebook_for_woocommerce_settings_sync.i18n.general_error;e.data&&e.data.length>0&&(o=e.data),s(o)}})).fail((function(){s(facebook_for_woocommerce_settings_sync.i18n.general_error)}))}}))}))}});
assets/js/admin/orders.js DELETED
@@ -1,541 +0,0 @@
1
- /**
2
- * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
3
- *
4
- * This source code is licensed under the license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @package FacebookCommerce
8
- */
9
-
10
- jQuery( document ).ready( ( $ ) => {
11
-
12
- 'use strict';
13
-
14
- const isCommerceOrder = Boolean( wc_facebook_commerce_orders.is_commerce_order );
15
-
16
- const commerceOrderOperations = {
17
- /**
18
- * Restrict order status options to only allowed options.
19
- *
20
- * @param {Object} $orderStatus Order select jQuery DOM object
21
- */
22
- restrict_order_statuses: $orderStatus => {
23
-
24
- $orderStatus.find( 'option' ).each( function ( index, option ) {
25
-
26
- // check if option value in the allowed list or not
27
- if ( wc_facebook_commerce_orders.allowed_commerce_statuses.indexOf( option.value ) === -1 ) {
28
- // delete/remove option if not allowed
29
- option.remove();
30
- }
31
- } );
32
- },
33
-
34
-
35
- /**
36
- * Enable or Disable order created fields.
37
- *
38
- * @param {Boolean} enable whether to enable date fields (true) or not (false)
39
- */
40
- toggle_created_date_fields_status: enable => {
41
-
42
- commerceOrderOperations.toggle_field( $( '#order_data' ).find( 'input[name*=order_date]' ), enable );
43
- },
44
-
45
-
46
- /**
47
- * Disable order status field
48
- *
49
- * @param {Object} $orderStatus Order select jQuery DOM object
50
- */
51
- disable_order_status_field: ( $orderStatus ) => {
52
-
53
- commerceOrderOperations.toggle_field( $orderStatus, false );
54
- },
55
-
56
-
57
- /**
58
- * Toggle customer field
59
- *
60
- * @param {Boolean} hide
61
- */
62
- toggle_order_customer_field: ( hide ) => {
63
- $( '#order_data' ).find( '.form-field.wc-customer-user' ).toggleClass( 'hidden', hide );
64
- },
65
-
66
-
67
- /**
68
- * Toggle customer field
69
- *
70
- * @param {Boolean} hide
71
- */
72
- toggle_billing_and_shipping_fields: ( hide ) => {
73
- $( '#order_data' ).find( 'a.edit_address' ).toggleClass( 'hidden', hide );
74
- },
75
-
76
-
77
- /**
78
- * Disable and hide related fields based on commerce order pending status
79
- *
80
- * @param {Object} $orderStatus Order select jQuery DOM object
81
- */
82
- disable_pending_order_related_fields: ( $orderStatus ) => {
83
-
84
- commerceOrderOperations.toggle_created_date_fields_status( false );
85
- commerceOrderOperations.disable_order_status_field( $orderStatus );
86
- commerceOrderOperations.toggle_order_customer_field( true );
87
- commerceOrderOperations.toggle_billing_and_shipping_fields( true );
88
- },
89
-
90
-
91
- /**
92
- * Hide the refund UI when refunds can't be performed.
93
- */
94
- maybe_disable_refunds: () => {
95
-
96
- // only completed (fulfilled) orders can be refunded
97
- if ( 'completed' !== wc_facebook_commerce_orders.order_status ) {
98
- $( '.wc-order-bulk-actions .refund-items' ).hide();
99
- }
100
- },
101
-
102
-
103
- /**
104
- * Uses CSS to enable/disable a form field.
105
- *
106
- * This function was copied from toggleSettingOptions() in facebook-for-woocommerce-settings-sync.js
107
- *
108
- * @since 2.1.0
109
- *
110
- * @param {jQuery} $element the form field
111
- * @param {boolean} enable whether to enable or disable the field
112
- */
113
- toggle_field: ( $element, enable ) => {
114
-
115
- if ( $element.hasClass( 'wc-enhanced-select' ) ) {
116
- $element = $element.next( 'span.select2-container' );
117
- }
118
-
119
- if ( enable ) {
120
- $element.css( 'pointer-events', 'all' ).css( 'opacity', '1.0' );
121
- } else {
122
- $element.css( 'pointer-events', 'none' ).css( 'opacity', '0.4' );
123
- }
124
- }
125
-
126
-
127
- };
128
-
129
- let $form = $( 'form[id="post"]' );
130
- let $orderStatusField = $( '#order_status' );
131
- let originalOrderStatus = $orderStatusField.val();
132
- let shipmentTracking = wc_facebook_commerce_orders.shipment_tracking;
133
- let existingTrackingNumber = '';
134
- let existingCarrierCode = '';
135
- let completeModalTrackingNumber = '';
136
- let completeModalCarrierCode = '';
137
-
138
- if ( Array.isArray( shipmentTracking ) && shipmentTracking[0] ) {
139
- existingTrackingNumber = shipmentTracking[0].tracking_number;
140
- existingCarrierCode = shipmentTracking[0].carrier_code;
141
- }
142
-
143
- if ( isCommerceOrder ) {
144
-
145
- commerceOrderOperations.restrict_order_statuses( $orderStatusField );
146
-
147
- if ( 'pending' === wc_facebook_commerce_orders.order_status ) {
148
- commerceOrderOperations.disable_pending_order_related_fields( $orderStatusField );
149
- }
150
-
151
- if ( 'cancelled' === wc_facebook_commerce_orders.order_status ) {
152
- commerceOrderOperations.disable_order_status_field( $orderStatusField );
153
- }
154
-
155
- commerceOrderOperations.maybe_disable_refunds();
156
- }
157
-
158
-
159
- /**
160
- * Determines whether we need to show the Cancel Order modal.
161
- *
162
- * @since 2.0.1-dev.1
163
- *
164
- * @returns {boolean}
165
- */
166
- function shouldShowCancelOrderModal() {
167
-
168
- if ( $( '#post' ).data( 'skip-cancel-modal' ) ) {
169
- return false;
170
- }
171
-
172
- if ( 'wc-cancelled' === originalOrderStatus ) {
173
- return false;
174
- }
175
-
176
- if ( ! isCommerceOrder ) {
177
- return false;
178
- }
179
-
180
- return 'wc-cancelled' === $orderStatusField.val();
181
- }
182
-
183
-
184
- /**
185
- * Shows and listens for events on the Cancel Order modal.
186
- *
187
- * @since 2.0.1-dev.1
188
- *
189
- * @param {jQuery.Event} event a submit event instance
190
- */
191
- function showCancelOrderModal( event ) {
192
-
193
- event.preventDefault();
194
-
195
- // close existing modals
196
- $( '#wc-backbone-modal-dialog .modal-close' ).trigger( 'click' );
197
-
198
- new $.WCBackboneModal.View( {
199
- target: 'facebook-for-woocommerce-modal',
200
- string: {
201
- message: wc_facebook_commerce_orders.cancel_modal_message,
202
- buttons: wc_facebook_commerce_orders.cancel_modal_buttons
203
- }
204
- } );
205
-
206
- // handle confirm action
207
- $( '.facebook-for-woocommerce-modal #btn-ok' )
208
- .off( 'click.facebook_for_commerce' )
209
- .on( 'click.facebook_for_commerce', ( event ) => {
210
-
211
- event.preventDefault();
212
- event.stopPropagation();
213
-
214
- blockModal();
215
-
216
- $.post( ajaxurl, {
217
- action: wc_facebook_commerce_orders.cancel_order_action,
218
- order_id: $( '#post_ID' ).val(),
219
- reason_code: $( '.facebook-for-woocommerce-modal [name="wc_facebook_cancel_reason"]' ).val(),
220
- security: wc_facebook_commerce_orders.cancel_order_nonce
221
- }, ( response ) => {
222
-
223
- if ( ! response || ! response.success ) {
224
- showErrorInModal( response && response.data ? response.data : wc_facebook_commerce_orders.i18n.unknown_error );
225
- return;
226
- }
227
-
228
- $( '#post' ).data( 'skip-cancel-modal', true ).trigger( 'submit' );
229
- } ).fail( () => {
230
-
231
- showErrorInModal( wc_facebook_commerce_orders.i18n.unknown_error );
232
- } );
233
- } );
234
-
235
- return false;
236
- }
237
-
238
-
239
- /**
240
- * Replaces the content of the active Facebook for WooCommerce modal to show the given error.
241
- *
242
- * @since 2.0.1-dev.1
243
- *
244
- * @param {string} error
245
- */
246
- function showErrorInModal( error ) {
247
-
248
- unBlockModal();
249
-
250
- $( '.facebook-for-woocommerce-modal .wc-backbone-modal-content article' ).html( '<p>' + error + '</p>' );
251
- $( '.facebook-for-woocommerce-modal .wc-backbone-modal-content footer' ).remove();
252
- }
253
-
254
-
255
- /**
256
- * Displays the refund modal on form submit.
257
- *
258
- * @since 2.0.1-dev.1
259
- *
260
- * @param {Event} event
261
- */
262
- function displayRefundModal( event ) {
263
-
264
- event.preventDefault();
265
-
266
- $( '#wc-backbone-modal-dialog .modal-close' ).trigger( 'click' );
267
-
268
-
269
- new $.WCBackboneModal.View( {
270
- target: 'facebook-for-woocommerce-modal',
271
- string: {
272
- message: wc_facebook_commerce_orders.refund_modal_message,
273
- buttons: wc_facebook_commerce_orders.refund_modal_buttons
274
- }
275
- } );
276
-
277
- $( document.body )
278
- .off( 'wc_backbone_modal_response.facebook_for_commerce' )
279
- .on( 'wc_backbone_modal_response.facebook_for_commerce', function() {
280
- // copy the value of the modal select to the WC field
281
- $( '#refund_reason' ).val( $( '#wc_facebook_refund_reason_modal' ).val() );
282
- // submit the form
283
- $form.data( 'allow-submit', true ).submit();
284
- } );
285
- }
286
-
287
-
288
- /**
289
- * Displays the order complete modal on order form submit
290
- */
291
- function displayCompleteModal() {
292
-
293
- $( '#wc-backbone-modal-dialog .modal-close' ).trigger( 'click' );
294
-
295
- if ( completeModalCarrierCode || completeModalTrackingNumber ) {
296
- $( document.body )
297
- .off( 'wc_backbone_modal_loaded' )
298
- .on( 'wc_backbone_modal_loaded', function() {
299
-
300
- if ( completeModalCarrierCode ) {
301
- $( '#wc_facebook_carrier' ).val( completeModalCarrierCode );
302
- }
303
-
304
- if ( completeModalTrackingNumber ) {
305
- $( '#wc_facebook_tracking_number' ).val( completeModalTrackingNumber );
306
- }
307
- } );
308
- }
309
-
310
- new $.WCBackboneModal.View( {
311
- target: 'facebook-for-woocommerce-modal',
312
- string: {
313
- message: wc_facebook_commerce_orders.complete_modal_message,
314
- buttons: wc_facebook_commerce_orders.complete_modal_buttons
315
- }
316
- } );
317
-
318
- // handle confirm action
319
- $( '.facebook-for-woocommerce-modal #btn-ok' )
320
- .off( 'click.facebook_for_commerce' )
321
- .on( 'click.facebook_for_commerce', ( event ) => {
322
-
323
- event.preventDefault();
324
- event.stopPropagation();
325
-
326
- completeModalCarrierCode = $( '#wc_facebook_carrier' ).val();
327
- completeModalTrackingNumber = $( '#wc_facebook_tracking_number' ).val();
328
-
329
- makeCompleteAjaxRequest( true, completeModalTrackingNumber, completeModalCarrierCode );
330
- } );
331
- }
332
-
333
-
334
- /**
335
- * Make complete order AJAX Request
336
- *
337
- * @param {Boolean} withModal
338
- * @param {String} trackingNumber
339
- * @param {String} carrierCode
340
- */
341
- function makeCompleteAjaxRequest( withModal = false, trackingNumber = null, carrierCode = null ) {
342
-
343
- if ( ! trackingNumber.length ) {
344
-
345
- alert( wc_facebook_commerce_orders.i18n.missing_tracking_number_error );
346
-
347
- return false;
348
- }
349
-
350
- if ( withModal ) {
351
- blockModal();
352
- }
353
-
354
- $form.find( 'button[type=submit].save_order' ).prop( 'disabled', true ).append( '<span class="spinner is-active"></span>' );
355
-
356
- $.post( ajaxurl, {
357
- action : wc_facebook_commerce_orders.complete_order_action,
358
- order_id : $( '#post_ID' ).val(),
359
- tracking_number: trackingNumber,
360
- carrier_code : carrierCode,
361
- nonce : wc_facebook_commerce_orders.complete_order_nonce
362
- }, ( response ) => {
363
-
364
- if ( withModal ) {
365
- unBlockModal();
366
- }
367
-
368
- if ( ! response || ! response.success ) {
369
-
370
- let error_message = response && response.data ? response.data : wc_facebook_commerce_orders.i18n.unknown_error;
371
-
372
- alert( error_message );
373
-
374
- return;
375
- }
376
-
377
- $form.data( 'allow-submit', true ).trigger( 'submit' );
378
-
379
- } ).fail( () => {
380
-
381
- showErrorInModal( wc_facebook_commerce_orders.i18n.unknown_error );
382
-
383
- } ).always( () => {
384
-
385
- $form.find( 'button[type=submit].save_order' ).prop( 'disabled', false ).find( 'span.spinner' ).remove();
386
-
387
- } );
388
- }
389
-
390
-
391
- /**
392
- *
393
- * Move the Facebook refund reason field if this is a Commerce order.
394
- *
395
- * @since 2.1.0
396
- */
397
- function maybeMoveRefundReasonField() {
398
-
399
- if ( isCommerceOrder ) {
400
- moveRefundReasonField();
401
- setupRefunReasonMutationObserver();
402
- }
403
- }
404
-
405
-
406
- /**
407
- * Moves the Facebook refund reason field above WooCommerce's refund reason field.
408
- *
409
- * It also updates the labels and tooltips.
410
- *
411
- * @since 2.0.1-dev.1
412
- */
413
- function moveRefundReasonField() {
414
-
415
- let $oldRefundReasonField = $( '#refund_reason' );
416
- let $newRefundReasonField = $( '#wc_facebook_refund_reason' ).clone().css( 'width', $oldRefundReasonField.css( 'width' ) );
417
- let $refundReasonRow = $oldRefundReasonField.closest( 'tr' );
418
- let $refundDescriptionRow = $refundReasonRow.clone();
419
-
420
- $refundReasonRow
421
- .find( 'td.total' ).css( 'width', '16em' ).end()
422
- .find( '#refund_reason' ).replaceWith( $newRefundReasonField.show() ).end()
423
- .find( 'label[for="refund_reason"]' ).attr( 'for', 'wc_facebook_refund_reason' );
424
-
425
- $refundReasonRow.after( $refundDescriptionRow );
426
-
427
- updateOrderTotalFieldLabel(
428
- $refundReasonRow,
429
- 'wc_facebook_refund_reason',
430
- wc_facebook_commerce_orders.i18n.refund_reason_label,
431
- wc_facebook_commerce_orders.i18n.refund_reason_tooltip
432
- );
433
-
434
- updateOrderTotalFieldLabel(
435
- $refundDescriptionRow,
436
- 'refund_reason',
437
- wc_facebook_commerce_orders.i18n.refund_description_label,
438
- wc_facebook_commerce_orders.i18n.refund_description_tooltip
439
- );
440
- }
441
-
442
-
443
- /**
444
- * Setups a MutationObserver to detect when the order refund items elements are replaced.
445
- *
446
- * WooCommerce (meta-boxes-orders.js) does not currently trigger an event when the order items are loaded.
447
- * We use the MutationObserver to move the Facebook refund reason field every time the order refund items are refreshed.
448
- *
449
- * @since 2.1.0
450
- */
451
- function setupRefunReasonMutationObserver() {
452
-
453
- if ( 'undefined' === typeof window.MutationObserver ) {
454
- return;
455
- }
456
-
457
- let node = document.querySelector( '#woocommerce-order-items .inside' );
458
-
459
- if ( ! node ) {
460
- return;
461
- }
462
-
463
- let observer = new MutationObserver( ( records ) => {
464
-
465
- records.forEach( ( record ) => {
466
-
467
- Array.prototype.forEach.call( record.addedNodes, ( child ) => {
468
-
469
- if ( $( child ).is( '.wc-order-refund-items' ) ) {
470
- moveRefundReasonField();
471
- }
472
- } );
473
- } );
474
- } );
475
-
476
- observer.observe( node, { childList: true } );
477
- }
478
-
479
-
480
- /**
481
- * Changes the label and tooltip of the specified order total field.
482
- *
483
- * @since 2.0.1-dev.1
484
- *
485
- * @param {jQuery} $container an element that contains the label of the field
486
- * @param {string} fieldId the id of the field
487
- * @param {string} label the new label for the field
488
- * @param {string} tooltip the new tooltip for the field
489
- */
490
- function updateOrderTotalFieldLabel( $container, fieldId, label, tooltip ) {
491
-
492
- let $label = $container.find( 'label[for="' + fieldId + '"]' );
493
- let $tooltip = $label.find( '.woocommerce-help-tip' ).clone();
494
-
495
- $label.text( label );
496
-
497
- if ( tooltip && $tooltip.length ) {
498
-
499
- $label.prepend( $tooltip );
500
-
501
- $tooltip.attr( 'data-tip', tooltip ).tipTip( {
502
- 'attribute': 'data-tip',
503
- 'fadeIn': 50,
504
- 'fadeOut': 50,
505
- 'delay': 200
506
- } );
507
- }
508
- }
509
-
510
-
511
- maybeMoveRefundReasonField();
512
-
513
- $form.on( 'submit', function( event ) {
514
-
515
- if ( shouldShowCancelOrderModal() ) {
516
- return showCancelOrderModal( event );
517
- }
518
-
519
- if ( ! isCommerceOrder || $form.data( 'allow-submit' ) ) {
520
- return;
521
- }
522
-
523
- let newOrderStatusField = $orderStatusField.val();
524
-
525
- if ( 'wc-refunded' === newOrderStatusField && originalOrderStatus !== newOrderStatusField ) {
526
- displayRefundModal( event );
527
- }
528
-
529
- if ( 'wc-completed' === newOrderStatusField ) {
530
-
531
- event.preventDefault();
532
-
533
- if ( existingTrackingNumber || existingCarrierCode ) {
534
- makeCompleteAjaxRequest( false, existingTrackingNumber, existingCarrierCode );
535
- } else {
536
- displayCompleteModal();
537
- }
538
- }
539
- } );
540
-
541
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
changelog.txt CHANGED
@@ -1,5 +1,16 @@
1
  *** Facebook for WooCommerce Changelog ***
2
 
 
 
 
 
 
 
 
 
 
 
 
3
  = 3.0.4 - 2022-11-21 =
4
  * Dev - Ensure return value matches method signature.
5
 
1
  *** Facebook for WooCommerce Changelog ***
2
 
3
+ = 3.0.5 - 2022-11-30 =
4
+ * Add - Debug tools to help reset settings, delete background options and delete catalog products.
5
+ * Add - Inbox note about Facebook menu moved under the Marketing menu.
6
+ * Dev - Add .nvmrc file.
7
+ * Fix - Facebook Product ID is different from what Facebook ID actually is.
8
+ * Fix - Prevent class redeclaration error for class WC_Facebookcommerce_Utils.
9
+ * Fix - Prevent errors in the disconnection procedure when the user id is missing.
10
+ * Tweak - Remove Facebook Orders sync functionality.
11
+ * Tweak - Update the API version set in the fbAsyncInit script in Advertise tab.
12
+ * Tweak - Update the plugin URI in the plugin file.
13
+
14
  = 3.0.4 - 2022-11-21 =
15
  * Dev - Ensure return value matches method signature.
16
 
class-wc-facebookcommerce.php CHANGED
@@ -12,15 +12,19 @@
12
  require_once __DIR__ . '/vendor/autoload.php';
13
  require_once __DIR__ . '/includes/fbutils.php';
14
 
 
15
  use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists;
16
  use WooCommerce\Facebook\Admin\Tasks\Setup;
 
17
  use WooCommerce\Facebook\Framework\Api\Exception as ApiException;
18
  use WooCommerce\Facebook\Framework\Helper;
 
19
  use WooCommerce\Facebook\Integrations\Bookings as BookingsIntegration;
20
  use WooCommerce\Facebook\Lifecycle;
21
  use WooCommerce\Facebook\ProductSync\ProductValidator as ProductSyncValidator;
22
  use WooCommerce\Facebook\Utilities\Background_Handle_Virtual_Products_Variations;
23
  use WooCommerce\Facebook\Utilities\Background_Remove_Duplicate_Visibility_Meta;
 
24
  use WooCommerce\Facebook\Utilities\Heartbeat;
25
 
26
  class WC_Facebookcommerce extends WooCommerce\Facebook\Framework\Plugin {
@@ -99,6 +103,13 @@ class WC_Facebookcommerce extends WooCommerce\Facebook\Framework\Plugin {
99
  /** @var WooCommerce\Facebook\Utilities\Heartbeat */
100
  public $heartbeat;
101
 
 
 
 
 
 
 
 
102
  /**
103
  * Constructs the plugin.
104
  *
@@ -129,6 +140,7 @@ class WC_Facebookcommerce extends WooCommerce\Facebook\Framework\Plugin {
129
 
130
  // Hook the setup task. The hook admin_init is not triggered when the WC fetches the tasks using the endpoint: wp-json/wc-admin/onboarding/tasks and hence hooking into init.
131
  add_action( 'init', array( $this, 'add_setup_task' ), 20 );
 
132
 
133
  // Product Set breadcrumb filters
134
  add_filter( 'woocommerce_navigation_is_connected_page', array( $this, 'is_current_page_conected_filter' ), 99, 2 );
@@ -182,6 +194,9 @@ class WC_Facebookcommerce extends WooCommerce\Facebook\Framework\Plugin {
182
  $this->job_manager = new WooCommerce\Facebook\Jobs\JobManager();
183
  add_action( 'init', [ $this->job_manager, 'init' ] );
184
 
 
 
 
185
  // load admin handlers, before admin_init
186
  if ( is_admin() ) {
187
  $this->admin_settings = new WooCommerce\Facebook\Admin\Settings();
@@ -207,6 +222,23 @@ class WC_Facebookcommerce extends WooCommerce\Facebook\Framework\Plugin {
207
  );
208
  }
209
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
 
211
  /**
212
  * Gets deprecated and removed hooks.
12
  require_once __DIR__ . '/vendor/autoload.php';
13
  require_once __DIR__ . '/includes/fbutils.php';
14
 
15
+ use Automattic\WooCommerce\Admin\Features\Features as WooAdminFeatures;
16
  use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists;
17
  use WooCommerce\Facebook\Admin\Tasks\Setup;
18
+ use WooCommerce\Facebook\Admin\Notes\SettingsMoved;
19
  use WooCommerce\Facebook\Framework\Api\Exception as ApiException;
20
  use WooCommerce\Facebook\Framework\Helper;
21
+ use WooCommerce\Facebook\Framework\Plugin\Compatibility;
22
  use WooCommerce\Facebook\Integrations\Bookings as BookingsIntegration;
23
  use WooCommerce\Facebook\Lifecycle;
24
  use WooCommerce\Facebook\ProductSync\ProductValidator as ProductSyncValidator;
25
  use WooCommerce\Facebook\Utilities\Background_Handle_Virtual_Products_Variations;
26
  use WooCommerce\Facebook\Utilities\Background_Remove_Duplicate_Visibility_Meta;
27
+ use WooCommerce\Facebook\Utilities\DebugTools;
28
  use WooCommerce\Facebook\Utilities\Heartbeat;
29
 
30
  class WC_Facebookcommerce extends WooCommerce\Facebook\Framework\Plugin {
103
  /** @var WooCommerce\Facebook\Utilities\Heartbeat */
104
  public $heartbeat;
105
 
106
+ /**
107
+ * The Debug tools instance.
108
+ *
109
+ * @var WooCommerce\Facebook\Utilities\DebugTools
110
+ */
111
+ private $debug_tools;
112
+
113
  /**
114
  * Constructs the plugin.
115
  *
140
 
141
  // Hook the setup task. The hook admin_init is not triggered when the WC fetches the tasks using the endpoint: wp-json/wc-admin/onboarding/tasks and hence hooking into init.
142
  add_action( 'init', array( $this, 'add_setup_task' ), 20 );
143
+ add_action( 'admin_notices', array( $this, 'add_inbox_notes' ) );
144
 
145
  // Product Set breadcrumb filters
146
  add_filter( 'woocommerce_navigation_is_connected_page', array( $this, 'is_current_page_conected_filter' ), 99, 2 );
194
  $this->job_manager = new WooCommerce\Facebook\Jobs\JobManager();
195
  add_action( 'init', [ $this->job_manager, 'init' ] );
196
 
197
+ // Instantiate the debug tools.
198
+ $this->debug_tools = new DebugTools();
199
+
200
  // load admin handlers, before admin_init
201
  if ( is_admin() ) {
202
  $this->admin_settings = new WooCommerce\Facebook\Admin\Settings();
222
  );
223
  }
224
 
225
+ /**
226
+ * Add Inbox notes.
227
+ */
228
+ public function add_inbox_notes() {
229
+ if ( Compatibility::is_enhanced_admin_available() ) {
230
+ if ( class_exists( WooAdminFeatures::class ) ) {
231
+ $is_marketing_enabled = WooAdminFeatures::is_enabled( 'marketing' );
232
+ } else {
233
+ $is_marketing_enabled = is_callable( '\Automattic\WooCommerce\Admin\Loader::is_feature_enabled' )
234
+ && \Automattic\WooCommerce\Admin\Loader::is_feature_enabled( 'marketing' );
235
+ }
236
+
237
+ if ( $is_marketing_enabled && class_exists( '\Automattic\WooCommerce\Admin\Notes\Note' ) ) { // Checking for Note class is for backward compatibility.
238
+ SettingsMoved::possibly_add_or_delete_note();
239
+ }
240
+ }
241
+ }
242
 
243
  /**
244
  * Gets deprecated and removed hooks.
facebook-commerce.php CHANGED
@@ -2766,7 +2766,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
2766
  *
2767
  * @param int $product_id product ID
2768
  */
2769
- private function delete_product_group( int $product_id ) {
2770
  $product_group_id = $this->get_product_fbid( self::FB_PRODUCT_GROUP_ID, $product_id );
2771
  if ( $product_group_id ) {
2772
  // TODO: replace with a call to API::delete_product_group() {WV 2020-05-26}
2766
  *
2767
  * @param int $product_id product ID
2768
  */
2769
+ public function delete_product_group( int $product_id ) {
2770
  $product_group_id = $this->get_product_fbid( self::FB_PRODUCT_GROUP_ID, $product_id );
2771
  if ( $product_group_id ) {
2772
  // TODO: replace with a call to API::delete_product_group() {WV 2020-05-26}
facebook-for-woocommerce.php CHANGED
@@ -7,11 +7,11 @@
7
  * LICENSE file in the root directory of this source tree.
8
  *
9
  * Plugin Name: Facebook for WooCommerce
10
- * Plugin URI: https://github.com/facebookincubator/facebook-for-woocommerce/
11
  * 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.
12
  * Author: Facebook
13
  * Author URI: https://www.facebook.com/
14
- * Version: 3.0.4
15
  * Text Domain: facebook-for-woocommerce
16
  * Tested up to: 6.1
17
  * WC requires at least: 5.3
@@ -44,7 +44,7 @@ class WC_Facebook_Loader {
44
  /**
45
  * @var string the plugin version. This must be in the main plugin file to be automatically bumped by Woorelease.
46
  */
47
- const PLUGIN_VERSION = '3.0.4'; // WRCS: DEFINED_VERSION.
48
 
49
  // Minimum PHP version required by this plugin.
50
  const MINIMUM_PHP_VERSION = '7.2.0';
7
  * LICENSE file in the root directory of this source tree.
8
  *
9
  * Plugin Name: Facebook for WooCommerce
10
+ * Plugin URI: https://github.com/woocommerce/facebook-for-woocommerce/
11
  * 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.
12
  * Author: Facebook
13
  * Author URI: https://www.facebook.com/
14
+ * Version: 3.0.5
15
  * Text Domain: facebook-for-woocommerce
16
  * Tested up to: 6.1
17
  * WC requires at least: 5.3
44
  /**
45
  * @var string the plugin version. This must be in the main plugin file to be automatically bumped by Woorelease.
46
  */
47
+ const PLUGIN_VERSION = '3.0.5'; // WRCS: DEFINED_VERSION.
48
 
49
  // Minimum PHP version required by this plugin.
50
  const MINIMUM_PHP_VERSION = '7.2.0';
i18n/languages/facebook-for-woocommerce.pot CHANGED
@@ -2,29 +2,29 @@
2
  # This file is distributed under the same license as the Facebook for WooCommerce plugin.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Facebook for WooCommerce 3.0.4\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/facebook-for-woocommerce\n"
7
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
8
  "Language-Team: LANGUAGE <LL@li.org>\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
- "POT-Creation-Date: 2022-11-21T15:01:13+00:00\n"
13
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
14
  "X-Generator: WP-CLI 2.7.1\n"
15
  "X-Domain: facebook-for-woocommerce\n"
16
 
17
  #. Plugin Name of the plugin
18
- #: class-wc-facebookcommerce.php:701
19
  #: facebook-commerce.php:198
20
- #: includes/Admin.php:1468
21
  #: includes/Admin/Settings.php:93
22
  #: includes/Admin/Settings.php:160
23
  msgid "Facebook for WooCommerce"
24
  msgstr ""
25
 
26
  #. Plugin URI of the plugin
27
- msgid "https://github.com/facebookincubator/facebook-for-woocommerce/"
28
  msgstr ""
29
 
30
  #. Description of the plugin
@@ -32,7 +32,7 @@ msgid "Grow your business on Facebook! Use this official plugin to help sell mor
32
  msgstr ""
33
 
34
  #. Author of the plugin
35
- #: includes/Admin.php:1127
36
  #: includes/Admin/Settings.php:94
37
  #: includes/Admin/Settings.php:332
38
  msgid "Facebook"
@@ -42,47 +42,47 @@ msgstr ""
42
  msgid "https://www.facebook.com/"
43
  msgstr ""
44
 
45
- #: class-wc-facebookcommerce.php:323
46
  #: includes/Admin/Settings.php:123
47
  #: includes/Admin/Settings.php:124
48
  msgid "Facebook Product Sets"
49
  msgstr ""
50
 
51
- #: class-wc-facebookcommerce.php:324
52
  msgid "Facebook Product Set"
53
  msgstr ""
54
 
55
  #. translators: Edit item label
56
- #: class-wc-facebookcommerce.php:332
57
  msgid "Edit %s"
58
  msgstr ""
59
 
60
  #. translators: Add new label
61
- #: class-wc-facebookcommerce.php:334
62
  msgid "Add new %s"
63
  msgstr ""
64
 
65
  #. translators: No items found text
66
- #: class-wc-facebookcommerce.php:337
67
  msgid "No %s found."
68
  msgstr ""
69
 
70
  #. translators: Search label
71
- #: class-wc-facebookcommerce.php:339
72
  msgid "Search %s."
73
  msgstr ""
74
 
75
  #. translators: Text label
76
- #: class-wc-facebookcommerce.php:341
77
  msgid "Separate %s with commas"
78
  msgstr ""
79
 
80
  #. translators: Text label
81
- #: class-wc-facebookcommerce.php:343
82
  msgid "Choose from the most used %s"
83
  msgstr ""
84
 
85
- #: class-wc-facebookcommerce.php:478
86
  msgid "Cannot create the API instance because the access token is missing."
87
  msgstr ""
88
 
@@ -157,175 +157,175 @@ msgstr ""
157
  msgid "%1$s requires WooCommerce version %2$s or higher. Please %3$supdate WooCommerce%4$s to the latest version, or %5$sdownload the minimum required version &raquo;%6$s"
158
  msgstr ""
159
 
160
- #: includes/Admin.php:125
161
  msgid "The name is how it appears on Facebook Catalog."
162
  msgstr ""
163
 
164
- #: includes/Admin.php:165
165
  msgid "Search main categories..."
166
  msgstr ""
167
 
168
- #: includes/Admin.php:166
169
  msgid "Choose a main category"
170
  msgstr ""
171
 
172
- #: includes/Admin.php:167
173
  msgid "Choose a category"
174
  msgstr ""
175
 
176
- #: includes/Admin.php:202
177
  msgid "You have selected one or more categories currently excluded from the Facebook sync. Products belonging to the excluded categories will not be added to your Facebook Product Set."
178
  msgstr ""
179
 
180
- #: includes/Admin.php:240
181
  msgid "Please enter a Google product category and at least one sub-category to sell this product on Instagram."
182
  msgstr ""
183
 
184
- #: includes/Admin.php:296
185
  msgid "To sell this product on Instagram, please ensure it meets the following requirements:"
186
  msgstr ""
187
 
188
- #: includes/Admin.php:298
189
  msgid "Has a price defined"
190
  msgstr ""
191
 
192
  #. translators: Placeholders: %1$s - <strong> opening HTML tag, %2$s - </strong> closing HTML tag
193
- #: includes/Admin.php:304
194
  msgid "Has %1$sManage Stock%2$s enabled on the %1$sInventory%2$s tab"
195
  msgstr ""
196
 
197
  #. translators: Placeholders: %1$s - <strong> opening HTML tag, %2$s - </strong> closing HTML tag
198
- #: includes/Admin.php:316
199
  msgid "Has the %1$sFacebook Sync%2$s setting set to \"Sync and show\" or \"Sync and hide\""
200
  msgstr ""
201
 
202
  #. translators: Placeholders: %1$s - opening <a> link tag, %2$s - closing </a> link tag
203
- #: includes/Admin.php:362
204
  msgid "You're removing a product from the Facebook sync that is currently listed in your %1$sFacebook catalog%2$s. Would you like to delete the product from the Facebook catalog as well?"
205
  msgstr ""
206
 
207
- #: includes/Admin.php:422
208
- #: includes/Admin.php:1170
209
- #: includes/Admin.php:1307
210
  msgid "Facebook sync"
211
  msgstr ""
212
 
213
- #: includes/Admin.php:445
214
- #: includes/Admin.php:473
215
  msgid "Sync and show"
216
  msgstr ""
217
 
218
- #: includes/Admin.php:447
219
- #: includes/Admin.php:474
220
  msgid "Sync and hide"
221
  msgstr ""
222
 
223
- #: includes/Admin.php:450
224
- #: includes/Admin.php:475
225
- #: includes/Admin.php:1174
226
- #: includes/Admin.php:1311
227
  msgid "Do not sync"
228
  msgstr ""
229
 
230
- #: includes/Admin.php:472
231
  msgid "Filter by Facebook sync setting"
232
  msgstr ""
233
 
234
- #: includes/Admin.php:831
235
  msgid "Include in Facebook sync"
236
  msgstr ""
237
 
238
- #: includes/Admin.php:832
239
  msgid "Exclude from Facebook sync"
240
  msgstr ""
241
 
242
  #. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s - <a> tag, %4$s - <a> tag
243
- #: includes/Admin.php:991
244
  msgid "%1$sHeads up!%2$s If this product was previously visible in Facebook, you may need to delete it from the %3$sFacebook catalog%4$s to completely hide it from customer view."
245
  msgid_plural "%1$sHeads up!%2$s If these products were previously visible in Facebook, you may need to delete them from the %3$sFacebook catalog%4$s to completely hide them from customer view."
246
  msgstr[0] ""
247
  msgstr[1] ""
248
 
249
- #: includes/Admin.php:998
250
  msgid "Don't show this notice again"
251
  msgstr ""
252
 
253
  #. translators: Placeholders: %1$s - number of affected products, %2$s opening HTML <a> tag, %3$s - closing HTML </a> tag, %4$s - opening HTML <a> tag, %5$s - closing HTML </a> tag
254
- #: includes/Admin.php:1032
255
  msgid "%2$s%1$s product%3$s or some of its variations could not be updated to show in the Facebook catalog — %4$sFacebook Commerce Policies%5$s prohibit selling some product types (like virtual products). You may still advertise Virtual products on Facebook."
256
  msgid_plural "%2$s%1$s products%3$s or some of their variations could not be updated to show in the Facebook catalog — %4$sFacebook Commerce Policies%5$s prohibit selling some product types (like virtual products). You may still advertise Virtual products on Facebook."
257
  msgstr[0] ""
258
  msgstr[1] ""
259
 
260
  #. translators: Placeholders: %1$s - opening HTML <strong> tag, %2$s - closing HTML </strong> tag, %3$s - opening HTML <a> tag, %4$s - closing HTML </a> tag
261
- #: includes/Admin.php:1098
262
  msgid "%1$sHeads up!%2$s Facebook's %3$sCommerce Policies%4$s do not support selling virtual products, so we have hidden your synced Virtual products in your Facebook catalog. You may still advertise Virtual products on Facebook."
263
  msgstr ""
264
 
265
- #: includes/Admin.php:1172
266
- #: includes/Admin.php:1309
267
  msgid "Sync and show in catalog"
268
  msgstr ""
269
 
270
- #: includes/Admin.php:1173
271
- #: includes/Admin.php:1310
272
  msgid "Sync and hide in catalog"
273
  msgstr ""
274
 
275
- #: includes/Admin.php:1183
276
- #: includes/Admin.php:1323
277
  msgid "Facebook Description"
278
  msgstr ""
279
 
280
- #: includes/Admin.php:1185
281
- #: includes/Admin.php:1325
282
  msgid "Custom (plain-text only) description for product on Facebook. If blank, product description will be used. If product description is blank, shortname will be used."
283
  msgstr ""
284
 
285
- #: includes/Admin.php:1196
286
- #: includes/Admin.php:1338
287
  msgid "Facebook Product Image"
288
  msgstr ""
289
 
290
- #: includes/Admin.php:1198
291
- #: includes/Admin.php:1340
292
  msgid "Choose the product image that should be synced to the Facebook catalog for this product. If using a custom image, please enter an absolute URL (e.g. https://domain.com/image.jpg)."
293
  msgstr ""
294
 
295
- #: includes/Admin.php:1200
296
  msgid "Use WooCommerce image"
297
  msgstr ""
298
 
299
- #: includes/Admin.php:1201
300
- #: includes/Admin.php:1344
301
  msgid "Use custom image"
302
  msgstr ""
303
 
304
- #: includes/Admin.php:1212
305
- #: includes/Admin.php:1356
306
  msgid "Custom Image URL"
307
  msgstr ""
308
 
309
  #. translators: Placeholders %1$s - WC currency symbol
310
- #: includes/Admin.php:1223
311
- #: includes/Admin.php:1369
312
  msgid "Facebook Price (%1$s)"
313
  msgstr ""
314
 
315
- #: includes/Admin.php:1227
316
- #: includes/Admin.php:1373
317
  msgid "Custom price for product on Facebook. Please enter in monetary decimal (.) format without thousand separators and currency symbols. If blank, product price will be used."
318
  msgstr ""
319
 
320
- #: includes/Admin.php:1342
321
  msgid "Use variation image"
322
  msgstr ""
323
 
324
- #: includes/Admin.php:1343
325
  msgid "Use parent image"
326
  msgstr ""
327
 
328
- #: includes/Admin.php:1470
329
  msgid "Close modal panel"
330
  msgstr ""
331
 
@@ -337,6 +337,18 @@ msgstr ""
337
  msgid "Show advanced options"
338
  msgstr ""
339
 
 
 
 
 
 
 
 
 
 
 
 
 
340
  #: includes/Admin/Products.php:96
341
  msgid "Select values for enhanced attributes for this product"
342
  msgstr ""
@@ -382,9 +394,9 @@ msgstr ""
382
 
383
  #: includes/Admin/Product_Categories.php:116
384
  #: includes/Admin/Settings_Screens/Product_Sync.php:148
385
- #: includes/AJAX.php:349
386
- #: includes/AJAX.php:417
387
- #: includes/AJAX.php:483
388
  msgid "Cancel"
389
  msgstr ""
390
 
@@ -422,23 +434,23 @@ msgstr ""
422
  msgid "Facebook Product Sync"
423
  msgstr ""
424
 
425
- #: includes/Admin/Product_Sync_Meta_Box.php:79
426
  msgid "Facebook ID:"
427
  msgstr ""
428
 
429
- #: includes/Admin/Product_Sync_Meta_Box.php:90
430
  msgid "Variant IDs:"
431
  msgstr ""
432
 
433
- #: includes/Admin/Product_Sync_Meta_Box.php:122
434
  msgid "Reset Facebook metadata"
435
  msgstr ""
436
 
437
- #: includes/Admin/Product_Sync_Meta_Box.php:127
438
  msgid "Delete product(s) on Facebook"
439
  msgstr ""
440
 
441
- #: includes/Admin/Product_Sync_Meta_Box.php:139
442
  msgid "This product is not yet synced to Facebook."
443
  msgstr ""
444
 
@@ -464,8 +476,8 @@ msgid "Product sync"
464
  msgstr ""
465
 
466
  #: includes/Admin/Settings.php:174
467
- #: includes/Admin/Settings_Screens/Advertise.php:34
468
  #: includes/Admin/Settings_Screens/Advertise.php:35
 
469
  msgid "Advertise"
470
  msgstr ""
471
 
@@ -483,11 +495,11 @@ msgid "Your settings could not be saved. %s"
483
  msgstr ""
484
 
485
  #. translators: Placeholders: %1$s - opening <a> HTML link tag, %2$s - closing </a> HTML link tag
486
- #: includes/Admin/Settings_Screens/Advertise.php:193
487
  msgid "Please %1$sconnect your store%2$s to Facebook to create ads."
488
  msgstr ""
489
 
490
- #: includes/Admin/Settings_Screens/Advertise.php:211
491
  msgid "If you are connected to Facebook but cannot display ads, please contact Facebook support."
492
  msgstr ""
493
 
@@ -728,141 +740,33 @@ msgstr ""
728
  msgid "20 minutes"
729
  msgstr ""
730
 
731
- #: includes/AJAX.php:83
732
- msgid "Invalid nonce."
733
- msgstr ""
734
-
735
- #: includes/AJAX.php:90
736
- msgid "Order ID is required."
737
- msgstr ""
738
-
739
- #: includes/AJAX.php:94
740
- msgid "Cancel reason is required."
741
- msgstr ""
742
-
743
- #: includes/AJAX.php:100
744
- msgid "A valid Order ID is required."
745
- msgstr ""
746
-
747
- #: includes/AJAX.php:183
748
- msgid "Order ID is required"
749
- msgstr ""
750
-
751
- #: includes/AJAX.php:187
752
- msgid "Tracking number is required"
753
- msgstr ""
754
-
755
- #: includes/AJAX.php:191
756
- msgid "Carrier code is required"
757
- msgstr ""
758
-
759
- #: includes/AJAX.php:197
760
- msgid "Order not found"
761
- msgstr ""
762
-
763
- #: includes/AJAX.php:221
764
  msgid "Full product sync disabled by filter."
765
  msgstr ""
766
 
767
- #: includes/AJAX.php:344
768
- #: includes/AJAX.php:412
769
  msgid "Go to Settings"
770
  msgstr ""
771
 
772
  #. translators: Placeholder %s - <br/> tag
773
- #: includes/AJAX.php:358
774
  msgid "This product belongs to a category or tag that is excluded from the Facebook catalog sync. It will not sync to Facebook. %sTo sync this product to Facebook, click Go to Settings and remove the category or tag exclusion or click Cancel and update the product's category / tag assignments."
775
  msgstr ""
776
 
777
- #: includes/AJAX.php:424
778
  msgid "One or more of the selected products belongs to a category or tag that is excluded from the Facebook catalog sync. To sync these products to Facebook, please remove the category or tag exclusion from the plugin settings."
779
  msgstr ""
780
 
781
- #: includes/AJAX.php:477
782
  msgid "Exclude Products"
783
  msgstr ""
784
 
785
  #. translators: Placeholder %s - <br/> tags
786
- #: includes/AJAX.php:492
787
  msgid "The categories and/or tags that you have selected to exclude from sync contain products that are currently synced to Facebook.%sTo exclude these products from the Facebook sync, click Exclude Products. To review the category / tag exclusion settings, click Cancel."
788
  msgstr ""
789
 
790
- #: includes/Commerce/Orders.php:428
791
- msgid "Order %1$s paid in %2$s"
792
- msgstr ""
793
-
794
- #: includes/Commerce/Orders.php:580
795
- #: includes/Commerce/Orders.php:814
796
- msgid "Remote ID not found."
797
- msgstr ""
798
-
799
- #: includes/Commerce/Orders.php:587
800
- msgid "%s is not a valid shipping carrier code."
801
- msgstr ""
802
-
803
- #: includes/Commerce/Orders.php:605
804
- #: includes/Commerce/Orders.php:781
805
- msgid "No valid Facebook products were found."
806
- msgstr ""
807
-
808
- #. translators: Placeholder: %s - sales channel name, like Facebook or Instagram
809
- #: includes/Commerce/Orders.php:623
810
- msgid "%s order fulfilled."
811
- msgstr ""
812
-
813
- #. translators: Placeholders: %1$s - sales channel name, like Facebook or Instagram, %2$s - error message
814
- #: includes/Commerce/Orders.php:633
815
- msgid "%1$s order could not be fulfilled. %2$s"
816
- msgstr ""
817
-
818
- #: includes/Commerce/Orders.php:676
819
- msgid "Parent order not found."
820
- msgstr ""
821
-
822
- #: includes/Commerce/Orders.php:682
823
- msgid "Remote ID for parent order not found."
824
- msgstr ""
825
-
826
- #. translators: Placeholder: %s - sales channel name, like Facebook or Instagram
827
- #: includes/Commerce/Orders.php:713
828
- msgid "Order refunded on %s."
829
- msgstr ""
830
-
831
- #. translators: Placeholders: %1$s - sales channel name, like Facebook or Instagram, %2$s - error message
832
- #: includes/Commerce/Orders.php:725
833
- msgid "Could not refund %1$s order: %2$s"
834
- msgstr ""
835
-
836
- #. translators: Placeholder: %s - sales channel name, like Facebook or Instagram
837
- #: includes/Commerce/Orders.php:822
838
- msgid "%s order cancelled."
839
- msgstr ""
840
-
841
- #. translators: Placeholders: %1$s - sales channel name, like Facebook or Instagram, %2$s - error message
842
- #: includes/Commerce/Orders.php:832
843
- msgid "%1$s order could not be cancelled. %2$s"
844
- msgstr ""
845
-
846
- #: includes/Commerce/Orders.php:854
847
- msgid "Customer requested cancellation"
848
- msgstr ""
849
-
850
- #: includes/Commerce/Orders.php:855
851
- msgid "Product(s) are out of stock"
852
- msgstr ""
853
-
854
- #: includes/Commerce/Orders.php:856
855
- msgid "Customer address is invalid"
856
- msgstr ""
857
-
858
- #: includes/Commerce/Orders.php:857
859
- msgid "Suspicious order"
860
- msgstr ""
861
-
862
- #: includes/Commerce/Orders.php:858
863
- msgid "Other"
864
- msgstr ""
865
-
866
  #: includes/fbinfobanner.php:184
867
  msgid "Click and redirect."
868
  msgstr ""
@@ -1041,16 +945,16 @@ msgstr ""
1041
  msgid "You do not have permission to uninstall Facebook Business Extension."
1042
  msgstr ""
1043
 
1044
- #: includes/Handlers/Connection.php:339
1045
  msgid "Disconnection successful."
1046
  msgstr ""
1047
 
1048
  #. translators: Placeholders: %s - Facebook page ID
1049
- #: includes/Handlers/Connection.php:402
1050
  msgid "Page %s not authorized."
1051
  msgstr ""
1052
 
1053
- #: includes/Handlers/Connection.php:1280
1054
  msgid "You do not have permission to finish App Store login."
1055
  msgstr ""
1056
 
@@ -1119,3 +1023,67 @@ msgstr ""
1119
  #: includes/ProductSync/ProductValidator.php:389
1120
  msgid "Too many attributes selected for product. Use 4 or less."
1121
  msgstr ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  # This file is distributed under the same license as the Facebook for WooCommerce plugin.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Facebook for WooCommerce 3.0.5\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/facebook-for-woocommerce\n"
7
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
8
  "Language-Team: LANGUAGE <LL@li.org>\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
+ "POT-Creation-Date: 2022-11-30T15:17:13+00:00\n"
13
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
14
  "X-Generator: WP-CLI 2.7.1\n"
15
  "X-Domain: facebook-for-woocommerce\n"
16
 
17
  #. Plugin Name of the plugin
18
+ #: class-wc-facebookcommerce.php:733
19
  #: facebook-commerce.php:198
20
+ #: includes/Admin.php:1467
21
  #: includes/Admin/Settings.php:93
22
  #: includes/Admin/Settings.php:160
23
  msgid "Facebook for WooCommerce"
24
  msgstr ""
25
 
26
  #. Plugin URI of the plugin
27
+ msgid "https://github.com/woocommerce/facebook-for-woocommerce/"
28
  msgstr ""
29
 
30
  #. Description of the plugin
32
  msgstr ""
33
 
34
  #. Author of the plugin
35
+ #: includes/Admin.php:1126
36
  #: includes/Admin/Settings.php:94
37
  #: includes/Admin/Settings.php:332
38
  msgid "Facebook"
42
  msgid "https://www.facebook.com/"
43
  msgstr ""
44
 
45
+ #: class-wc-facebookcommerce.php:355
46
  #: includes/Admin/Settings.php:123
47
  #: includes/Admin/Settings.php:124
48
  msgid "Facebook Product Sets"
49
  msgstr ""
50
 
51
+ #: class-wc-facebookcommerce.php:356
52
  msgid "Facebook Product Set"
53
  msgstr ""
54
 
55
  #. translators: Edit item label
56
+ #: class-wc-facebookcommerce.php:364
57
  msgid "Edit %s"
58
  msgstr ""
59
 
60
  #. translators: Add new label
61
+ #: class-wc-facebookcommerce.php:366
62
  msgid "Add new %s"
63
  msgstr ""
64
 
65
  #. translators: No items found text
66
+ #: class-wc-facebookcommerce.php:369
67
  msgid "No %s found."
68
  msgstr ""
69
 
70
  #. translators: Search label
71
+ #: class-wc-facebookcommerce.php:371
72
  msgid "Search %s."
73
  msgstr ""
74
 
75
  #. translators: Text label
76
+ #: class-wc-facebookcommerce.php:373
77
  msgid "Separate %s with commas"
78
  msgstr ""
79
 
80
  #. translators: Text label
81
+ #: class-wc-facebookcommerce.php:375
82
  msgid "Choose from the most used %s"
83
  msgstr ""
84
 
85
+ #: class-wc-facebookcommerce.php:510
86
  msgid "Cannot create the API instance because the access token is missing."
87
  msgstr ""
88
 
157
  msgid "%1$s requires WooCommerce version %2$s or higher. Please %3$supdate WooCommerce%4$s to the latest version, or %5$sdownload the minimum required version &raquo;%6$s"
158
  msgstr ""
159
 
160
+ #: includes/Admin.php:124
161
  msgid "The name is how it appears on Facebook Catalog."
162
  msgstr ""
163
 
164
+ #: includes/Admin.php:164
165
  msgid "Search main categories..."
166
  msgstr ""
167
 
168
+ #: includes/Admin.php:165
169
  msgid "Choose a main category"
170
  msgstr ""
171
 
172
+ #: includes/Admin.php:166
173
  msgid "Choose a category"
174
  msgstr ""
175
 
176
+ #: includes/Admin.php:201
177
  msgid "You have selected one or more categories currently excluded from the Facebook sync. Products belonging to the excluded categories will not be added to your Facebook Product Set."
178
  msgstr ""
179
 
180
+ #: includes/Admin.php:239
181
  msgid "Please enter a Google product category and at least one sub-category to sell this product on Instagram."
182
  msgstr ""
183
 
184
+ #: includes/Admin.php:295
185
  msgid "To sell this product on Instagram, please ensure it meets the following requirements:"
186
  msgstr ""
187
 
188
+ #: includes/Admin.php:297
189
  msgid "Has a price defined"
190
  msgstr ""
191
 
192
  #. translators: Placeholders: %1$s - <strong> opening HTML tag, %2$s - </strong> closing HTML tag
193
+ #: includes/Admin.php:303
194
  msgid "Has %1$sManage Stock%2$s enabled on the %1$sInventory%2$s tab"
195
  msgstr ""
196
 
197
  #. translators: Placeholders: %1$s - <strong> opening HTML tag, %2$s - </strong> closing HTML tag
198
+ #: includes/Admin.php:315
199
  msgid "Has the %1$sFacebook Sync%2$s setting set to \"Sync and show\" or \"Sync and hide\""
200
  msgstr ""
201
 
202
  #. translators: Placeholders: %1$s - opening <a> link tag, %2$s - closing </a> link tag
203
+ #: includes/Admin.php:361
204
  msgid "You're removing a product from the Facebook sync that is currently listed in your %1$sFacebook catalog%2$s. Would you like to delete the product from the Facebook catalog as well?"
205
  msgstr ""
206
 
207
+ #: includes/Admin.php:421
208
+ #: includes/Admin.php:1169
209
+ #: includes/Admin.php:1306
210
  msgid "Facebook sync"
211
  msgstr ""
212
 
213
+ #: includes/Admin.php:444
214
+ #: includes/Admin.php:472
215
  msgid "Sync and show"
216
  msgstr ""
217
 
218
+ #: includes/Admin.php:446
219
+ #: includes/Admin.php:473
220
  msgid "Sync and hide"
221
  msgstr ""
222
 
223
+ #: includes/Admin.php:449
224
+ #: includes/Admin.php:474
225
+ #: includes/Admin.php:1173
226
+ #: includes/Admin.php:1310
227
  msgid "Do not sync"
228
  msgstr ""
229
 
230
+ #: includes/Admin.php:471
231
  msgid "Filter by Facebook sync setting"
232
  msgstr ""
233
 
234
+ #: includes/Admin.php:830
235
  msgid "Include in Facebook sync"
236
  msgstr ""
237
 
238
+ #: includes/Admin.php:831
239
  msgid "Exclude from Facebook sync"
240
  msgstr ""
241
 
242
  #. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s - <a> tag, %4$s - <a> tag
243
+ #: includes/Admin.php:990
244
  msgid "%1$sHeads up!%2$s If this product was previously visible in Facebook, you may need to delete it from the %3$sFacebook catalog%4$s to completely hide it from customer view."
245
  msgid_plural "%1$sHeads up!%2$s If these products were previously visible in Facebook, you may need to delete them from the %3$sFacebook catalog%4$s to completely hide them from customer view."
246
  msgstr[0] ""
247
  msgstr[1] ""
248
 
249
+ #: includes/Admin.php:997
250
  msgid "Don't show this notice again"
251
  msgstr ""
252
 
253
  #. translators: Placeholders: %1$s - number of affected products, %2$s opening HTML <a> tag, %3$s - closing HTML </a> tag, %4$s - opening HTML <a> tag, %5$s - closing HTML </a> tag
254
+ #: includes/Admin.php:1031
255
  msgid "%2$s%1$s product%3$s or some of its variations could not be updated to show in the Facebook catalog — %4$sFacebook Commerce Policies%5$s prohibit selling some product types (like virtual products). You may still advertise Virtual products on Facebook."
256
  msgid_plural "%2$s%1$s products%3$s or some of their variations could not be updated to show in the Facebook catalog — %4$sFacebook Commerce Policies%5$s prohibit selling some product types (like virtual products). You may still advertise Virtual products on Facebook."
257
  msgstr[0] ""
258
  msgstr[1] ""
259
 
260
  #. translators: Placeholders: %1$s - opening HTML <strong> tag, %2$s - closing HTML </strong> tag, %3$s - opening HTML <a> tag, %4$s - closing HTML </a> tag
261
+ #: includes/Admin.php:1097
262
  msgid "%1$sHeads up!%2$s Facebook's %3$sCommerce Policies%4$s do not support selling virtual products, so we have hidden your synced Virtual products in your Facebook catalog. You may still advertise Virtual products on Facebook."
263
  msgstr ""
264
 
265
+ #: includes/Admin.php:1171
266
+ #: includes/Admin.php:1308
267
  msgid "Sync and show in catalog"
268
  msgstr ""
269
 
270
+ #: includes/Admin.php:1172
271
+ #: includes/Admin.php:1309
272
  msgid "Sync and hide in catalog"
273
  msgstr ""
274
 
275
+ #: includes/Admin.php:1182
276
+ #: includes/Admin.php:1322
277
  msgid "Facebook Description"
278
  msgstr ""
279
 
280
+ #: includes/Admin.php:1184
281
+ #: includes/Admin.php:1324
282
  msgid "Custom (plain-text only) description for product on Facebook. If blank, product description will be used. If product description is blank, shortname will be used."
283
  msgstr ""
284
 
285
+ #: includes/Admin.php:1195
286
+ #: includes/Admin.php:1337
287
  msgid "Facebook Product Image"
288
  msgstr ""
289
 
290
+ #: includes/Admin.php:1197
291
+ #: includes/Admin.php:1339
292
  msgid "Choose the product image that should be synced to the Facebook catalog for this product. If using a custom image, please enter an absolute URL (e.g. https://domain.com/image.jpg)."
293
  msgstr ""
294
 
295
+ #: includes/Admin.php:1199
296
  msgid "Use WooCommerce image"
297
  msgstr ""
298
 
299
+ #: includes/Admin.php:1200
300
+ #: includes/Admin.php:1343
301
  msgid "Use custom image"
302
  msgstr ""
303
 
304
+ #: includes/Admin.php:1211
305
+ #: includes/Admin.php:1355
306
  msgid "Custom Image URL"
307
  msgstr ""
308
 
309
  #. translators: Placeholders %1$s - WC currency symbol
310
+ #: includes/Admin.php:1222
311
+ #: includes/Admin.php:1368
312
  msgid "Facebook Price (%1$s)"
313
  msgstr ""
314
 
315
+ #: includes/Admin.php:1226
316
+ #: includes/Admin.php:1372
317
  msgid "Custom price for product on Facebook. Please enter in monetary decimal (.) format without thousand separators and currency symbols. If blank, product price will be used."
318
  msgstr ""
319
 
320
+ #: includes/Admin.php:1341
321
  msgid "Use variation image"
322
  msgstr ""
323
 
324
+ #: includes/Admin.php:1342
325
  msgid "Use parent image"
326
  msgstr ""
327
 
328
+ #: includes/Admin.php:1469
329
  msgid "Close modal panel"
330
  msgstr ""
331
 
337
  msgid "Show advanced options"
338
  msgstr ""
339
 
340
+ #: includes/Admin/Notes/SettingsMoved.php:75
341
+ msgid "Sync your products and reach customers across Facebook, Instagram, Messenger and WhatsApp through your Facebook plugin, which can be found at Marketing > Facebook."
342
+ msgstr ""
343
+
344
+ #: includes/Admin/Notes/SettingsMoved.php:78
345
+ msgid "Facebook is now found under Marketing"
346
+ msgstr ""
347
+
348
+ #: includes/Admin/Notes/SettingsMoved.php:84
349
+ msgid "Go to Facebook"
350
+ msgstr ""
351
+
352
  #: includes/Admin/Products.php:96
353
  msgid "Select values for enhanced attributes for this product"
354
  msgstr ""
394
 
395
  #: includes/Admin/Product_Categories.php:116
396
  #: includes/Admin/Settings_Screens/Product_Sync.php:148
397
+ #: includes/AJAX.php:242
398
+ #: includes/AJAX.php:310
399
+ #: includes/AJAX.php:376
400
  msgid "Cancel"
401
  msgstr ""
402
 
434
  msgid "Facebook Product Sync"
435
  msgstr ""
436
 
437
+ #: includes/Admin/Product_Sync_Meta_Box.php:83
438
  msgid "Facebook ID:"
439
  msgstr ""
440
 
441
+ #: includes/Admin/Product_Sync_Meta_Box.php:94
442
  msgid "Variant IDs:"
443
  msgstr ""
444
 
445
+ #: includes/Admin/Product_Sync_Meta_Box.php:126
446
  msgid "Reset Facebook metadata"
447
  msgstr ""
448
 
449
+ #: includes/Admin/Product_Sync_Meta_Box.php:131
450
  msgid "Delete product(s) on Facebook"
451
  msgstr ""
452
 
453
+ #: includes/Admin/Product_Sync_Meta_Box.php:143
454
  msgid "This product is not yet synced to Facebook."
455
  msgstr ""
456
 
476
  msgstr ""
477
 
478
  #: includes/Admin/Settings.php:174
 
479
  #: includes/Admin/Settings_Screens/Advertise.php:35
480
+ #: includes/Admin/Settings_Screens/Advertise.php:36
481
  msgid "Advertise"
482
  msgstr ""
483
 
495
  msgstr ""
496
 
497
  #. translators: Placeholders: %1$s - opening <a> HTML link tag, %2$s - closing </a> HTML link tag
498
+ #: includes/Admin/Settings_Screens/Advertise.php:194
499
  msgid "Please %1$sconnect your store%2$s to Facebook to create ads."
500
  msgstr ""
501
 
502
+ #: includes/Admin/Settings_Screens/Advertise.php:212
503
  msgid "If you are connected to Facebook but cannot display ads, please contact Facebook support."
504
  msgstr ""
505
 
740
  msgid "20 minutes"
741
  msgstr ""
742
 
743
+ #: includes/AJAX.php:114
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
744
  msgid "Full product sync disabled by filter."
745
  msgstr ""
746
 
747
+ #: includes/AJAX.php:237
748
+ #: includes/AJAX.php:305
749
  msgid "Go to Settings"
750
  msgstr ""
751
 
752
  #. translators: Placeholder %s - <br/> tag
753
+ #: includes/AJAX.php:251
754
  msgid "This product belongs to a category or tag that is excluded from the Facebook catalog sync. It will not sync to Facebook. %sTo sync this product to Facebook, click Go to Settings and remove the category or tag exclusion or click Cancel and update the product's category / tag assignments."
755
  msgstr ""
756
 
757
+ #: includes/AJAX.php:317
758
  msgid "One or more of the selected products belongs to a category or tag that is excluded from the Facebook catalog sync. To sync these products to Facebook, please remove the category or tag exclusion from the plugin settings."
759
  msgstr ""
760
 
761
+ #: includes/AJAX.php:370
762
  msgid "Exclude Products"
763
  msgstr ""
764
 
765
  #. translators: Placeholder %s - <br/> tags
766
+ #: includes/AJAX.php:385
767
  msgid "The categories and/or tags that you have selected to exclude from sync contain products that are currently synced to Facebook.%sTo exclude these products from the Facebook sync, click Exclude Products. To review the category / tag exclusion settings, click Cancel."
768
  msgstr ""
769
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
770
  #: includes/fbinfobanner.php:184
771
  msgid "Click and redirect."
772
  msgstr ""
945
  msgid "You do not have permission to uninstall Facebook Business Extension."
946
  msgstr ""
947
 
948
+ #: includes/Handlers/Connection.php:340
949
  msgid "Disconnection successful."
950
  msgstr ""
951
 
952
  #. translators: Placeholders: %s - Facebook page ID
953
+ #: includes/Handlers/Connection.php:411
954
  msgid "Page %s not authorized."
955
  msgstr ""
956
 
957
+ #: includes/Handlers/Connection.php:1289
958
  msgid "You do not have permission to finish App Store login."
959
  msgstr ""
960
 
1023
  #: includes/ProductSync/ProductValidator.php:389
1024
  msgid "Too many attributes selected for product. Use 4 or less."
1025
  msgstr ""
1026
+
1027
+ #: includes/Utilities/DebugTools.php:38
1028
+ msgid "Facebook: Reset connection settings"
1029
+ msgstr ""
1030
+
1031
+ #: includes/Utilities/DebugTools.php:39
1032
+ msgid "Reset settings"
1033
+ msgstr ""
1034
+
1035
+ #: includes/Utilities/DebugTools.php:40
1036
+ msgid "This tool will clear your Facebook settings to reset them, allowing you to rebuild your connection."
1037
+ msgstr ""
1038
+
1039
+ #: includes/Utilities/DebugTools.php:45
1040
+ msgid "Facebook: Delete Background Sync Jobs"
1041
+ msgstr ""
1042
+
1043
+ #: includes/Utilities/DebugTools.php:46
1044
+ msgid "Clear Background Sync Jobs"
1045
+ msgstr ""
1046
+
1047
+ #: includes/Utilities/DebugTools.php:47
1048
+ msgid "This tool will clear your clear background sync jobs from the options table."
1049
+ msgstr ""
1050
+
1051
+ #: includes/Utilities/DebugTools.php:52
1052
+ msgid "Facebook: Reset all products"
1053
+ msgstr ""
1054
+
1055
+ #: includes/Utilities/DebugTools.php:53
1056
+ msgid "Reset products Facebook settings"
1057
+ msgstr ""
1058
+
1059
+ #: includes/Utilities/DebugTools.php:54
1060
+ msgid "This tool will reset Facebook settings for all products on your WooCommerce store."
1061
+ msgstr ""
1062
+
1063
+ #: includes/Utilities/DebugTools.php:59
1064
+ msgid "Facebook: Delete all products from your Facebook Catalog"
1065
+ msgstr ""
1066
+
1067
+ #: includes/Utilities/DebugTools.php:60
1068
+ msgid "Delete all products"
1069
+ msgstr ""
1070
+
1071
+ #: includes/Utilities/DebugTools.php:61
1072
+ msgid "This tool will delete all products from your Facebook Catalog."
1073
+ msgstr ""
1074
+
1075
+ #: includes/Utilities/DebugTools.php:80
1076
+ msgid "Background sync jobs have been deleted."
1077
+ msgstr ""
1078
+
1079
+ #: includes/Utilities/DebugTools.php:95
1080
+ msgid "Cleared all Facebook settings!"
1081
+ msgstr ""
1082
+
1083
+ #: includes/Utilities/DebugTools.php:108
1084
+ msgid "Reset products Facebook settings job started!"
1085
+ msgstr ""
1086
+
1087
+ #: includes/Utilities/DebugTools.php:121
1088
+ msgid "Delete products from Facebook catalog job started!"
1089
+ msgstr ""
includes/AJAX.php CHANGED
@@ -24,17 +24,9 @@ defined( 'ABSPATH' ) or exit;
24
  */
25
  class AJAX {
26
 
27
-
28
  /** @var string the product attribute search AJAX action */
29
  const ACTION_SEARCH_PRODUCT_ATTRIBUTES = 'wc_facebook_search_product_attributes';
30
 
31
- /** @var string facebook order cancel AJAX action */
32
- const ACTION_CANCEL_ORDER = 'wc_facebook_cancel_order';
33
-
34
- /** @var string the complete order AJAX action */
35
- const ACTION_COMPLETE_ORDER = 'wc_facebook_complete_order';
36
-
37
-
38
  /**
39
  * AJAX handler constructor.
40
  *
@@ -57,57 +49,6 @@ class AJAX {
57
 
58
  // search a product's attributes for the given term
59
  add_action( 'wp_ajax_' . self::ACTION_SEARCH_PRODUCT_ATTRIBUTES, array( $this, 'admin_search_product_attributes' ) );
60
-
61
- // complete a Facebook order for the given order ID
62
- add_action( 'wp_ajax_' . self::ACTION_COMPLETE_ORDER, array( $this, 'admin_complete_order' ) );
63
-
64
- // cancel facebook order by the given order ID
65
- add_action( 'wp_ajax_' . self::ACTION_CANCEL_ORDER, array( $this, 'admin_cancel_order' ) );
66
- }
67
-
68
-
69
- /**
70
- * Cancels a Facebook order by the given order ID.
71
- *
72
- * @internal
73
- *
74
- * @since 2.1.0
75
- */
76
- public function admin_cancel_order() {
77
-
78
- $order = null;
79
-
80
- try {
81
-
82
- if ( ! wp_verify_nonce( Helper::get_posted_value( 'security' ), self::ACTION_CANCEL_ORDER ) ) {
83
- throw new PluginException( __( 'Invalid nonce.', 'facebook-for-woocommerce' ) );
84
- }
85
-
86
- $order_id = Helper::get_posted_value( 'order_id' );
87
- $reason_code = Helper::get_posted_value( 'reason_code' );
88
-
89
- if ( empty( $order_id ) ) {
90
- throw new PluginException( __( 'Order ID is required.', 'facebook-for-woocommerce' ) );
91
- }
92
-
93
- if ( empty( $reason_code ) ) {
94
- throw new PluginException( __( 'Cancel reason is required.', 'facebook-for-woocommerce' ) );
95
- }
96
-
97
- $order = wc_get_order( absint( $order_id ) );
98
-
99
- if ( false === $order ) {
100
- throw new PluginException( __( 'A valid Order ID is required.', 'facebook-for-woocommerce' ) );
101
- }
102
-
103
- facebook_for_woocommerce()->get_commerce_handler()->get_orders_handler()->cancel_order( $order, $reason_code );
104
-
105
- wp_send_json_success();
106
-
107
- } catch ( PluginException $exception ) {
108
-
109
- wp_send_json_error( $exception->getMessage() );
110
- }
111
  }
112
 
113
 
@@ -160,54 +101,6 @@ class AJAX {
160
  }
161
 
162
 
163
- /**
164
- * Completes a Facebook order for the given order ID.
165
- *
166
- * @internal
167
- *
168
- * @since 2.1.0
169
- */
170
- public function admin_complete_order() {
171
-
172
- try {
173
-
174
- if ( ! wp_verify_nonce( Helper::get_posted_value( 'nonce' ), self::ACTION_COMPLETE_ORDER ) ) {
175
- throw new PluginException( 'Invalid nonce', 403 );
176
- }
177
-
178
- $order_id = (int) Helper::get_posted_value( 'order_id' );
179
- $tracking_number = wc_clean( Helper::get_posted_value( 'tracking_number' ) );
180
- $carrier_code = wc_clean( Helper::get_posted_value( 'carrier_code' ) );
181
-
182
- if ( empty( $order_id ) ) {
183
- throw new PluginException( __( 'Order ID is required', 'facebook-for-woocommerce' ) );
184
- }
185
-
186
- if ( empty( $tracking_number ) ) {
187
- throw new PluginException( __( 'Tracking number is required', 'facebook-for-woocommerce' ) );
188
- }
189
-
190
- if ( empty( $carrier_code ) ) {
191
- throw new PluginException( __( 'Carrier code is required', 'facebook-for-woocommerce' ) );
192
- }
193
-
194
- $order = wc_get_order( $order_id );
195
-
196
- if ( ! $order instanceof \WC_Order ) {
197
- throw new PluginException( __( 'Order not found', 'facebook-for-woocommerce' ) );
198
- }
199
-
200
- facebook_for_woocommerce()->get_commerce_handler()->get_orders_handler()->fulfill_order( $order, $tracking_number, $carrier_code );
201
-
202
- wp_send_json_success();
203
-
204
- } catch ( PluginException $exception ) {
205
-
206
- wp_send_json_error( $exception->getMessage(), $exception->getCode() );
207
- }
208
- }
209
-
210
-
211
  /**
212
  * Syncs all products via AJAX.
213
  *
24
  */
25
  class AJAX {
26
 
 
27
  /** @var string the product attribute search AJAX action */
28
  const ACTION_SEARCH_PRODUCT_ATTRIBUTES = 'wc_facebook_search_product_attributes';
29
 
 
 
 
 
 
 
 
30
  /**
31
  * AJAX handler constructor.
32
  *
49
 
50
  // search a product's attributes for the given term
51
  add_action( 'wp_ajax_' . self::ACTION_SEARCH_PRODUCT_ATTRIBUTES, array( $this, 'admin_search_product_attributes' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  }
53
 
54
 
101
  }
102
 
103
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  /**
105
  * Syncs all products via AJAX.
106
  *
includes/API.php CHANGED
@@ -13,7 +13,6 @@ namespace WooCommerce\Facebook;
13
 
14
  defined( 'ABSPATH' ) or exit;
15
 
16
- use WooCommerce\Facebook\API\Orders\Order;
17
  use WooCommerce\Facebook\API\Request;
18
  use WooCommerce\Facebook\API\Response;
19
  use WooCommerce\Facebook\Events\Event;
@@ -606,140 +605,6 @@ class API extends Base {
606
  }
607
 
608
 
609
- /**
610
- * Gets all new orders.
611
- *
612
- * @since 2.1.0
613
- *
614
- * @param string $page_id page ID
615
- * @return API\Orders\Response
616
- * @throws ApiException
617
- */
618
- public function get_new_orders( $page_id ) {
619
- $request_args = array(
620
- 'state' => array(
621
- Order::STATUS_PROCESSING,
622
- Order::STATUS_CREATED,
623
- ),
624
- );
625
- $request = new API\Orders\Request( $page_id, $request_args );
626
- $this->set_response_handler( API\Orders\Response::class );
627
- return $this->perform_request( $request );
628
- }
629
-
630
-
631
- /**
632
- * Gets the latest cancelled orders.
633
- *
634
- * @since 2.1.0
635
- *
636
- * @param string $page_id page ID
637
- * @return API\Orders\Response
638
- * @throws ApiException
639
- */
640
- public function get_cancelled_orders( $page_id ) {
641
- $request_args = array(
642
- 'state' => array(
643
- Order::STATUS_COMPLETED,
644
- ),
645
- 'updated_after' => time() - facebook_for_woocommerce()->get_commerce_handler()->get_orders_handler()->get_order_update_interval(),
646
- 'filters' => 'has_cancellations',
647
- );
648
- $request = new API\Orders\Request( $page_id, $request_args );
649
- $this->set_response_handler( API\Orders\Response::class );
650
- return $this->perform_request( $request );
651
- }
652
-
653
-
654
- /**
655
- * Gets a single order based on its remote ID.
656
- *
657
- * @since 2.1.0
658
- *
659
- * @param string $remote_id remote order ID
660
- * @return API\Orders\Read\Response
661
- * @throws ApiException
662
- */
663
- public function get_order( $remote_id ) {
664
- $request = new API\Orders\Read\Request( $remote_id );
665
- $this->set_response_handler( API\Orders\Read\Response::class );
666
- return $this->perform_request( $request );
667
- }
668
-
669
-
670
- /**
671
- * Acknowledges the given order.
672
- *
673
- * @since 2.1.0
674
- *
675
- * @param string $remote_id remote order ID
676
- * @param string $merchant_order_reference WC order ID
677
- * @return API\Response
678
- * @throws ApiException
679
- */
680
- public function acknowledge_order( $remote_id, $merchant_order_reference ) {
681
- $request = new API\Orders\Acknowledge\Request( $remote_id, $merchant_order_reference );
682
- $this->set_response_handler( API\Response::class );
683
- return $this->perform_request( $request );
684
- }
685
-
686
-
687
- /**
688
- * Issues a fulfillment request for the given order.
689
- *
690
- * @see https://developers.facebook.com/docs/commerce-platform/order-management/fulfillment-api#attach_shipment
691
- *
692
- * @since 2.1.0
693
- *
694
- * @param string $remote_id remote order ID
695
- * @param array $fulfillment_data fulfillment data to be sent on the request
696
- * @return API\Response
697
- * @throws ApiException
698
- */
699
- public function fulfill_order( $remote_id, $fulfillment_data ) {
700
- $request = new API\Orders\Fulfillment\Request( $remote_id, $fulfillment_data );
701
- $this->set_response_handler( API\Response::class );
702
- return $this->perform_request( $request );
703
- }
704
-
705
-
706
- /**
707
- * Cancels the given order.
708
- *
709
- * @since 2.1.0
710
- *
711
- * @param string $remote_id remote order ID
712
- * @param string $reason cancellation reason
713
- * @param bool $restock_items whether to restock items remotely
714
- * @return API\Response
715
- * @throws ApiException
716
- */
717
- public function cancel_order( $remote_id, $reason, $restock_items = true ) {
718
- $request = new API\Orders\Cancel\Request( $remote_id, $reason, $restock_items );
719
- $this->set_response_handler( API\Response::class );
720
- return $this->perform_request( $request );
721
- }
722
-
723
-
724
- /**
725
- * Issues a refund request for the given order.
726
- *
727
- * @see https://developers.facebook.com/docs/commerce-platform/order-management/cancellation-refund-api#refund_order
728
- *
729
- * @since 2.1.0
730
- *
731
- * @param string $remote_id remote order ID
732
- * @param array $refund_data refund data to be sent on the request
733
- * @return API\Response
734
- * @throws ApiException
735
- */
736
- public function add_order_refund( $remote_id, $refund_data ) {
737
- $request = new API\Orders\Refund\Request( $remote_id, $refund_data );
738
- $this->set_response_handler( API\Response::class );
739
- return $this->perform_request( $request );
740
- }
741
-
742
-
743
  /**
744
  * Returns a new request object.
745
  *
13
 
14
  defined( 'ABSPATH' ) or exit;
15
 
 
16
  use WooCommerce\Facebook\API\Request;
17
  use WooCommerce\Facebook\API\Response;
18
  use WooCommerce\Facebook\Events\Event;
605
  }
606
 
607
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
608
  /**
609
  * Returns a new request object.
610
  *
includes/API/Orders/Abstract_Request.php DELETED
@@ -1,36 +0,0 @@
1
- <?php
2
- // phpcs:ignoreFile
3
- /**
4
- * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
5
- *
6
- * This source code is licensed under the license found in the
7
- * LICENSE file in the root directory of this source tree.
8
- *
9
- * @package FacebookCommerce
10
- */
11
-
12
- namespace WooCommerce\Facebook\API\Orders;
13
-
14
- defined( 'ABSPATH' ) or exit;
15
-
16
- use WooCommerce\Facebook\API;
17
-
18
- abstract class Abstract_Request extends API\Request {
19
-
20
-
21
- /**
22
- * Abstract_Request constructor.
23
- *
24
- * @param string $path request path
25
- * @param string $method request method
26
- */
27
- public function __construct( $path, $method ) {
28
-
29
- parent::__construct( $path, $method );
30
-
31
- /** @link https://developers.facebook.com/docs/commerce-platform/order-management/error-codes */
32
- $this->retry_codes[] = 2361081;
33
- }
34
-
35
-
36
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/API/Orders/Acknowledge/Request.php DELETED
@@ -1,65 +0,0 @@
1
- <?php
2
- // phpcs:ignoreFile
3
- /**
4
- * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
5
- *
6
- * This source code is licensed under the license found in the
7
- * LICENSE file in the root directory of this source tree.
8
- *
9
- * @package FacebookCommerce
10
- */
11
-
12
- namespace WooCommerce\Facebook\API\Orders\Acknowledge;
13
-
14
- defined( 'ABSPATH' ) or exit;
15
-
16
- use WooCommerce\Facebook\API;
17
-
18
- /**
19
- * Orders API acknowledge request object.
20
- *
21
- * @since 2.1.0
22
- */
23
- class Request extends API\Orders\Abstract_Request {
24
-
25
-
26
- use API\Traits\Idempotent_Request;
27
-
28
-
29
- /**
30
- * API request constructor.
31
- *
32
- * @since 2.1.0
33
- *
34
- * @param string $remote_id remote order ID
35
- * @param string $merchant_order_reference WC order ID
36
- */
37
- public function __construct( $remote_id, $merchant_order_reference ) {
38
-
39
- parent::__construct( "/{$remote_id}/acknowledge_order", 'POST' );
40
-
41
- $this->set_data(
42
- array(
43
- 'merchant_order_reference' => $merchant_order_reference,
44
- 'idempotency_key' => $this->get_idempotency_key(),
45
- )
46
- );
47
- }
48
-
49
-
50
- /**
51
- * Gets the rate limit ID.
52
- *
53
- * While this is the Orders API, orders belong to pages so this is where the rate limit comes from.
54
- *
55
- * @since 2.1.0
56
- *
57
- * @return string
58
- */
59
- public static function get_rate_limit_id() {
60
-
61
- return 'pages';
62
- }
63
-
64
-
65
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/API/Orders/Cancel/Request.php DELETED
@@ -1,69 +0,0 @@
1
- <?php
2
- // phpcs:ignoreFile
3
- /**
4
- * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
5
- *
6
- * This source code is licensed under the license found in the
7
- * LICENSE file in the root directory of this source tree.
8
- *
9
- * @package FacebookCommerce
10
- */
11
-
12
- namespace WooCommerce\Facebook\API\Orders\Cancel;
13
-
14
- defined( 'ABSPATH' ) or exit;
15
-
16
- use WooCommerce\Facebook\API;
17
-
18
- /**
19
- * Orders API cancel request object.
20
- *
21
- * @since 2.1.0
22
- */
23
- class Request extends API\Orders\Abstract_Request {
24
-
25
-
26
- use API\Traits\Idempotent_Request;
27
-
28
-
29
- /**
30
- * API request constructor.
31
- *
32
- * @since 2.1.0
33
- *
34
- * @param string $remote_id remote order ID
35
- * @param string $reason cancellation reason code
36
- * @param bool $restock_items whether or not the items were restocked
37
- */
38
- public function __construct( $remote_id, $reason, $restock_items = true ) {
39
-
40
- parent::__construct( "/{$remote_id}/cancellations", 'POST' );
41
-
42
- $this->set_data(
43
- array(
44
- 'cancel_reason' => array(
45
- 'reason_code' => $reason,
46
- ),
47
- 'restock_items' => $restock_items,
48
- 'idempotency_key' => $this->get_idempotency_key(),
49
- )
50
- );
51
- }
52
-
53
-
54
- /**
55
- * Gets the rate limit ID.
56
- *
57
- * While this is the Orders API, orders belong to pages so this is where the rate limit comes from.
58
- *
59
- * @since 2.1.0
60
- *
61
- * @return string
62
- */
63
- public static function get_rate_limit_id() {
64
-
65
- return 'pages';
66
- }
67
-
68
-
69
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/API/Orders/Fulfillment/Request.php DELETED
@@ -1,62 +0,0 @@
1
- <?php
2
- // phpcs:ignoreFile
3
- /**
4
- * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
5
- *
6
- * This source code is licensed under the license found in the
7
- * LICENSE file in the root directory of this source tree.
8
- *
9
- * @package FacebookCommerce
10
- */
11
-
12
- namespace WooCommerce\Facebook\API\Orders\Fulfillment;
13
-
14
- defined( 'ABSPATH' ) or exit;
15
-
16
- use WooCommerce\Facebook\API;
17
-
18
- /**
19
- * Orders API fulfillment request object.
20
- *
21
- * @since 2.1.0
22
- */
23
- class Request extends API\Orders\Abstract_Request {
24
-
25
-
26
- use API\Traits\Idempotent_Request;
27
-
28
-
29
- /**
30
- * API request constructor.
31
- *
32
- * @since 2.1.0
33
- *
34
- * @param string $remote_id remote order ID
35
- * @param array $fulfillment_data fulfillment data
36
- */
37
- public function __construct( $remote_id, $fulfillment_data ) {
38
-
39
- parent::__construct( "/{$remote_id}/shipments", 'POST' );
40
-
41
- $fulfillment_data['idempotency_key'] = $this->get_idempotency_key();
42
-
43
- $this->set_data( $fulfillment_data );
44
- }
45
-
46
-
47
- /**
48
- * Gets the rate limit ID.
49
- *
50
- * While this is the Orders API, orders belong to pages so this is where the rate limit comes from.
51
- *
52
- * @since 2.1.0
53
- *
54
- * @return string
55
- */
56
- public static function get_rate_limit_id() {
57
-
58
- return 'pages';
59
- }
60
-
61
-
62
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/API/Orders/Order.php DELETED
@@ -1,168 +0,0 @@
1
- <?php
2
- // phpcs:ignoreFile
3
- /**
4
- * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
5
- *
6
- * This source code is licensed under the license found in the
7
- * LICENSE file in the root directory of this source tree.
8
- *
9
- * @package FacebookCommerce
10
- */
11
-
12
- namespace WooCommerce\Facebook\API\Orders;
13
-
14
- defined( 'ABSPATH' ) or exit;
15
-
16
- /**
17
- * Orders API order handler.
18
- *
19
- * @since 2.1.0
20
- */
21
- class Order {
22
-
23
-
24
- /** @var string API state meaning Facebook is still processing the order and no action is possible */
25
- const STATUS_PROCESSING = 'FB_PROCESSING';
26
-
27
- /** @var string API state meaning Facebook has processed the orders and the seller needs to acknowledge it */
28
- const STATUS_CREATED = 'CREATED';
29
-
30
- /** @var string API state meaning the order was acknowledged and is now being processed in WC */
31
- const STATUS_IN_PROGRESS = 'IN_PROGRESS';
32
-
33
- /** @var string API state meaning all items in the order are shipped and/or cancelled */
34
- const STATUS_COMPLETED = 'COMPLETED';
35
-
36
-
37
- /** @var array order data */
38
- protected $data;
39
-
40
-
41
- /**
42
- * Orders API order handler constructor.
43
- *
44
- * @since 2.1.0
45
- *
46
- * @param array $response_data response data from the API
47
- */
48
- public function __construct( $response_data ) {
49
-
50
- $this->data = $response_data;
51
- }
52
-
53
-
54
- /**
55
- * Gets the order’s ID.
56
- *
57
- * @since 2.1.0
58
- *
59
- * @return string
60
- */
61
- public function get_id() {
62
-
63
- return ! empty( $this->data['id'] ) ? $this->data['id'] : '';
64
- }
65
-
66
-
67
- /**
68
- * Gets the order’s status.
69
- *
70
- * @since 2.1.0
71
- *
72
- * @return string
73
- */
74
- public function get_status() {
75
-
76
- return ! empty( $this->data['order_status'] ) && ! empty( $this->data['order_status']['state'] ) ? $this->data['order_status']['state'] : '';
77
- }
78
-
79
-
80
- /**
81
- * Gets the items' data.
82
- *
83
- * @see https://developers.facebook.com/docs/commerce-platform/order-management/order-api#item
84
- *
85
- * @since 2.1.0
86
- *
87
- * @return array
88
- */
89
- public function get_items() {
90
-
91
- return ! empty( $this->data['items']['data'] ) ? $this->data['items']['data'] : array();
92
- }
93
-
94
-
95
- /**
96
- * Gets the channel name.
97
- *
98
- * @since 2.1.0
99
- *
100
- * @return string
101
- */
102
- public function get_channel() {
103
-
104
- return ! empty( $this->data['channel'] ) ? $this->data['channel'] : '';
105
- }
106
-
107
-
108
- /**
109
- * Gets the shipping details.
110
- *
111
- * @see https://developers.facebook.com/docs/commerce-platform/order-management/order-api#selected_shipping_option
112
- *
113
- * @since 2.1.0
114
- *
115
- * @return array
116
- */
117
- public function get_selected_shipping_option() {
118
-
119
- return isset( $this->data['selected_shipping_option'] ) ? $this->data['selected_shipping_option'] : array();
120
- }
121
-
122
-
123
- /**
124
- * Gets the shipping address.
125
- *
126
- * @see https://developers.facebook.com/docs/commerce-platform/order-management/order-api#shipping_address
127
- *
128
- * @since 2.1.0
129
- *
130
- * @return array
131
- */
132
- public function get_shipping_address() {
133
-
134
- return isset( $this->data['shipping_address'] ) ? $this->data['shipping_address'] : array();
135
- }
136
-
137
-
138
- /**
139
- * Gets the payment details.
140
- *
141
- * @see https://developers.facebook.com/docs/commerce-platform/order-management/order-api#estimated_payment_details
142
- *
143
- * @since 2.1.0
144
- *
145
- * @return array
146
- */
147
- public function get_estimated_payment_details() {
148
-
149
- return isset( $this->data['estimated_payment_details'] ) ? $this->data['estimated_payment_details'] : array();
150
- }
151
-
152
-
153
- /**
154
- * Gets the buyer details.
155
- *
156
- * @see https://developers.facebook.com/docs/commerce-platform/order-management/order-api#buyer_details
157
- *
158
- * @since 2.1.0
159
- *
160
- * @return array
161
- */
162
- public function get_buyer_details() {
163
-
164
- return isset( $this->data['buyer_details'] ) ? $this->data['buyer_details'] : array();
165
- }
166
-
167
-
168
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/API/Orders/Read/Request.php DELETED
@@ -1,83 +0,0 @@
1
- <?php
2
- // phpcs:ignoreFile
3
- /**
4
- * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
5
- *
6
- * This source code is licensed under the license found in the
7
- * LICENSE file in the root directory of this source tree.
8
- *
9
- * @package FacebookCommerce
10
- */
11
-
12
- namespace WooCommerce\Facebook\API\Orders\Read;
13
-
14
- defined( 'ABSPATH' ) or exit;
15
-
16
- use WooCommerce\Facebook\API;
17
-
18
- /**
19
- * Orders API read request object.
20
- *
21
- * @since 2.1.0
22
- */
23
- class Request extends API\Orders\Abstract_Request {
24
-
25
-
26
- /**
27
- * API request constructor.
28
- *
29
- * @since 2.1.0
30
- *
31
- * @param string $remote_id remote order ID
32
- * @param array $fields fields to be returned
33
- */
34
- public function __construct( $remote_id, $fields = array() ) {
35
-
36
- parent::__construct( "/{$remote_id}", 'GET' );
37
-
38
- if ( empty( $fields ) ) {
39
-
40
- // request all top-level fields
41
- $fields = implode(
42
- ',',
43
- array(
44
- 'id',
45
- 'order_status',
46
- 'created',
47
- 'last_updated',
48
- 'items{id,retailer_id,product_id,quantity,price_per_unit,tax_details}',
49
- 'ship_by_date',
50
- 'merchant_order_id',
51
- 'channel',
52
- 'selected_shipping_option',
53
- 'shipping_address',
54
- 'estimated_payment_details',
55
- 'buyer_details',
56
- )
57
- );
58
-
59
- } elseif ( is_array( $fields ) ) {
60
-
61
- $fields = implode( ',', $fields );
62
- }
63
-
64
- $this->set_params( array( 'fields' => $fields ) );
65
- }
66
-
67
-
68
- /**
69
- * Gets the rate limit ID.
70
- *
71
- * While this is the Orders API, orders belong to pages so this is where the rate limit comes from.
72
- *
73
- * @since 2.1.0
74
- *
75
- * @return string
76
- */
77
- public static function get_rate_limit_id() {
78
-
79
- return 'pages';
80
- }
81
-
82
-
83
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/API/Orders/Read/Response.php DELETED
@@ -1,40 +0,0 @@
1
- <?php
2
- // phpcs:ignoreFile
3
- /**
4
- * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
5
- *
6
- * This source code is licensed under the license found in the
7
- * LICENSE file in the root directory of this source tree.
8
- *
9
- * @package FacebookCommerce
10
- */
11
-
12
- namespace WooCommerce\Facebook\API\Orders\Read;
13
-
14
- defined( 'ABSPATH' ) or exit;
15
-
16
- use WooCommerce\Facebook\API;
17
- use WooCommerce\Facebook\API\Orders\Order;
18
-
19
- /**
20
- * Orders API read response object.
21
- *
22
- * @since 2.1.0
23
- */
24
- class Response extends API\Response {
25
-
26
-
27
- /**
28
- * Gets an order object from the response data.
29
- *
30
- * @since 2.1.0
31
- *
32
- * @return \WooCommerce\Facebook\API\Orders\Order
33
- */
34
- public function get_order() {
35
-
36
- return new Order( json_decode( json_encode( $this->response_data ), true ) );
37
- }
38
-
39
-
40
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/API/Orders/Refund/Request.php DELETED
@@ -1,62 +0,0 @@
1
- <?php
2
- // phpcs:ignoreFile
3
- /**
4
- * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
5
- *
6
- * This source code is licensed under the license found in the
7
- * LICENSE file in the root directory of this source tree.
8
- *
9
- * @package FacebookCommerce
10
- */
11
-
12
- namespace WooCommerce\Facebook\API\Orders\Refund;
13
-
14
- defined( 'ABSPATH' ) or exit;
15
-
16
- use WooCommerce\Facebook\API;
17
-
18
- /**
19
- * Orders API refund request object.
20
- *
21
- * @since 2.1.0
22
- */
23
- class Request extends API\Orders\Abstract_Request {
24
-
25
-
26
- use API\Traits\Idempotent_Request;
27
-
28
-
29
- /**
30
- * API request constructor.
31
- *
32
- * @since 2.1.0
33
- *
34
- * @param string $remote_id remote order ID
35
- * @param array $refund_data refund data
36
- */
37
- public function __construct( $remote_id, $refund_data ) {
38
-
39
- parent::__construct( "/{$remote_id}/refunds", 'POST' );
40
-
41
- $refund_data['idempotency_key'] = $this->get_idempotency_key();
42
-
43
- $this->set_data( $refund_data );
44
- }
45
-
46
-
47
- /**
48
- * Gets the rate limit ID.
49
- *
50
- * While this is the Orders API, orders belong to pages so this is where the rate limit comes from.
51
- *
52
- * @since 2.1.0
53
- *
54
- * @return string
55
- */
56
- public static function get_rate_limit_id() {
57
-
58
- return 'pages';
59
- }
60
-
61
-
62
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/API/Orders/Request.php DELETED
@@ -1,105 +0,0 @@
1
- <?php
2
- // phpcs:ignoreFile
3
- /**
4
- * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
5
- *
6
- * This source code is licensed under the license found in the
7
- * LICENSE file in the root directory of this source tree.
8
- *
9
- * @package FacebookCommerce
10
- */
11
-
12
- namespace WooCommerce\Facebook\API\Orders;
13
-
14
- defined( 'ABSPATH' ) or exit;
15
-
16
- /**
17
- * Orders API list request object.
18
- *
19
- * @since 2.1.0
20
- */
21
- class Request extends Abstract_Request {
22
-
23
-
24
- /**
25
- * Gets the rate limit ID.
26
- *
27
- * While this is the Orders API, orders belong to pages so this is where the rate limit comes from.
28
- *
29
- * @since 2.1.0
30
- *
31
- * @return string
32
- */
33
- public static function get_rate_limit_id() {
34
-
35
- return 'pages';
36
- }
37
-
38
-
39
- /**
40
- * API request constructor.
41
- *
42
- * @see https://developers.facebook.com/docs/commerce-platform/order-management/order-api#get_orders
43
- *
44
- * @since 2.1.0
45
- *
46
- * @param string $page_id page ID
47
- * @param array $args optional additional arguments
48
- */
49
- public function __construct( $page_id, $args = array() ) {
50
-
51
- parent::__construct( "/{$page_id}/commerce_orders", 'GET' );
52
-
53
- $params = array();
54
-
55
- if ( isset( $args['updated_before'] ) ) {
56
-
57
- $params['updated_before'] = $args['updated_before'];
58
- }
59
-
60
- if ( isset( $args['updated_after'] ) ) {
61
-
62
- $params['updated_after'] = $args['updated_after'];
63
- }
64
-
65
- if ( isset( $args['state'] ) ) {
66
-
67
- $params['state'] = is_array( $args['state'] ) ? implode( ',', $args['state'] ) : $args['state'];
68
- }
69
-
70
- if ( isset( $args['filters'] ) ) {
71
-
72
- $params['filters'] = is_array( $args['filters'] ) ? implode( ',', $args['filters'] ) : $args['filters'];
73
- }
74
-
75
- if ( ! empty( $args['fields'] ) ) {
76
-
77
- $params['fields'] = is_array( $args['fields'] ) ? implode( ',', $args['fields'] ) : $args['fields'];
78
-
79
- } else {
80
-
81
- // request all top-level fields
82
- $params['fields'] = implode(
83
- ',',
84
- array(
85
- 'id',
86
- 'order_status',
87
- 'created',
88
- 'last_updated',
89
- 'items{id,retailer_id,product_id,quantity,price_per_unit,tax_details}',
90
- 'ship_by_date',
91
- 'merchant_order_id',
92
- 'channel',
93
- 'selected_shipping_option',
94
- 'shipping_address',
95
- 'estimated_payment_details',
96
- 'buyer_details',
97
- )
98
- );
99
- }
100
-
101
- $this->set_params( $params );
102
- }
103
-
104
-
105
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/API/Orders/Response.php DELETED
@@ -1,48 +0,0 @@
1
- <?php
2
- // phpcs:ignoreFile
3
- /**
4
- * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
5
- *
6
- * This source code is licensed under the license found in the
7
- * LICENSE file in the root directory of this source tree.
8
- *
9
- * @package FacebookCommerce
10
- */
11
-
12
- namespace WooCommerce\Facebook\API\Orders;
13
-
14
- defined( 'ABSPATH' ) or exit;
15
-
16
- use WooCommerce\Facebook\API;
17
-
18
- /**
19
- * Orders API list response object.
20
- *
21
- * @since 2.1.0
22
- */
23
- class Response extends API\Response {
24
-
25
-
26
- use API\Traits\Paginated_Response;
27
-
28
-
29
- /**
30
- * Gets an array of order objects from the response data.
31
- *
32
- * @since 2.1.0
33
- *
34
- * @return \WooCommerce\Facebook\API\Orders\Order[]
35
- */
36
- public function get_orders() {
37
-
38
- $orders = array();
39
-
40
- foreach ( $this->get_data() as $order_data ) {
41
- $orders[] = new Order( json_decode( json_encode( $order_data ), true ) );
42
- }
43
-
44
- return $orders;
45
- }
46
-
47
-
48
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/Admin.php CHANGED
@@ -13,7 +13,6 @@ namespace WooCommerce\Facebook;
13
 
14
  use WooCommerce\Facebook\Admin\Enhanced_Catalog_Attribute_Fields;
15
  use WooCommerce\Facebook\Framework\Helper;
16
- use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;
17
  use Automattic\WooCommerce\Utilities\OrderUtil;
18
 
19
  defined( 'ABSPATH' ) or exit;
13
 
14
  use WooCommerce\Facebook\Admin\Enhanced_Catalog_Attribute_Fields;
15
  use WooCommerce\Facebook\Framework\Helper;
 
16
  use Automattic\WooCommerce\Utilities\OrderUtil;
17
 
18
  defined( 'ABSPATH' ) or exit;
includes/Admin/Notes/SettingsMoved.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Facebook Menu Settings moved note.
4
+ *
5
+ * Adds a note to merchant's inbox about Facebook Menu being moved to Marketing menu.
6
+ *
7
+ * @package FacebookCommerce
8
+ */
9
+
10
+ namespace WooCommerce\Facebook\Admin\Notes;
11
+
12
+ defined( 'ABSPATH' ) || exit;
13
+
14
+ use \Automattic\WooCommerce\Admin\Notes\Note;
15
+ use \Automattic\WooCommerce\Admin\Notes\NoteTraits;
16
+
17
+ /**
18
+ * SettingsMoved class.
19
+ */
20
+ class SettingsMoved {
21
+ /**
22
+ * Note traits.
23
+ */
24
+ use NoteTraits;
25
+
26
+ /**
27
+ * Name of the note for use in the database.
28
+ */
29
+ const NOTE_NAME = 'facebook-for-woocommerce-settings-moved-to-marketing';
30
+
31
+ /**
32
+ * Checks if this note should be displayed.
33
+ *
34
+ * @return bool
35
+ */
36
+ public static function should_display() {
37
+ /**
38
+ * The Facebook menu was moved under Marketing menu in v2.2.0. Display this note
39
+ * only to users updating from a version prior to v2.2.0.
40
+ */
41
+ $should_display = false;
42
+ $last_event = facebook_for_woocommerce()->get_last_event_from_history();
43
+
44
+ if ( isset( $last_event['name'] ) && 'upgrade' === $last_event['name'] ) {
45
+ $last_version = $last_event['data']['from_version'];
46
+ if ( version_compare( $last_version, '2.2.0', '<' ) ) {
47
+ $should_display = true;
48
+ }
49
+ }
50
+
51
+ return $should_display;
52
+ }
53
+
54
+ /**
55
+ * Add or delete note depending on the conditions to display the note.
56
+ *
57
+ * @throws NotesUnavailableException Throws exception when notes are unavailable.
58
+ */
59
+ public static function possibly_add_or_delete_note() {
60
+ // Verify the conditions to display the note.
61
+ if ( self::should_display() ) {
62
+ self::possibly_add_note();
63
+ } elseif ( self::note_exists() ) {
64
+ self::possibly_delete_note();
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Get the note.
70
+ *
71
+ * @return Note
72
+ */
73
+ public static function get_note() {
74
+ $settings_url = facebook_for_woocommerce()->get_settings_url();
75
+ $content = esc_html__( 'Sync your products and reach customers across Facebook, Instagram, Messenger and WhatsApp through your Facebook plugin, which can be found at Marketing > Facebook.', 'facebook-for-woocommerce' );
76
+
77
+ $note = new Note();
78
+ $note->set_title( esc_html__( 'Facebook is now found under Marketing', 'facebook-for-woocommerce' ) );
79
+ $note->set_content( $content );
80
+ $note->set_content_data( (object) array() );
81
+ $note->set_type( Note::E_WC_ADMIN_NOTE_INFORMATIONAL );
82
+ $note->set_name( self::NOTE_NAME );
83
+ $note->set_source( 'facebook-for-woocommerce' );
84
+ $note->add_action( 'settings', esc_html__( 'Go to Facebook', 'facebook-for-woocommerce' ), $settings_url );
85
+ return $note;
86
+ }
87
+ }
includes/Admin/Product_Sync_Meta_Box.php CHANGED
@@ -52,7 +52,7 @@ class Product_Sync_Meta_Box {
52
 
53
  $fb_integration = facebook_for_woocommerce()->get_integration();
54
  $fb_product = new \WC_Facebook_Product( $post->ID );
55
- $fb_product_group_id = null;
56
  $should_sync = true;
57
  $no_sync_reason = '';
58
 
@@ -65,24 +65,28 @@ class Product_Sync_Meta_Box {
65
  }
66
  }
67
 
68
- if ( $should_sync || $fb_product->woo_product->is_type( 'variable' ) ) {
69
- $fb_product_group_id = $fb_integration->get_product_fbid( $fb_integration::FB_PRODUCT_GROUP_ID, $post->ID, $fb_product->woo_product );
 
 
 
 
70
  }
71
  ?>
72
  <span id="fb_metadata">
73
  <?php
74
 
75
- if ( $fb_product_group_id ) {
76
 
77
  ?>
78
 
79
  <?php echo esc_html__( 'Facebook ID:', 'facebook-for-woocommerce' ); ?>
80
- <a href="https://facebook.com/<?php echo esc_attr( $fb_product_group_id ); ?>" target="_blank"><?php echo esc_html( $fb_product_group_id ); ?></a>
81
 
82
  <?php if ( \WC_Facebookcommerce_Utils::is_variable_type( $fb_product->get_type() ) ) : ?>
83
 
84
  <?php
85
- $product_item_ids_by_variation_id = $fb_integration->get_variation_product_item_ids( $fb_product, $fb_product_group_id );
86
  if ( $product_item_ids_by_variation_id ) :
87
  ?>
88
 
52
 
53
  $fb_integration = facebook_for_woocommerce()->get_integration();
54
  $fb_product = new \WC_Facebook_Product( $post->ID );
55
+ $fb_product_id = null;
56
  $should_sync = true;
57
  $no_sync_reason = '';
58
 
65
  }
66
  }
67
 
68
+ if ( $should_sync ) {
69
+ if ( $fb_product->woo_product->is_type( 'variable' ) ) {
70
+ $fb_product_id = $fb_integration->get_product_fbid( $fb_integration::FB_PRODUCT_GROUP_ID, $post->ID, $fb_product->woo_product );
71
+ } else {
72
+ $fb_product_id = $fb_integration->get_product_fbid( $fb_integration::FB_PRODUCT_ITEM_ID, $post->ID, $fb_product->woo_product );
73
+ }
74
  }
75
  ?>
76
  <span id="fb_metadata">
77
  <?php
78
 
79
+ if ( $fb_product_id ) {
80
 
81
  ?>
82
 
83
  <?php echo esc_html__( 'Facebook ID:', 'facebook-for-woocommerce' ); ?>
84
+ <a href="https://facebook.com/<?php echo esc_attr( $fb_product_id ); ?>" target="_blank"><?php echo esc_html( $fb_product_id ); ?></a>
85
 
86
  <?php if ( \WC_Facebookcommerce_Utils::is_variable_type( $fb_product->get_type() ) ) : ?>
87
 
88
  <?php
89
+ $product_item_ids_by_variation_id = $fb_integration->get_variation_product_item_ids( $fb_product, $fb_product_id );
90
  if ( $product_item_ids_by_variation_id ) :
91
  ?>
92
 
includes/Admin/Settings_Screens/Advertise.php CHANGED
@@ -13,6 +13,7 @@ namespace WooCommerce\Facebook\Admin\Settings_Screens;
13
 
14
  defined( 'ABSPATH' ) or exit;
15
 
 
16
  use WooCommerce\Facebook\Locale;
17
  use WooCommerce\Facebook\Admin\Abstract_Settings_Screen;
18
 
@@ -84,7 +85,7 @@ class Advertise extends Abstract_Settings_Screen {
84
  appId : '<?php echo esc_js( $connection_handler->get_client_id() ); ?>',
85
  autoLogAppEvents : true,
86
  xfbml : true,
87
- version : 'v8.0', // Note: This expires on November 1 2022
88
  } );
89
  };
90
  </script>
13
 
14
  defined( 'ABSPATH' ) or exit;
15
 
16
+ use WooCommerce\Facebook\API;
17
  use WooCommerce\Facebook\Locale;
18
  use WooCommerce\Facebook\Admin\Abstract_Settings_Screen;
19
 
85
  appId : '<?php echo esc_js( $connection_handler->get_client_id() ); ?>',
86
  autoLogAppEvents : true,
87
  xfbml : true,
88
+ version : '<?php echo esc_js( API::API_VERSION )?>',
89
  } );
90
  };
91
  </script>
includes/Commerce.php CHANGED
@@ -25,20 +25,6 @@ class Commerce {
25
  const OPTION_GOOGLE_PRODUCT_CATEGORY_ID = 'wc_facebook_google_product_category_id';
26
 
27
 
28
- /** @var Commerce\Orders the orders handler */
29
- protected $orders;
30
-
31
-
32
- /**
33
- * Commerce handler constructor.
34
- *
35
- * @since 2.1.0
36
- */
37
- public function __construct() {
38
- $this->orders = new Commerce\Orders();
39
- }
40
-
41
-
42
  /**
43
  * Gets the plugin-level fallback Google product category ID.
44
  *
@@ -124,19 +110,4 @@ class Commerce {
124
  */
125
  return (bool) apply_filters( 'wc_facebook_commerce_is_connected', $connected, $this );
126
  }
127
-
128
-
129
- /**
130
- * Gets the orders handler instance.
131
- *
132
- * @since 2.1.0
133
- *
134
- * @return \WooCommerce\Facebook\Commerce\Orders
135
- */
136
- public function get_orders_handler() {
137
-
138
- return $this->orders;
139
- }
140
-
141
-
142
  }
25
  const OPTION_GOOGLE_PRODUCT_CATEGORY_ID = 'wc_facebook_google_product_category_id';
26
 
27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  /**
29
  * Gets the plugin-level fallback Google product category ID.
30
  *
110
  */
111
  return (bool) apply_filters( 'wc_facebook_commerce_is_connected', $connected, $this );
112
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  }
includes/Commerce/Orders.php DELETED
@@ -1,903 +0,0 @@
1
- <?php
2
- // phpcs:ignoreFile
3
- /**
4
- * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
5
- *
6
- * This source code is licensed under the license found in the
7
- * LICENSE file in the root directory of this source tree.
8
- *
9
- * @package FacebookCommerce
10
- */
11
-
12
- namespace WooCommerce\Facebook\Commerce;
13
-
14
- use WooCommerce\Facebook\API\Orders\Order;
15
- use WooCommerce\Facebook\Framework\Api\Exception as ApiException;
16
- use WooCommerce\Facebook\Framework\Plugin\Exception as PluginException;
17
- use WooCommerce\Facebook\Products;
18
- use WooCommerce\Facebook\Utilities;
19
-
20
- defined( 'ABSPATH' ) or exit;
21
-
22
- /**
23
- * General Commerce orders handler.
24
- *
25
- * @since 2.1.0
26
- */
27
- class Orders {
28
-
29
-
30
- /** @var string the fetch orders action */
31
- const ACTION_FETCH_ORDERS = 'wc_facebook_commerce_fetch_orders';
32
-
33
- /** @var string the meta key used to store the remote order ID */
34
- const REMOTE_ID_META_KEY = '_wc_facebook_commerce_remote_id';
35
-
36
- /** @var string the meta key used to store the email remarketing option */
37
- const EMAIL_REMARKETING_META_KEY = '_wc_facebook_commerce_email_remarketing';
38
-
39
- /** @var string buyer's remorse refund reason */
40
- const REFUND_REASON_BUYERS_REMORSE = 'BUYERS_REMORSE';
41
-
42
- /** @var string damaged goods refund reason */
43
- const REFUND_REASON_DAMAGED_GOODS = 'DAMAGED_GOODS';
44
-
45
- /** @var string not as described refund reason */
46
- const REFUND_REASON_NOT_AS_DESCRIBED = 'NOT_AS_DESCRIBED';
47
-
48
- /** @var string quality issue refund reason */
49
- const REFUND_REASON_QUALITY_ISSUE = 'QUALITY_ISSUE';
50
-
51
- /** @var string wrong item refund reason */
52
- const REFUND_REASON_WRONG_ITEM = 'WRONG_ITEM';
53
-
54
- /** @var string other refund reason */
55
- const REFUND_REASON_OTHER = 'REFUND_REASON_OTHER';
56
-
57
- /** @var string customer requested cancellation */
58
- const CANCEL_REASON_CUSTOMER_REQUESTED = 'CUSTOMER_REQUESTED';
59
-
60
- /** @var string out of stock cancellation */
61
- const CANCEL_REASON_OUT_OF_STOCK = 'OUT_OF_STOCK';
62
-
63
- /** @var string invalid address cancellation */
64
- const CANCEL_REASON_INVALID_ADDRESS = 'INVALID_ADDRESS';
65
-
66
- /** @var string suspicious order cancellation */
67
- const CANCEL_REASON_SUSPICIOUS_ORDER = 'SUSPICIOUS_ORDER';
68
-
69
- /** @var string other reason cancellation */
70
- const CANCEL_REASON_OTHER = 'CANCEL_REASON_OTHER';
71
-
72
-
73
- /**
74
- * Orders constructor.
75
- *
76
- * @since 2.1.0
77
- */
78
- public function __construct() {
79
- $this->add_hooks();
80
- }
81
-
82
-
83
- /**
84
- * Returns whether or not the order is a pending Commerce order.
85
- *
86
- * @since 2.1.0
87
- *
88
- * @param \WC_Order $order order object
89
- * @return bool
90
- */
91
- public static function is_order_pending( \WC_Order $order ) {
92
- return self::is_commerce_order( $order ) && 'pending' === $order->get_status();
93
- }
94
-
95
-
96
- /**
97
- * Returns whether or not the order is a Commerce order.
98
- *
99
- * @since 2.1.0
100
- *
101
- * @param \WC_Order $order order object
102
- * @return bool
103
- */
104
- public static function is_commerce_order( \WC_Order $order ) {
105
- return in_array( $order->get_created_via(), array( 'instagram', 'facebook' ), true );
106
- }
107
-
108
-
109
- /**
110
- * Finds a local order based on the Commerce ID stored in REMOTE_ID_META_KEY.
111
- *
112
- * @since 2.1.0
113
- *
114
- * @param string $remote_id Commerce order ID
115
- * @return \WC_Order|null
116
- */
117
- public function find_local_order( $remote_id ) {
118
-
119
- $orders = wc_get_orders(
120
- array(
121
- 'limit' => 1,
122
- 'status' => 'any',
123
- 'meta_key' => self::REMOTE_ID_META_KEY,
124
- 'meta_value' => $remote_id,
125
- )
126
- );
127
-
128
- return ! empty( $orders ) ? current( $orders ) : null;
129
- }
130
-
131
-
132
- /**
133
- * Creates a local WooCommerce order based on an Orders API order object.
134
- *
135
- * @since 2.1.0
136
- *
137
- * @param Order $remote_order Orders API order object
138
- * @return \WC_Order
139
- * @throws PluginException|\WC_Data_Exception
140
- */
141
- public function create_local_order( Order $remote_order ) {
142
-
143
- $local_order = new \WC_Order();
144
- $local_order->set_created_via( $remote_order->get_channel() );
145
- $local_order->set_status( 'pending' );
146
- $local_order->save();
147
-
148
- $local_order = $this->update_local_order( $remote_order, $local_order );
149
-
150
- return $local_order;
151
- }
152
-
153
-
154
- /**
155
- * Updates a local WooCommerce order based on an Orders API order object.
156
- *
157
- * @since 2.1.0
158
- *
159
- * @param Order $remote_order Orders API order object
160
- * @param \WC_Order $local_order local order object
161
- * @return \WC_Order
162
- * @throws PluginException|\WC_Data_Exception
163
- */
164
- public function update_local_order( Order $remote_order, \WC_Order $local_order ) {
165
-
166
- $total_items_tax = 0;
167
-
168
- // add/update items
169
- foreach ( $remote_order->get_items() as $item ) {
170
-
171
- $product = Products::get_product_by_fb_product_id( $item['product_id'] );
172
-
173
- if ( empty( $product ) ) {
174
- $product = Products::get_product_by_fb_retailer_id( $item['retailer_id'] );
175
- }
176
-
177
- if ( ! $product instanceof \WC_Product ) {
178
-
179
- // add a note and skip this item
180
- $local_order->add_order_note( "Product with retailer ID {$item['retailer_id']} not found" );
181
- continue;
182
- }
183
-
184
- $matching_wc_order_item = false;
185
-
186
- // check if the local order already has this item
187
- foreach ( $local_order->get_items() as $wc_order_item ) {
188
-
189
- if ( ! $wc_order_item instanceof \WC_Order_Item_Product ) {
190
- continue;
191
- }
192
-
193
- $order_item_product_id = $wc_order_item->get_variation_id() ?: $wc_order_item->get_product_id();
194
-
195
- if ( $product->get_id() === $order_item_product_id ) {
196
- $matching_wc_order_item = $wc_order_item;
197
- break;
198
- }
199
- }
200
-
201
- if ( empty( $matching_wc_order_item ) ) {
202
-
203
- $matching_wc_order_item = new \WC_Order_Item_Product();
204
- $matching_wc_order_item->set_product( $product );
205
-
206
- $local_order->add_item( $matching_wc_order_item );
207
- }
208
-
209
- $matching_wc_order_item->set_quantity( $item['quantity'] );
210
- $matching_wc_order_item->set_subtotal( $item['quantity'] * $item['price_per_unit']['amount'] );
211
- $matching_wc_order_item->set_total( $item['quantity'] * $item['price_per_unit']['amount'] );
212
- // we use the estimated_tax because the captured_tax represents the tax after the order/item has been shipped and we don't fulfill order at the line-item level
213
- $matching_wc_order_item->set_taxes(
214
- array(
215
- 'subtotal' => array( $item['tax_details']['estimated_tax']['amount'] ),
216
- 'total' => array( $item['tax_details']['estimated_tax']['amount'] ),
217
- )
218
- );
219
- $matching_wc_order_item->save();
220
-
221
- if ( ! empty( $item['tax_details']['estimated_tax']['amount'] ) ) {
222
-
223
- $total_items_tax += $item['tax_details']['estimated_tax']['amount'];
224
- }
225
- }
226
-
227
- // update information from selected_shipping_option
228
- $selected_shipping_option = $remote_order->get_selected_shipping_option();
229
-
230
- $matching_shipping_order_item = false;
231
-
232
- // check if the local order already has this item
233
- if ( ! empty( $shipping_order_items = $local_order->get_items( 'shipping' ) ) ) {
234
-
235
- /** @var \WC_Order_Item_Shipping $shipping_order_item */
236
- foreach ( $shipping_order_items as $shipping_order_item ) {
237
-
238
- if ( $selected_shipping_option['name'] === $shipping_order_item->get_method_title() ) {
239
- $matching_shipping_order_item = $shipping_order_item;
240
- }
241
- }
242
- }
243
-
244
- if ( empty( $matching_shipping_order_item ) ) {
245
-
246
- $matching_shipping_order_item = new \WC_Order_Item_Shipping();
247
- $matching_shipping_order_item->set_method_title( $selected_shipping_option['name'] );
248
-
249
- $local_order->add_item( $matching_shipping_order_item );
250
- }
251
-
252
- $matching_shipping_order_item->set_total( $selected_shipping_option['price']['amount'] );
253
- $matching_shipping_order_item->set_taxes(
254
- array(
255
- 'total' => array( $selected_shipping_option['calculated_tax']['amount'] ),
256
- )
257
- );
258
- $matching_shipping_order_item->save();
259
-
260
- // add tax item
261
- $matching_tax_order_item = false;
262
-
263
- // check if the local order already has a tax item item
264
- if ( ! empty( $tax_order_items = $local_order->get_items( 'tax' ) ) ) {
265
- $matching_tax_order_item = current( $tax_order_items );
266
- }
267
-
268
- if ( empty( $matching_tax_order_item ) ) {
269
-
270
- $matching_tax_order_item = new \WC_Order_Item_Tax();
271
- $local_order->add_item( $matching_tax_order_item );
272
- }
273
-
274
- $matching_tax_order_item->set_tax_total( $total_items_tax );
275
- $matching_tax_order_item->set_shipping_tax_total( $selected_shipping_option['calculated_tax']['amount'] );
276
- $matching_tax_order_item->save();
277
-
278
- $local_order->set_shipping_total( $selected_shipping_option['price']['amount'] );
279
- $local_order->set_shipping_tax( $selected_shipping_option['calculated_tax']['amount'] );
280
-
281
- // update information from shipping_address
282
- $shipping_address = $remote_order->get_shipping_address();
283
-
284
- if ( ! empty( $shipping_address['name'] ) ) {
285
-
286
- if ( strpos( $shipping_address['name'], ' ' ) !== false ) {
287
-
288
- list( $first_name, $last_name ) = explode( ' ', $shipping_address['name'], 2 );
289
- $local_order->set_shipping_first_name( $first_name );
290
- $local_order->set_shipping_last_name( $last_name );
291
-
292
- } else {
293
-
294
- $local_order->set_shipping_last_name( $shipping_address['name'] );
295
- }
296
- }
297
-
298
- if ( ! empty( $shipping_address['street1'] ) ) {
299
- $local_order->set_shipping_address_1( $shipping_address['street1'] );
300
- }
301
-
302
- if ( ! empty( $shipping_address['street2'] ) ) {
303
- $local_order->set_shipping_address_2( $shipping_address['street2'] );
304
- }
305
-
306
- if ( ! empty( $shipping_address['city'] ) ) {
307
- $local_order->set_shipping_city( $shipping_address['city'] );
308
- }
309
-
310
- if ( ! empty( $shipping_address['state'] ) ) {
311
- $local_order->set_shipping_state( $shipping_address['state'] );
312
- }
313
-
314
- if ( ! empty( $shipping_address['postal_code'] ) ) {
315
- $local_order->set_shipping_postcode( $shipping_address['postal_code'] );
316
- }
317
-
318
- if ( ! empty( $shipping_address['country'] ) ) {
319
- $local_order->set_shipping_country( $shipping_address['country'] );
320
- }
321
-
322
- // update information from estimated_payment_details
323
- $estimated_payment_details = $remote_order->get_estimated_payment_details();
324
-
325
- // we do not use subtotal values from the API because WC calculates them on the fly based on the items
326
- $local_order->set_total( $estimated_payment_details['total_amount']['amount'] );
327
- $local_order->set_currency( $estimated_payment_details['total_amount']['currency'] );
328
-
329
- // update information from buyer_details
330
- $buyer_details = $remote_order->get_buyer_details();
331
-
332
- if ( ! empty( $buyer_details ) ) {
333
-
334
- if ( ! empty( $buyer_details['name'] ) ) {
335
-
336
- if ( strpos( $buyer_details['name'], ' ' ) !== false ) {
337
-
338
- list( $first_name, $last_name ) = explode( ' ', $buyer_details['name'], 2 );
339
- $local_order->set_billing_first_name( $first_name );
340
- $local_order->set_billing_last_name( $last_name );
341
-
342
- } else {
343
-
344
- $local_order->set_billing_last_name( $buyer_details['name'] );
345
- }
346
- }
347
-
348
- if ( ! empty( $buyer_details['email'] ) ) {
349
- $local_order->set_billing_email( $buyer_details['email'] );
350
- }
351
-
352
- $local_order->update_meta_data( self::EMAIL_REMARKETING_META_KEY, wc_bool_to_string( $buyer_details['email_remarketing_option'] ) );
353
- }
354
-
355
- // set remote ID
356
- $local_order->update_meta_data( self::REMOTE_ID_META_KEY, $remote_order->get_id() );
357
-
358
- // always reduce stock levels
359
- wc_reduce_stock_levels( $local_order );
360
-
361
- $local_order->save();
362
-
363
- return $local_order;
364
- }
365
-
366
-
367
- /**
368
- * Updates WooCommerce’s Orders by fetching orders from the API and either creating or updating local orders.
369
- *
370
- * @since 2.1.0
371
- */
372
- public function update_local_orders() {
373
- // sanity check for connection status
374
- if ( ! facebook_for_woocommerce()->get_commerce_handler()->is_connected() ) {
375
- return;
376
- }
377
-
378
- $page_id = facebook_for_woocommerce()->get_integration()->get_facebook_page_id();
379
-
380
- try {
381
-
382
- $response = facebook_for_woocommerce()->get_api( facebook_for_woocommerce()->get_connection_handler()->get_page_access_token() )->get_new_orders( $page_id );
383
-
384
- } catch ( ApiException $exception ) {
385
-
386
- facebook_for_woocommerce()->log( 'Error fetching Commerce orders from the Orders API: ' . $exception->getMessage() );
387
-
388
- return;
389
- }
390
-
391
- $remote_orders = $response->get_orders();
392
-
393
- foreach ( $remote_orders as $remote_order ) {
394
-
395
- $local_order = $this->find_local_order( $remote_order->get_id() );
396
-
397
- try {
398
-
399
- if ( empty( $local_order ) ) {
400
- $local_order = $this->create_local_order( $remote_order );
401
- } else {
402
- $local_order = $this->update_local_order( $remote_order, $local_order );
403
- }
404
- } catch ( \Exception $exception ) {
405
-
406
- if ( ! empty( $local_order ) ) {
407
- // add note to order
408
- $local_order->add_order_note( 'Error updating local order from Commerce order from the Orders API: ' . $exception->getMessage() );
409
- } else {
410
- facebook_for_woocommerce()->log( 'Error creating local order from Commerce order from the Orders API: ' . $exception->getMessage() );
411
- }
412
-
413
- continue;
414
- }
415
-
416
- if ( ! empty( $local_order ) && Order::STATUS_CREATED === $remote_order->get_status() ) {
417
-
418
- // acknowledge the order
419
- try {
420
-
421
- facebook_for_woocommerce()->get_api( facebook_for_woocommerce()->get_connection_handler()->get_page_access_token() )->acknowledge_order( $remote_order->get_id(), $local_order->get_id() );
422
-
423
- $local_order->set_status( 'processing' );
424
-
425
- /* translators: Placeholders: %1$s - order remote id, %2$s - order created by */
426
- $local_order->add_order_note(
427
- sprintf(
428
- __( 'Order %1$s paid in %2$s', 'facebook-for-woocommerce' ),
429
- $remote_order->get_id(),
430
- ucfirst( $remote_order->get_channel() )
431
- )
432
- );
433
-
434
- } catch ( ApiException $exception ) {
435
-
436
- $local_order->add_order_note( 'Error acknowledging the order: ' . $exception->getMessage() );
437
-
438
- // if we have a clear indication that the order was not found, cancel it locally
439
- if ( 803 === (int) $exception->getCode() ) {
440
- $local_order->set_status( 'cancelled' );
441
- }
442
- }
443
-
444
- $local_order->save();
445
- }
446
- }
447
-
448
- // update any local orders that have since been cancelled on Facebook
449
- $this->update_cancelled_orders();
450
- }
451
-
452
-
453
- /**
454
- * Updates any local orders that have since been cancelled on Facebook.
455
- *
456
- * @since 2.1.0
457
- */
458
- public function update_cancelled_orders() {
459
-
460
- $page_id = facebook_for_woocommerce()->get_integration()->get_facebook_page_id();
461
-
462
- try {
463
-
464
- $response = facebook_for_woocommerce()->get_api( facebook_for_woocommerce()->get_connection_handler()->get_page_access_token() )->get_cancelled_orders( $page_id );
465
-
466
- } catch ( ApiException $exception ) {
467
-
468
- facebook_for_woocommerce()->log( 'Error fetching Commerce orders from the Orders API: ' . $exception->getMessage() );
469
-
470
- return;
471
- }
472
-
473
- foreach ( $response->get_orders() as $remote_order ) {
474
-
475
- $local_order = $this->find_local_order( $remote_order->get_id() );
476
-
477
- if ( ! $local_order instanceof \WC_Order || 'cancelled' === $local_order->get_status() ) {
478
- continue;
479
- }
480
-
481
- $local_order->set_status( 'cancelled' );
482
- $local_order->save();
483
-
484
- wc_increase_stock_levels( $local_order );
485
- }
486
- }
487
-
488
-
489
- /**
490
- * Frequency in seconds that orders are updated.
491
- *
492
- * @since 2.1.0
493
- *
494
- * @return int
495
- */
496
- public function get_order_update_interval() {
497
-
498
- $default_interval = 5 * MINUTE_IN_SECONDS;
499
-
500
- /**
501
- * Filters the interval between querying Facebook for new or updated orders.
502
- *
503
- * @since 2.1.0
504
- *
505
- * @param int $interval interval in seconds. Defaults to 5 minutes, and the minimum interval is 120 seconds.
506
- */
507
- $interval = apply_filters( 'wc_facebook_commerce_order_update_interval', $default_interval );
508
-
509
- // if given a valid number, ensure it's 120 seconds at a minimum
510
- if ( is_numeric( $interval ) ) {
511
- $interval = max( 2 * MINUTE_IN_SECONDS, $interval );
512
- } else {
513
- $interval = $default_interval; // invalid values should get the default
514
- }
515
-
516
- return $interval;
517
- }
518
-
519
-
520
- /**
521
- * Schedules a recurring ACTION_FETCH_ORDERS action, if not already scheduled.
522
- *
523
- * @internal
524
- *
525
- * @since 2.1.0
526
- */
527
- public function schedule_local_orders_update() {
528
- if ( facebook_for_woocommerce()->get_commerce_handler()->is_connected() && false === as_next_scheduled_action( self::ACTION_FETCH_ORDERS, array(), \WC_Facebookcommerce::PLUGIN_ID ) ) {
529
-
530
- $interval = $this->get_order_update_interval();
531
-
532
- as_schedule_recurring_action( time() + $interval, $interval, self::ACTION_FETCH_ORDERS, array(), \WC_Facebookcommerce::PLUGIN_ID );
533
- }
534
- }
535
-
536
-
537
- /**
538
- * Adds the necessary action & filter hooks.
539
- *
540
- * @since 2.1.0
541
- */
542
- public function add_hooks() {
543
-
544
- // schedule a recurring ACTION_FETCH_ORDERS action, if not already scheduled
545
- add_action( 'init', array( $this, 'schedule_local_orders_update' ) );
546
-
547
- add_action( self::ACTION_FETCH_ORDERS, array( $this, 'update_local_orders' ) );
548
-
549
- // prevent sending emails for Commerce orders
550
- add_action( 'woocommerce_email_enabled_customer_completed_order', array( $this, 'maybe_stop_order_email' ), 10, 2 );
551
- add_action( 'woocommerce_email_enabled_customer_processing_order', array( $this, 'maybe_stop_order_email' ), 10, 2 );
552
- add_action( 'woocommerce_email_enabled_customer_refunded_order', array( $this, 'maybe_stop_order_email' ), 10, 2 );
553
- add_action( 'woocommerce_email_enabled_customer_partially_refunded_order', array( $this, 'maybe_stop_order_email' ), 10, 2 );
554
- }
555
-
556
-
557
- /**
558
- * Fulfills an order via API.
559
- *
560
- * In addition to the exceptions we throw for missing data, the API request will also fail if:
561
- * - The stored remote ID is invalid
562
- * - The order has an item with a retailer ID that was not originally part of the order
563
- * - An item has a different quantity than what was originally ordered
564
- * - The remote order was already fulfilled
565
- *
566
- * @since 2.1.0
567
- *
568
- * @param \WC_Order $order order object
569
- * @param string $tracking_number shipping tracking number
570
- * @param string $carrier shipping carrier
571
- * @throws PluginException
572
- */
573
- public function fulfill_order( \WC_Order $order, $tracking_number, $carrier ) {
574
-
575
- try {
576
-
577
- $remote_id = $order->get_meta( self::REMOTE_ID_META_KEY );
578
-
579
- if ( ! $remote_id ) {
580
- throw new PluginException( __( 'Remote ID not found.', 'facebook-for-woocommerce' ) );
581
- }
582
-
583
- $shipment_utilities = new Utilities\Shipment();
584
-
585
- if ( ! $shipment_utilities->is_valid_carrier( $carrier ) ) {
586
- /** translators: Placeholders: %s - shipping carrier code */
587
- throw new PluginException( sprintf( __( '%s is not a valid shipping carrier code.', 'facebook-for-woocommerce' ), $carrier ) );
588
- }
589
-
590
- $items = array();
591
-
592
- /** @var \WC_Order_Item_Product $item */
593
- foreach ( $order->get_items() as $item ) {
594
-
595
- if ( $product = $item->get_product() ) {
596
-
597
- $items[] = array(
598
- 'retailer_id' => \WC_Facebookcommerce_Utils::get_fb_retailer_id( $product ),
599
- 'quantity' => $item->get_quantity(),
600
- );
601
- }
602
- }
603
-
604
- if ( empty( $items ) ) {
605
- throw new PluginException( __( 'No valid Facebook products were found.', 'facebook-for-woocommerce' ) );
606
- }
607
-
608
- $fulfillment_data = array(
609
- 'items' => $items,
610
- 'tracking_info' => array(
611
- 'carrier' => $carrier,
612
- 'tracking_number' => $tracking_number,
613
- ),
614
- );
615
-
616
- $plugin = facebook_for_woocommerce();
617
-
618
- $plugin->get_api( $plugin->get_connection_handler()->get_page_access_token() )->fulfill_order( $remote_id, $fulfillment_data );
619
-
620
- $order->add_order_note(
621
- sprintf(
622
- /* translators: Placeholder: %s - sales channel name, like Facebook or Instagram */
623
- __( '%s order fulfilled.', 'facebook-for-woocommerce' ),
624
- ucfirst( $order->get_created_via() )
625
- )
626
- );
627
-
628
- } catch ( PluginException $exception ) {
629
-
630
- $order->add_order_note(
631
- sprintf(
632
- /* translators: Placeholders: %1$s - sales channel name, like Facebook or Instagram, %2$s - error message */
633
- __( '%1$s order could not be fulfilled. %2$s', 'facebook-for-woocommerce' ),
634
- ucfirst( $order->get_created_via() ),
635
- $exception->getMessage()
636
- )
637
- );
638
-
639
- throw $exception;
640
- }
641
- }
642
-
643
-
644
- /**
645
- * Refunds an order.
646
- *
647
- * @since 2.1.0
648
- *
649
- * @param \WC_Order_Refund $refund order refund object
650
- * @param string $reason_code refund reason code
651
- * @throws PluginException
652
- */
653
- public function add_order_refund( \WC_Order_Refund $refund, $reason_code ) {
654
-
655
- try {
656
- $plugin = facebook_for_woocommerce();
657
-
658
- $api = $plugin->get_api( $plugin->get_connection_handler()->get_page_access_token() );
659
-
660
- $valid_reason_codes = array(
661
- self::REFUND_REASON_BUYERS_REMORSE,
662
- self::REFUND_REASON_DAMAGED_GOODS,
663
- self::REFUND_REASON_NOT_AS_DESCRIBED,
664
- self::REFUND_REASON_QUALITY_ISSUE,
665
- self::REFUND_REASON_OTHER,
666
- self::REFUND_REASON_WRONG_ITEM,
667
- );
668
-
669
- if ( ! in_array( $reason_code, $valid_reason_codes, true ) ) {
670
- $reason_code = self::REFUND_REASON_OTHER;
671
- }
672
-
673
- $parent_order = wc_get_order( $refund->get_parent_id() );
674
-
675
- if ( ! $parent_order instanceof \WC_Order ) {
676
- throw new PluginException( __( 'Parent order not found.', 'facebook-for-woocommerce' ) );
677
- }
678
-
679
- $remote_id = $parent_order->get_meta( self::REMOTE_ID_META_KEY );
680
-
681
- if ( ! $remote_id ) {
682
- throw new PluginException( __( 'Remote ID for parent order not found.', 'facebook-for-woocommerce' ) );
683
- }
684
-
685
- $refund_data = array(
686
- 'reason_code' => $reason_code,
687
- );
688
-
689
- if ( ! empty( $reason_text = $refund->get_reason() ) ) {
690
- $refund_data['reason_text'] = $reason_text;
691
- }
692
-
693
- // only send items for partial refunds
694
- if ( $parent_order->get_total() - $refund->get_amount() > 0 ) {
695
- $refund_data['items'] = $this->get_refund_items( $refund );
696
- }
697
-
698
- if ( ! empty( $refund->get_shipping_total() ) ) {
699
-
700
- $refund_data['shipping'] = array(
701
- 'shipping_refund' => array(
702
- 'amount' => abs( $refund->get_shipping_total() ),
703
- 'currency' => $refund->get_currency(),
704
- ),
705
- );
706
- }
707
-
708
- $api->add_order_refund( $remote_id, $refund_data );
709
-
710
- $parent_order->add_order_note(
711
- sprintf(
712
- /* translators: Placeholder: %s - sales channel name, like Facebook or Instagram */
713
- __( 'Order refunded on %s.', 'facebook-for-woocommerce' ),
714
- ucfirst( $parent_order->get_created_via() )
715
- )
716
- );
717
-
718
- } catch ( PluginException $exception ) {
719
-
720
- if ( ! empty( $parent_order ) && $parent_order instanceof \WC_Order ) {
721
-
722
- $parent_order->add_order_note(
723
- sprintf(
724
- /* translators: Placeholders: %1$s - sales channel name, like Facebook or Instagram, %2$s - error message */
725
- __( 'Could not refund %1$s order: %2$s', 'facebook-for-woocommerce' ),
726
- ucfirst( $parent_order->get_created_via() ),
727
- $exception->getMessage()
728
- )
729
- );
730
-
731
- } else {
732
-
733
- facebook_for_woocommerce()->log( "Could not refund remote order for order refund {$refund->get_id()}: {$exception->getMessage()}" );
734
- }
735
-
736
- // re-throw the exception so the error halts refund creation
737
- throw $exception;
738
- }
739
- }
740
-
741
-
742
- /**
743
- * Gets the Facebook items from the given refund.
744
- *
745
- * @since 2.1.0
746
- *
747
- * @param \WC_Order_Refund $refund refund object
748
- * @return array
749
- * @throws PluginException
750
- */
751
- private function get_refund_items( \WC_Order_Refund $refund ) {
752
-
753
- $items = array();
754
-
755
- /** @var \WC_Order_Item_Product $item */
756
- foreach ( $refund->get_items() as $item ) {
757
-
758
- if ( $product = $item->get_product() ) {
759
-
760
- $refund_item = array(
761
- 'retailer_id' => \WC_Facebookcommerce_Utils::get_fb_retailer_id( $product ),
762
- );
763
-
764
- if ( ! empty( $item->get_quantity() ) ) {
765
-
766
- $refund_item['item_refund_quantity'] = abs( $item->get_quantity() );
767
-
768
- } else {
769
-
770
- $refund_item['item_refund_amount'] = array(
771
- 'amount' => abs( $item->get_total() ),
772
- 'currency' => $refund->get_currency(),
773
- );
774
- }
775
-
776
- $items[] = $refund_item;
777
- }
778
- }
779
-
780
- if ( empty( $items ) ) {
781
- throw new PluginException( __( 'No valid Facebook products were found.', 'facebook-for-woocommerce' ) );
782
- }
783
-
784
- return $items;
785
- }
786
-
787
-
788
- /**
789
- * Cancels an order.
790
- *
791
- * @since 2.1.0
792
- *
793
- * @param \WC_Order $order order object
794
- * @param string $reason_code cancellation reason code
795
- * @throws PluginException
796
- */
797
- public function cancel_order( \WC_Order $order, $reason_code ) {
798
-
799
- try {
800
-
801
- $plugin = facebook_for_woocommerce();
802
-
803
- $api = $plugin->get_api( $plugin->get_connection_handler()->get_page_access_token() );
804
-
805
- $valid_reason_codes = array_keys( $this->get_cancellation_reasons() );
806
-
807
- if ( ! in_array( $reason_code, $valid_reason_codes, true ) ) {
808
- $reason_code = self::CANCEL_REASON_OTHER;
809
- }
810
-
811
- $remote_id = $order->get_meta( self::REMOTE_ID_META_KEY );
812
-
813
- if ( ! $remote_id ) {
814
- throw new PluginException( __( 'Remote ID not found.', 'facebook-for-woocommerce' ) );
815
- }
816
-
817
- $api->cancel_order( $remote_id, $reason_code );
818
-
819
- $order->add_order_note(
820
- sprintf(
821
- /* translators: Placeholder: %s - sales channel name, like Facebook or Instagram */
822
- __( '%s order cancelled.', 'facebook-for-woocommerce' ),
823
- ucfirst( $order->get_created_via() )
824
- )
825
- );
826
-
827
- } catch ( PluginException $exception ) {
828
-
829
- $order->add_order_note(
830
- sprintf(
831
- /* translators: Placeholders: %1$s - sales channel name, like Facebook or Instagram, %2$s - error message */
832
- __( '%1$s order could not be cancelled. %2$s', 'facebook-for-woocommerce' ),
833
- ucfirst( $order->get_created_via() ),
834
- $exception->getMessage()
835
- )
836
- );
837
-
838
- throw $exception;
839
- }
840
- }
841
-
842
-
843
- /**
844
- * Gets the valid cancellation reasons.
845
- *
846
- * @since 2.1.0
847
- *
848
- * @return array key-value array with codes and their labels
849
- */
850
- public function get_cancellation_reasons() {
851
-
852
- return array(
853
-
854
- self::CANCEL_REASON_CUSTOMER_REQUESTED => __( 'Customer requested cancellation', 'facebook-for-woocommerce' ),
855
- self::CANCEL_REASON_OUT_OF_STOCK => __( 'Product(s) are out of stock', 'facebook-for-woocommerce' ),
856
- self::CANCEL_REASON_INVALID_ADDRESS => __( 'Customer address is invalid', 'facebook-for-woocommerce' ),
857
- self::CANCEL_REASON_SUSPICIOUS_ORDER => __( 'Suspicious order', 'facebook-for-woocommerce' ),
858
- self::CANCEL_REASON_OTHER => __( 'Other', 'facebook-for-woocommerce' ),
859
- );
860
- }
861
-
862
-
863
- /**
864
- * Prevents sending emails for Commerce orders.
865
- *
866
- * @internal
867
- *
868
- * @since 2.1.0
869
- *
870
- * @param bool $is_enabled whether the email is enabled in the first place
871
- * @param \WC_Order $order order object
872
- * @return bool
873
- */
874
- public function maybe_stop_order_email( $is_enabled, $order ) {
875
-
876
- // will decide whether to allow $is_enabled to be filtered
877
- $is_previously_enabled = $is_enabled;
878
-
879
- // checks whether or not the order is a Commerce order
880
- $is_commerce_order = $order instanceof \WC_Order && self::is_commerce_order( $order );
881
-
882
- // decides whether to disable or to keep emails enabled
883
- $is_enabled = $is_enabled && ! $is_commerce_order;
884
-
885
- if ( $is_previously_enabled && $is_commerce_order ) {
886
-
887
- /**
888
- * Filters the flag used to determine whether the email is enabled.
889
- *
890
- * @since 2.1.0
891
- *
892
- * @param bool $is_enabled whether the email is enabled
893
- * @param \WC_Order $order order object
894
- * @param Orders $this admin orders instance
895
- */
896
- $is_enabled = (bool) apply_filters( 'wc_facebook_commerce_send_woocommerce_emails', $is_enabled, $order, $this );
897
- }
898
-
899
- return $is_enabled;
900
- }
901
-
902
-
903
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/Handlers/Connection.php CHANGED
@@ -334,15 +334,23 @@ class Connection {
334
  }
335
  try {
336
  $response = facebook_for_woocommerce()->get_api()->get_user();
337
- $response = facebook_for_woocommerce()->get_api()->delete_user_permission( $response->get_id(), 'manage_business_extension' );
338
- $this->disconnect();
339
- facebook_for_woocommerce()->get_message_handler()->add_message( __( 'Disconnection successful.', 'facebook-for-woocommerce' ) );
 
 
 
 
340
  } catch ( ApiException $exception ) {
341
- facebook_for_woocommerce()->log( sprintf( 'An error occurred during disconnection: %s. Your Facebook connection settings have been reset.', $exception->getMessage() ) );
 
 
 
342
  $this->disconnect();
 
 
 
343
  }
344
- wp_safe_redirect( facebook_for_woocommerce()->get_settings_url() );
345
- exit;
346
  }
347
 
348
 
@@ -353,15 +361,16 @@ class Connection {
353
  *
354
  * @since 2.0.0
355
  */
356
- private function disconnect() {
357
  $this->update_access_token( '' );
 
358
  $this->update_merchant_access_token( '' );
359
  $this->update_system_user_id( '' );
360
  $this->update_business_manager_id( '' );
361
  $this->update_ad_account_id( '' );
362
  $this->update_instagram_business_id( '' );
363
  $this->update_commerce_merchant_settings_id( '' );
364
- $this->update_external_business_id('');
365
  update_option( \WC_Facebookcommerce_Integration::SETTING_FACEBOOK_PAGE_ID, '' );
366
  update_option( \WC_Facebookcommerce_Integration::SETTING_FACEBOOK_PIXEL_ID, '' );
367
  facebook_for_woocommerce()->get_integration()->update_product_catalog_id( '' );
334
  }
335
  try {
336
  $response = facebook_for_woocommerce()->get_api()->get_user();
337
+ $id = $response->get_id();
338
+ if ( null !== $id ) {
339
+ $response = facebook_for_woocommerce()->get_api()->delete_user_permission( (string) $id , 'manage_business_extension' );
340
+ facebook_for_woocommerce()->get_message_handler()->add_message( __( 'Disconnection successful.', 'facebook-for-woocommerce' ) );
341
+ } else {
342
+ facebook_for_woocommerce()->log( 'User id not found for the disconnection procedure, connection will be reset.' );
343
+ }
344
  } catch ( ApiException $exception ) {
345
+ facebook_for_woocommerce()->log( sprintf( 'An error occurred during disconnection: %s.', $exception->getMessage() ) );
346
+ } catch ( \Exception $exception ) {
347
+ facebook_for_woocommerce()->log( sprintf( 'Internal error occurred during disconnection: %s.', $exception->getMessage() ) );
348
+ } finally {
349
  $this->disconnect();
350
+ facebook_for_woocommerce()->log( sprintf( 'Your Facebook connection settings have been reset.' ) );
351
+ wp_safe_redirect( facebook_for_woocommerce()->get_settings_url() );
352
+ exit;
353
  }
 
 
354
  }
355
 
356
 
361
  *
362
  * @since 2.0.0
363
  */
364
+ public function disconnect() {
365
  $this->update_access_token( '' );
366
+ $this->update_page_access_token( '' );
367
  $this->update_merchant_access_token( '' );
368
  $this->update_system_user_id( '' );
369
  $this->update_business_manager_id( '' );
370
  $this->update_ad_account_id( '' );
371
  $this->update_instagram_business_id( '' );
372
  $this->update_commerce_merchant_settings_id( '' );
373
+ $this->update_external_business_id( '' );
374
  update_option( \WC_Facebookcommerce_Integration::SETTING_FACEBOOK_PAGE_ID, '' );
375
  update_option( \WC_Facebookcommerce_Integration::SETTING_FACEBOOK_PIXEL_ID, '' );
376
  facebook_for_woocommerce()->get_integration()->update_product_catalog_id( '' );
includes/Jobs/DeleteProductsFromFBCatalog.php ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Facebook\Jobs;
4
+
5
+ use Automattic\WooCommerce\ActionSchedulerJobFramework\Utilities\BatchQueryOffset;
6
+ use Exception;
7
+ use WC_Facebookcommerce;
8
+ use WC_Product;
9
+
10
+ defined( 'ABSPATH' ) || exit;
11
+
12
+ /**
13
+ * Class ResetAllProductsFBSettings
14
+ *
15
+ * @since 3.0.5
16
+ */
17
+ class DeleteProductsFromFBCatalog extends AbstractChainedJob {
18
+
19
+ use BatchQueryOffset, LoggingTrait;
20
+
21
+ /**
22
+ * Called before starting the job.
23
+ */
24
+ protected function handle_start() {
25
+ $this->log( 'Starting job to delete all product FB data.' );
26
+ }
27
+
28
+ /**
29
+ * Called after the finishing the job.
30
+ */
31
+ protected function handle_end() {
32
+ $this->log( 'Finished job to delete all product FB data.' );
33
+ }
34
+
35
+ /**
36
+ * Get a set of items for the batch.
37
+ *
38
+ * NOTE: when using an OFFSET based query to retrieve items it's recommended to order by the item ID while
39
+ * ASCENDING. This is so that any newly added items will not disrupt the query offset.
40
+ *
41
+ * @param int $batch_number The batch number increments for each new batch in the job cycle.
42
+ * @param array $args The args for the job.
43
+ *
44
+ * @throws Exception On error. The failure will be logged by Action Scheduler and the job chain will stop.
45
+ */
46
+ protected function get_items_for_batch( int $batch_number, array $args ): array {
47
+ global $wpdb;
48
+
49
+ $products = get_posts(
50
+ [
51
+ 'post_type' => 'product',
52
+ 'post_status' => 'any',
53
+ 'fields' => 'ids',
54
+ 'offset' => $this->get_query_offset( $batch_number ),
55
+ 'posts_per_page' => $this->get_batch_size(),
56
+ ]
57
+ );
58
+
59
+ return array_map( 'intval', $products );
60
+
61
+ }
62
+
63
+ /**
64
+ * Processes a batch of items.
65
+ *
66
+ * @since 3.0.5
67
+ *
68
+ * @param array $items The items of the current batch.
69
+ * @param array $args The args for the job.
70
+ *
71
+ * @throws Exception On error. The failure will be logged by Action Scheduler and the job chain will stop.
72
+ */
73
+ protected function process_items( array $items, array $args ) {
74
+ $integration = facebook_for_woocommerce()->get_integration();
75
+ foreach ( $items as $product_id ) {
76
+ $product = wc_get_product( $product_id );
77
+ // check if variable product
78
+ if ( $product->is_type( 'variable' ) ) {
79
+ $integration->delete_product_group( $product_id );
80
+ } else {
81
+ $integration->delete_product_item( $product_id );
82
+ }
83
+
84
+ // Reset product.
85
+ $integration->reset_single_product( $product_id );
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Empty function to satisfy parent class requirements.
91
+ * We don't use it because we are processing the whole batch at once in process_items.
92
+ *
93
+ * @since 3.0.5
94
+ *
95
+ * @param mixed $item The items of the current batch.
96
+ * @param array $args The args for the job.
97
+ *
98
+ * @return void
99
+ */
100
+ protected function process_item( $item, array $args ) {}
101
+
102
+ /**
103
+ * Get the name/slug of the job.
104
+ *
105
+ * @return string
106
+ */
107
+ public function get_name(): string {
108
+ return 'delete_products_from_FB_catalog';
109
+ }
110
+
111
+ /**
112
+ * Get the name/slug of the plugin that owns the job.
113
+ *
114
+ * @return string
115
+ */
116
+ public function get_plugin_name(): string {
117
+ return WC_Facebookcommerce::PLUGIN_ID;
118
+ }
119
+
120
+ /**
121
+ * Get the job's batch size.
122
+ *
123
+ * @return int
124
+ */
125
+ public function get_batch_size(): int {
126
+ return 25;
127
+ }
128
+
129
+ }
includes/Jobs/JobManager.php CHANGED
@@ -24,6 +24,16 @@ class JobManager {
24
  */
25
  public $cleanup_skyverge_job_options;
26
 
 
 
 
 
 
 
 
 
 
 
27
  /**
28
  * Instantiate and init all jobs for the plugin.
29
  */
@@ -35,6 +45,12 @@ class JobManager {
35
 
36
  $this->cleanup_skyverge_job_options = new CleanupSkyvergeFrameworkJobOptions();
37
  $this->cleanup_skyverge_job_options->init();
 
 
 
 
 
 
38
  }
39
 
40
  }
24
  */
25
  public $cleanup_skyverge_job_options;
26
 
27
+ /**
28
+ * @var ResetAllProductsFBSettings
29
+ */
30
+ public $reset_all_product_fb_settings;
31
+
32
+ /**
33
+ * @var DeleteProductsFromFBCatalog
34
+ */
35
+ public $delete_all_products;
36
+
37
  /**
38
  * Instantiate and init all jobs for the plugin.
39
  */
45
 
46
  $this->cleanup_skyverge_job_options = new CleanupSkyvergeFrameworkJobOptions();
47
  $this->cleanup_skyverge_job_options->init();
48
+
49
+ $this->reset_all_product_fb_settings = new ResetAllProductsFBSettings( $action_scheduler_proxy);
50
+ $this->reset_all_product_fb_settings->init();
51
+
52
+ $this->delete_all_products = new DeleteProductsFromFBCatalog( $action_scheduler_proxy);
53
+ $this->delete_all_products->init();
54
  }
55
 
56
  }
includes/Jobs/ResetAllProductsFBSettings.php ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Facebook\Jobs;
4
+
5
+ use Automattic\WooCommerce\ActionSchedulerJobFramework\Utilities\BatchQueryOffset;
6
+ use Exception;
7
+ use WC_Facebookcommerce;
8
+ use WC_Product;
9
+
10
+ defined( 'ABSPATH' ) || exit;
11
+
12
+ /**
13
+ * Class ResetAllProductsFBSettings
14
+ *
15
+ * @since 3.0.5
16
+ */
17
+ class ResetAllProductsFBSettings extends AbstractChainedJob {
18
+
19
+ use BatchQueryOffset, LoggingTrait;
20
+
21
+ /**
22
+ * Called before starting the job.
23
+ */
24
+ protected function handle_start() {
25
+ $this->log( 'Starting job to reset all product FB data.' );
26
+ }
27
+
28
+ /**
29
+ * Called after the finishing the job.
30
+ */
31
+ protected function handle_end() {
32
+ $this->log( 'Finished job to reset all product FB data.' );
33
+ }
34
+
35
+ /**
36
+ * Get a set of items for the batch.
37
+ *
38
+ * NOTE: when using an OFFSET based query to retrieve items it's recommended to order by the item ID while
39
+ * ASCENDING. This is so that any newly added items will not disrupt the query offset.
40
+ *
41
+ * @param int $batch_number The batch number increments for each new batch in the job cycle.
42
+ * @param array $args The args for the job.
43
+ *
44
+ * @throws Exception On error. The failure will be logged by Action Scheduler and the job chain will stop.
45
+ */
46
+ protected function get_items_for_batch( int $batch_number, array $args ): array {
47
+ global $wpdb;
48
+
49
+ $products = get_posts(
50
+ [
51
+ 'post_type' => 'product',
52
+ 'post_status' => 'any',
53
+ 'fields' => 'ids',
54
+ 'offset' => $this->get_query_offset( $batch_number ),
55
+ 'posts_per_page' => $this->get_batch_size(),
56
+ ]
57
+ );
58
+
59
+ return array_map( 'intval', $products );
60
+
61
+ }
62
+
63
+ /**
64
+ * Processes a batch of items.
65
+ *
66
+ * @since 3.0.5
67
+ *
68
+ * @param array $items The items of the current batch.
69
+ * @param array $args The args for the job.
70
+ *
71
+ * @throws Exception On error. The failure will be logged by Action Scheduler and the job chain will stop.
72
+ */
73
+ protected function process_items( array $items, array $args ) {
74
+ foreach ( $items as $product_id ) {
75
+ $integration = facebook_for_woocommerce()->get_integration();
76
+ $integration->reset_single_product( $product_id );
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Empty function to satisfy parent class requirements.
82
+ * We don't use it because we are processing the whole batch at once in process_items.
83
+ *
84
+ * @since 3.0.5
85
+ *
86
+ * @param mixed $item The items of the current batch.
87
+ * @param array $args The args for the job.
88
+ *
89
+ * @return void
90
+ */
91
+ protected function process_item( $item, array $args ) {}
92
+
93
+ /**
94
+ * Get the name/slug of the job.
95
+ *
96
+ * @return string
97
+ */
98
+ public function get_name(): string {
99
+ return 'reset_all_catalog_products';
100
+ }
101
+
102
+ /**
103
+ * Get the name/slug of the plugin that owns the job.
104
+ *
105
+ * @return string
106
+ */
107
+ public function get_plugin_name(): string {
108
+ return WC_Facebookcommerce::PLUGIN_ID;
109
+ }
110
+
111
+ /**
112
+ * Get the job's batch size.
113
+ *
114
+ * @return int
115
+ */
116
+ public function get_batch_size(): int {
117
+ return 25;
118
+ }
119
+
120
+ }
includes/Utilities/DebugTools.php ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Facebook\Utilities;
4
+
5
+ /**
6
+ * Class DebugTools
7
+ *
8
+ * @since 3.0.5
9
+ */
10
+ class DebugTools {
11
+
12
+ /**
13
+ * Initialize the class.
14
+ *
15
+ * @since 3.0.5
16
+ */
17
+ public function __construct() {
18
+ if ( is_admin() && ! is_ajax() ) {
19
+ add_filter( 'woocommerce_debug_tools', [ $this, 'add_debug_tool' ] );
20
+ }
21
+ }
22
+
23
+ /**
24
+ * Adds clear settings tool to WC system status -> tools page.
25
+ *
26
+ * @since 3.0.5
27
+ *
28
+ * @param array $tools system status tools.
29
+ * @return array
30
+ */
31
+ public function add_debug_tool( $tools ) {
32
+ if ( ! facebook_for_woocommerce()->get_connection_handler()->is_connected()
33
+ || ! facebook_for_woocommerce()->get_integration()->is_debug_mode_enabled() ) {
34
+ return $tools;
35
+ }
36
+
37
+ $tools['wc_facebook_settings_reset'] = [
38
+ 'name' => __( 'Facebook: Reset connection settings', 'facebook-for-woocommerce' ),
39
+ 'button' => __( 'Reset settings', 'facebook-for-woocommerce' ),
40
+ 'desc' => __( 'This tool will clear your Facebook settings to reset them, allowing you to rebuild your connection.', 'facebook-for-woocommerce' ),
41
+ 'callback' => [ $this, 'clear_facebook_settings' ],
42
+ ];
43
+
44
+ $tools['wc_facebook_delete_background_jobs'] = [
45
+ 'name' => __( 'Facebook: Delete Background Sync Jobs', 'facebook-for-woocommerce' ),
46
+ 'button' => __( 'Clear Background Sync Jobs', 'facebook-for-woocommerce' ),
47
+ 'desc' => __( 'This tool will clear your clear background sync jobs from the options table.', 'facebook-for-woocommerce' ),
48
+ 'callback' => [ $this, 'clean_up_old_background_sync_options' ],
49
+ ];
50
+
51
+ $tools['reset_all_product_fb_settings'] = [
52
+ 'name' => __( 'Facebook: Reset all products', 'facebook-for-woocommerce' ),
53
+ 'button' => __( 'Reset products Facebook settings', 'facebook-for-woocommerce' ),
54
+ 'desc' => __( 'This tool will reset Facebook settings for all products on your WooCommerce store.', 'facebook-for-woocommerce' ),
55
+ 'callback' => [ $this, 'reset_all_product_fb_settings' ],
56
+ ];
57
+
58
+ $tools['wc_facebook_delete_all_products'] = [
59
+ 'name' => __( 'Facebook: Delete all products from your Facebook Catalog', 'facebook-for-woocommerce' ),
60
+ 'button' => __( 'Delete all products', 'facebook-for-woocommerce' ),
61
+ 'desc' => __( 'This tool will delete all products from your Facebook Catalog.', 'facebook-for-woocommerce' ),
62
+ 'callback' => [ $this, 'delete_all_products' ],
63
+ ];
64
+
65
+ return $tools;
66
+ }
67
+
68
+ /**
69
+ * Runs the Delete Background Sync Jobs tool.
70
+ *
71
+ * @since 3.0.5
72
+ *
73
+ * @return string
74
+ */
75
+ public function clean_up_old_background_sync_options() {
76
+ global $wpdb;
77
+
78
+ $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '%wc_facebook_background_product_sync%'" );
79
+
80
+ return __( 'Background sync jobs have been deleted.', 'facebook-for-woocommerce' );
81
+
82
+ }
83
+
84
+ /**
85
+ * Runs the clear settings tool.
86
+ *
87
+ * @since 3.0.5
88
+ *
89
+ * @return string
90
+ */
91
+ public function clear_facebook_settings() {
92
+ // Disconnect FB.
93
+ facebook_for_woocommerce()->get_connection_handler()->disconnect();
94
+
95
+ return esc_html__( 'Cleared all Facebook settings!', 'facebook-for-woocommerce' );
96
+
97
+ }
98
+
99
+ /**
100
+ * Runs the reset all catalog products settings tool.
101
+ *
102
+ * @since 3.0.5
103
+ *
104
+ * @return string
105
+ */
106
+ public function reset_all_product_fb_settings() {
107
+ facebook_for_woocommerce()->job_manager->reset_all_product_fb_settings->queue_start();
108
+ return esc_html__( 'Reset products Facebook settings job started!', 'facebook-for-woocommerce' );
109
+
110
+ }
111
+
112
+ /**
113
+ * Delete products from Facebook catalog.
114
+ *
115
+ * @since 3.0.5
116
+ *
117
+ * @return string
118
+ */
119
+ public function delete_all_products() {
120
+ facebook_for_woocommerce()->job_manager->delete_all_products->queue_start();
121
+ return esc_html__( 'Delete products from Facebook catalog job started!', 'facebook-for-woocommerce' );
122
+ }
123
+
124
+ }
includes/Utilities/Shipment.php DELETED
@@ -1,689 +0,0 @@
1
- <?php
2
- // phpcs:ignoreFile
3
- /**
4
- * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
5
- *
6
- * This source code is licensed under the license found in the
7
- * LICENSE file in the root directory of this source tree.
8
- *
9
- * @package FacebookCommerce
10
- */
11
-
12
- namespace WooCommerce\Facebook\Utilities;
13
-
14
- defined( 'ABSPATH' ) or exit;
15
-
16
- /**
17
- * Utility class for shipment functionality.
18
- *
19
- * @since 2.1.0
20
- */
21
- class Shipment {
22
-
23
-
24
- /** @var mixed key-value array of valid carriers Facebook codes and labels */
25
- protected $valid_carriers;
26
-
27
- /** @var mixed mapping of carriers from the Shipment Tracking plugin to their Facebook code */
28
- protected $shipment_tracking_carriers;
29
-
30
-
31
- /**
32
- * Constructor.
33
- *
34
- * @since 2.1.0
35
- */
36
- public function __construct() {
37
-
38
- /**
39
- * @see https://developers.facebook.com/docs/commerce-platform/order-management/carrier-codes
40
- */
41
- $this->valid_carriers = array(
42
- 'AUSTRALIA_POST' => 'Australia Post',
43
- 'CANADA_POST' => 'Canada Post',
44
- 'DHL' => 'DHL',
45
- 'DHL_ECOMMERCE_US' => 'DHL eCommerce US',
46
- 'EAGLE' => 'Eagle',
47
- 'FEDEX' => 'FedEx',
48
- 'FEDEX_UK' => 'FedEx UK',
49
- 'NEW_ZEALAND_POST' => 'New Zealand Post',
50
- 'ONTRAC' => 'OnTrac',
51
- 'POST_DANMARK' => 'Post Danmark',
52
- 'PUROLATOR' => 'Purolator',
53
- 'ROYAL_MAIL' => 'Royal Mail',
54
- 'SPEE_DEE' => 'Spee-Dee',
55
- 'TNT' => 'TNT',
56
- 'TNT_POST' => 'TNT Post',
57
- 'UPS' => 'UPS',
58
- 'USPS' => 'USPS',
59
- 'OTHER' => 'Other tracking number',
60
- 'ABF_FREIGHT' => 'ABF Freight',
61
- 'ABX_EXPRESS' => 'ABX Express',
62
- 'AB_CUSTOM_GROUP' => 'AB Custom Group',
63
- 'ACOMMERCE' => 'aCommerce',
64
- 'ACS_COURIER' => 'ACS Courier',
65
- 'ACS_WORLDWIDE_EXPRESS' => 'ACS Worldwide Express',
66
- 'ADICIONAL_LOGISTICS' => 'Adicional Logistics',
67
- 'ADSONE' => 'ADSOne',
68
- 'AIR21' => 'AIR21',
69
- 'AIRPAK_EXPRESS' => 'Airpak Express',
70
- 'AIRSPEED_INTERNATIONAL_CORPORATION' => 'Airspeed International Corporation',
71
- 'ALFATREX' => 'AlfaTrex',
72
- 'ALLIED_EXPRESS' => 'Allied Express',
73
- 'ALLJOY_SUPPLY_CHAIN_CO_LTD' => 'ALLJOY SUPPLY CHAIN CO., LTD',
74
- 'ALPHAFAST' => 'alphaFAST',
75
- 'AMAZON_FBA_USA' => 'Amazon FBA USA',
76
- 'AMAZON_LOGISTICS' => 'Amazon Logistics',
77
- 'AN_POST' => 'An Post',
78
- 'APC_OVERNIGHT' => 'APC Overnight',
79
- 'APC_OVERNIGHT_REFERENCE' => 'APC Overnight Reference',
80
- 'APC_POSTAL_LOGISTICS' => 'APC Postal Logistics',
81
- 'APRISA_EXPRESS' => 'Aprisa Express',
82
- 'ARAMEX' => 'Aramex',
83
- 'ARROW_XL' => 'Arrow XL',
84
- 'ASENDIA_GERMANY' => 'Asendia Germany',
85
- 'ASENDIA_HK' => 'Asendia HK',
86
- 'ASENDIA_HK_PREMIUM_SERVICE_LATAM' => 'Asendia HK - Premium Service (LATAM)',
87
- 'ASENDIA_UK' => 'Asendia UK',
88
- 'ASENDIA_USA' => 'Asendia USA',
89
- 'ASM' => 'ASM',
90
- 'AUPOST_CHINA' => 'AuPost China',
91
- 'AUSTRALIA_POST_SFTP' => 'Australia Post Sftp',
92
- 'AUSTRIAN_POST_EXPRESS' => 'Austrian Post (Express)',
93
- 'AUSTRIAN_POST_REGISTERED' => 'Austrian Post (Registered)',
94
- 'AXL_EXPRESS_LOGISTICS' => 'AXL Express & Logistics',
95
- 'A_DUIE_PYLE' => 'A Duie Pyle',
96
- 'A_J_EXPRESS' => 'a j express',
97
- 'B2C_EUROPE' => 'B2C Europe',
98
- 'BELPOST' => 'Belpost',
99
- 'BERT_TRANSPORT' => 'Bert Transport',
100
- 'BEST_EXPRESS' => 'Best Express',
101
- 'BEST_WAY_PARCEL' => 'Best Way Parcel',
102
- 'BIRDSYSTEM' => 'BirdSystem',
103
- 'BJS_DISTRIBUTION_STORAGE_COURIERS' => 'BJS Distribution, Storage & Couriers',
104
- 'BJS_DISTRIBUTION_STORAGE_COURIERS_FTP' => 'BJS Distribution, Storage & Couriers - FTP',
105
- 'BLUECARE_EXPRESS_LTD' => 'Bluecare Express Ltd',
106
- 'BLUEDART' => 'Bluedart',
107
- 'BLUE_STAR' => 'Blue Star',
108
- 'BNEED' => 'Bneed',
109
- 'BONDS_COURIERS' => 'Bonds Couriers',
110
- 'BOXC' => 'BoxC',
111
- 'BPOST' => 'Bpost',
112
- 'BPOST_INTERNATIONAL' => 'Bpost international',
113
- 'BRAZIL_CORREIOS' => 'Brazil Correios',
114
- 'BRT_BARTOLINI' => 'BRT Bartolini',
115
- 'BRT_BARTOLINI_PARCEL_ID' => 'BRT Bartolini(Parcel ID)',
116
- 'BULGARIAN_POSTS' => 'Bulgarian Posts',
117
- 'BUYLOGIC' => 'Buylogic',
118
- 'CAMBODIA_POST' => 'Cambodia Post',
119
- 'CANPAR_COURIER' => 'Canpar Courier',
120
- 'CAPITAL_TRANSPORT' => 'Capital Transport',
121
- 'CARRIER_007EX' => '007EX',
122
- 'CARRIER_17_POST_SERVICE' => '17 Post Service',
123
- 'CARRIER_2GO' => '2GO',
124
- 'CARRIER_360_LION_EXPRESS' => '360 Lion Express',
125
- 'CARRIER_4PX' => '4PX',
126
- 'CARRIER_4_72_ENTREGANDO' => '4-72 Entregando',
127
- 'CARRIER_ECHO' => 'Echo',
128
- 'CBL_LOGISTICS' => 'CBL Logistics',
129
- 'CELERITAS_TRANSPORTE_SL' => 'Celeritas Transporte, S.L',
130
- 'CESKA_POSTA' => 'Česká Poš',
131
- 'CHINA_EMS_EPACKET' => 'China EMS (ePacket)',
132
- 'CHINA_POST' => 'China Post',
133
- 'CHIT_CHATS' => 'Chit Chats',
134
- 'CHRONOPOST_FRANCE' => 'Chronopost France',
135
- 'CHRONOPOST_PORTUGAL' => 'Chronopost Portugal',
136
- 'CH_ROBINSON_WORLDWIDE_INC' => 'C.H. Robinson Worldwide, Inc.',
137
- 'CITY_LINK_EXPRESS' => 'City-Link Express',
138
- 'CJ_CENTURY' => 'CJ Century',
139
- 'CJ_CENTURY_INTERNATIONAL' => 'CJ Century (International)',
140
- 'CJ_GLS' => 'CJ GLS',
141
- 'CJ_KOREA_EXPRESS' => 'CJ Korea Express',
142
- 'CJ_LOGISTICS_INTERNATIONAL' => 'CJ Logistics International',
143
- 'CJ_TRANSNATIONAL_PHILIPPINES' => 'CJ Transnational Philippines',
144
- 'CLEVY_LINKS' => 'Clevy Links',
145
- 'CLOUDWISH_ASIA' => 'Cloudwish Asia',
146
- 'CNE_EXPRESS' => 'CNE Express',
147
- 'COLISSIMO' => 'Colissimo',
148
- 'COLIS_PRIVE' => 'Colis Privé',
149
- 'COLLECTCO' => 'CollectCo',
150
- 'COLLECT_PLUS' => 'Collect+',
151
- 'CON_WAY_FREIGHT' => 'Con-way Freight',
152
- 'COPA_AIRLINES_COURIER' => 'Copa Airlines Courier',
153
- 'CORREOS_CHILE' => 'Correos Chile',
154
- 'CORREOS_DE_COSTA_RICA' => 'Correos de Costa Rica',
155
- 'CORREOS_DE_ESPANA' => 'Correos de España',
156
- 'CORREOS_DE_MEXICO' => 'Correos de Mexico',
157
- 'CORREOS_EXPRESS' => 'Correos Express',
158
- 'CORREO_ARGENTINO' => 'Correo Argentino',
159
- 'COSMETICS_NOW' => 'Cosmetics Now',
160
- 'COUREX' => 'Courex',
161
- 'COURIERPOST' => 'CourierPost',
162
- 'COURIERS_PLEASE' => 'Couriers Please',
163
- 'COURIER_IT' => 'Courier IT',
164
- 'COURIER_PLUS' => 'Courier Plus',
165
- 'CPACKET' => 'cPacket',
166
- 'CUCKOO_EXPRESS' => 'Cuckoo Express',
167
- 'CYPRUS_POST' => 'Cyprus Post',
168
- 'DACHSER' => 'DACHSER',
169
- 'DAWN_WING' => 'Dawn Wing',
170
- 'DAYLIGHT_TRANSPORT_LLC' => 'Daylight Transport, LLC',
171
- 'DB_SCHENKER' => 'DB Schenker',
172
- 'DB_SCHENKER_SWEDEN' => 'DB Schenker Sweden',
173
- 'DD_EXPRESS_COURIER' => 'DD Express Courier',
174
- 'DELCART' => 'Delcart',
175
- 'DELHIVERY' => 'Delhivery',
176
- 'DELIVERYONTIME_LOGISTICS_PVT_LTD' => 'DELIVERYONTIME LOGISTICS PVT LTD',
177
- 'DELTEC_COURIER' => 'Deltec Courier',
178
- 'DEMANDSHIP' => 'DemandShip',
179
- 'DETRACK' => 'Detrack',
180
- 'DEUTSCHE_POST_DHL' => 'Deutsche Post DHL',
181
- 'DEUTSCHE_POST_MAIL' => 'Deutsche Post Mail',
182
- 'DEX_I' => 'DEX-I',
183
- 'DHL_2_MANN_HANDLING' => 'DHL 2-Mann-Handling',
184
- 'DHL_ACTIVE_TRACING' => 'DHL Active Tracing',
185
- 'DHL_BENELUX' => 'DHL Benelux',
186
- 'DHL_ECOMMERCE_ASIA' => 'DHL eCommerce Asia',
187
- 'DHL_EXPRESS_PIECE_ID' => 'DHL Express (Piece ID)',
188
- 'DHL_GLOBAL_FORWARDING' => 'DHL Global Forwarding',
189
- 'DHL_HONG_KONG' => 'DHL Hong Kong',
190
- 'DHL_NETHERLANDS' => 'DHL Netherlands',
191
- 'DHL_PARCEL_NL' => 'DHL Parcel NL',
192
- 'DHL_PARCEL_SPAIN' => 'DHL Parcel Spain',
193
- 'DHL_POLAND_DOMESTIC' => 'DHL Poland Domestic',
194
- 'DHL_SPAIN_DOMESTIC' => 'DHL Spain Domestic',
195
- 'DIMERCO_EXPRESS_GROUP' => 'Dimerco Express Group',
196
- 'DIRECTLOG' => 'Directlog',
197
- 'DIRECT_FREIGHT_EXPRESS' => 'Direct Freight Express',
198
- 'DIRECT_LINK' => 'Direct Link',
199
- 'DMM_NETWORK' => 'DMM Network',
200
- 'DOORA_LOGISTICS' => 'Doora Logistics',
201
- 'DOTZOT' => 'Dotzot',
202
- 'DPD' => 'DPD',
203
- 'DPD_FRANCE' => 'DPD France',
204
- 'DPD_GERMANY' => 'DPD Germany',
205
- 'DPD_HK' => 'DPD HK',
206
- 'DPD_IRELAND' => 'DPD Ireland',
207
- 'DPD_LOCAL' => 'DPD Local',
208
- 'DPD_LOCAL_REFERENCE' => 'DPD Local reference',
209
- 'DPD_POLAND' => 'DPD Poland',
210
- 'DPD_ROMANIA' => 'DPD Romania',
211
- 'DPD_RUSSIA' => 'DPD Russia',
212
- 'DPD_UK' => 'DPD UK',
213
- 'DPEX' => 'DPEX',
214
- 'DPEX_CHINA' => 'DPEX China',
215
- 'DPE_EXPRESS' => 'DPE Express',
216
- 'DPE_SOUTH_AFRICA' => 'DPE South Africa',
217
- 'DSV' => 'DSV',
218
- 'DTDC_AUSTRALIA' => 'DTDC Australia',
219
- 'DTDC_EXPRESS_GLOBAL_PTE_LTD' => 'DTDC Express Global PTE LTD',
220
- 'DTDC_INDIA' => 'DTDC India',
221
- 'DX' => 'DX',
222
- 'DX_FREIGHT' => 'DX Freight',
223
- 'DYNALOGIC_BENELUX_BV' => 'Dynalogic Benelux BV',
224
- 'DYNAMIC_LOGISTICS' => 'Dynamic Logistics',
225
- 'EASY_MAIL' => 'Easy Mail',
226
- 'ECARGO' => 'Ecargo',
227
- 'ECMS_INTERNATIONAL_LOGISTICS_CO_LTD' => 'ECMS International Logistics Co., Ltd.',
228
- 'ECOM_EXPRESS' => 'Ecom Express',
229
- 'EC_FIRSTCLASS' => 'EC-Firstclass',
230
- 'EFS_E_COMMERCE_FULFILLMENT_SERVICE' => 'EFS (E-commerce Fulfillment Service)',
231
- 'EKART' => 'Ekart',
232
- 'ELTA_HELLENIC_POST' => 'ELTA Hellenic Post',
233
- 'EMIRATES_POST' => 'Emirates Post',
234
- 'EMPS_EXPRESS' => 'EMPS Express',
235
- 'ENSENDA' => 'Ensenda',
236
- 'ENVIALIA' => 'Envialia',
237
- 'EPARCEL_KOREA' => 'eParcel Korea',
238
- 'EP_BOX' => 'EP-Box',
239
- 'EQUICK_CHINA' => 'Equick China',
240
- 'ESTAFETA' => 'Estafeta',
241
- 'ESTES' => 'Estes',
242
- 'ETOTAL_SOLUTION_LIMITED' => 'eTotal Solution Limited',
243
- 'EURODIS' => 'Eurodis',
244
- 'EXPEDITORS' => 'Expeditors',
245
- 'EZSHIP' => 'EZship',
246
- 'FASTRAK_SERVICES' => 'Fastrak Services',
247
- 'FASTWAY_AUSTRALIA' => 'Fastway Australia',
248
- 'FASTWAY_IRELAND' => 'Fastway Ireland',
249
- 'FASTWAY_NEW_ZEALAND' => 'Fastway New Zealand',
250
- 'FASTWAY_SOUTH_AFRICA' => 'Fastway South Africa',
251
- 'FEDEX_CROSS_BORDER' => 'Fedex Cross Border',
252
- 'FEDEX_FREIGHT' => 'FedEx Freight',
253
- 'FEDEX_POLAND_DOMESTIC' => 'FedEx Poland Domestic',
254
- 'FERCAM_LOGISTICS_TRANSPORT' => 'FERCAM Logistics & Transport',
255
- 'FIRST_FLIGHT_COURIERS' => 'First Flight Couriers',
256
- 'FIRST_LOGISTICS' => 'First Logistics',
257
- 'FLYT_EXPRESS' => 'Flyt Express',
258
- 'GATI_KWE' => 'Gati-KWE',
259
- 'GDEX' => 'GDEX',
260
- 'GENIKI_TAXYDROMIKI' => 'Geniki Taxydromiki',
261
- 'GEODIS_E_SPACE' => 'Geodis E-space',
262
- 'GEODIS_DISTRIBUTION_EXPRESS' => 'GEODIS - Distribution & Express',
263
- 'GIAO_HANG_NHANH' => 'Giao hàng nhanh',
264
- 'GLOBEGISTICS_INC' => 'Globegistics Inc.',
265
- 'GLS' => 'GLS',
266
- 'GLS_CZECH_REPUBLIC' => 'GLS Czech Republic',
267
- 'GLS_ITALY' => 'GLS Italy',
268
- 'GLS_NETHERLANDS' => 'GLS Netherlands',
269
- 'GOFLY' => 'GoFly',
270
- 'GOJAVAS' => 'GoJavas',
271
- 'GREYHOUND' => 'Greyhound',
272
- 'GSI_EXPRESS' => 'GSI EXPRESS',
273
- 'HERMESWORLD' => 'Hermesworld',
274
- 'HERMES_GERMANY' => 'Hermes Germany',
275
- 'HERMES_ITALY' => 'Hermes Italy',
276
- 'HOLISOL' => 'Holisol',
277
- 'HOMEDIRECT_LOGISTICS' => 'Homedirect Logistics',
278
- 'HONG_KONG_POST' => 'Hong Kong Post',
279
- 'HRVATSKA_POSTA' => 'Hrvatska Pošta',
280
- 'HUA_HAN_LOGISTICS' => 'Hua Han Logistics',
281
- 'HUNTER_EXPRESS' => 'Hunter Express',
282
- 'ICELAND_POST' => 'Iceland Post',
283
- 'IDEX' => 'IDEX',
284
- 'IMEX_GLOBAL_SOLUTIONS' => 'IMEX Global Solutions',
285
- 'IMX_MAIL' => 'IMX Mail',
286
- 'INDIA_POST_DOMESTIC' => 'India Post Domestic',
287
- 'INDIA_POST_INTERNATIONAL' => 'India Post International',
288
- 'INPOST_PACZKOMATY' => 'InPost Paczkomaty',
289
- 'INSTANT_TIONG_NAM_EBIZ_EXPRESS_SDN_BHD' => 'INSTANT (Tiong Nam Ebiz Express Sdn Bhd)',
290
- 'INTERNATIONAL_SEUR' => 'International Seur',
291
- 'INTERNET_EXPRESS' => 'Internet Express',
292
- 'ISRAEL_POST' => 'Israel Post',
293
- 'ISRAEL_POST_DOMESTIC' => 'Israel Post Domestic',
294
- 'ITALY_SDA' => 'Italy SDA',
295
- 'I_PARCEL' => 'i-parcel',
296
- 'J_T_EXPRESS' => 'J&T EXPRESS',
297
- 'JAM_EXPRESS' => 'Jam Express',
298
- 'JANCO_ECOMMERCE' => 'Janco Ecommerce',
299
- 'JAPAN_POST' => 'Japan Post',
300
- 'JAYON_EXPRESS_JEX' => 'Jayon Express (JEX)',
301
- 'JCEX' => 'JCEX',
302
- 'JERSEY_POST' => 'Jersey Post',
303
- 'JET_SHIP_WORLDWIDE' => 'Jet-Ship Worldwide',
304
- 'JINSUNG_TRADING' => 'JINSUNG TRADING',
305
- 'JNE' => 'JNE',
306
- 'JOCOM' => 'Jocom',
307
- 'JP_BH_POSTA' => 'JP BH Pošta',
308
- 'JX' => 'JX',
309
- 'J_NET' => 'J-Net',
310
- 'K1_EXPRESS' => 'K1 Express',
311
- 'KANGAROO_WORLDWIDE_EXPRESS' => 'Kangaroo Worldwide Express',
312
- 'KERRY_EXPRESS_HONG_KONG' => 'Kerry Express Hong Kong',
313
- 'KERRY_EXPRESS_THAILAND' => 'Kerry Express Thailand',
314
- 'KERRY_EXPRESS_VIETNAM_CO_LTD' => 'Kerry Express (Vietnam) Co Ltd',
315
- 'KGM_HUB' => 'KGM Hub',
316
- 'KIALA' => 'Kiala',
317
- 'KOREA_POST' => 'Korea Post',
318
- 'KOREA_POST_EMS' => 'Korea Post EMS',
319
- 'KRONOS_EXPRESS' => 'Kronos Express',
320
- 'KUEHNE_NAGEL' => 'Kuehne + Nagel',
321
- 'LANDMARK_GLOBAL' => 'Landmark Global',
322
- 'LAO_POST' => 'Lao Post',
323
- 'LASERSHIP' => 'LaserShip',
324
- 'LA_POSTE' => 'La Poste',
325
- 'LBC_EXPRESS' => 'LBC Express',
326
- 'LHT_EXPRESS' => 'LHT Express',
327
- 'LIETUVOS_PASTAS' => 'Lietuvos Paštas',
328
- 'LINE_CLEAR_EXPRESS_LOGISTICS_SDN_BHD' => 'Line Clear Express & Logistics Sdn Bhd',
329
- 'LINK_BRIDGE_BEIJING_INTERNATIONAL_LOGISTICS_COLTD' => 'Link Bridge(BeiJing)international logistics co.,ltd',
330
- 'LION_PARCEL' => 'Lion Parcel',
331
- 'LOGISTIC_WORLDWIDE_EXPRESS' => 'Logistic Worldwide Express',
332
- 'LOGWIN_LOGISTICS' => 'Logwin Logistics',
333
- 'LONE_STAR_OVERNIGHT' => 'Lone Star Overnight',
334
- 'MAGYAR_POSTA' => 'Magyar Posta',
335
- 'MAILAMERICAS' => 'MailAmericas',
336
- 'MAILPLUS' => 'MailPlus',
337
- 'MAINFREIGHT' => 'Mainfreight',
338
- 'MALAYSIA_POST_EMS_POS_LAJU' => 'Malaysia Post EMS / Pos Laju',
339
- 'MALAYSIA_POST_REGISTERED' => 'Malaysia Post - Registered',
340
- 'MARA_XPRESS' => 'Mara Xpress',
341
- 'MATDESPATCH' => 'Matdespatch',
342
- 'MATKAHUOLTO' => 'Matkahuolto',
343
- 'MDS_COLLIVERY_PTY_LTD' => 'MDS Collivery Pty (Ltd)',
344
- 'MEGASAVE' => 'Megasave',
345
- 'MEXICO_AEROFLASH' => 'Mexico AeroFlash',
346
- 'MEXICO_REDPACK' => 'Mexico Redpack',
347
- 'MEXICO_SENDA_EXPRESS' => 'Mexico Senda Express',
348
- 'MIKROPAKKET' => 'Mikropakket',
349
- 'MONDIAL_RELAY' => 'Mondial Relay',
350
- 'MRW' => 'MRW',
351
- 'MUDITA' => 'MUDITA',
352
- 'MXE_EXPRESS' => 'MXE Express',
353
- 'MYHERMES_UK' => 'myHermes UK',
354
- 'MYPOSTONLINE' => 'Mypostonline',
355
- 'M_XPRESS_SDN_BHD' => 'M Xpress Sdn Bhd',
356
- 'NACEX_SPAIN' => 'NACEX Spain',
357
- 'NANJING_WOYUAN' => 'Nanjing Woyuan',
358
- 'NATIONAL_SAMEDAY' => 'National Sameday',
359
- 'NATIONWIDE_EXPRESS' => 'Nationwide Express',
360
- 'NEWGISTICS' => 'Newgistics',
361
- 'NEWGISTICS_API' => 'Newgistics API',
362
- 'NEXIVE_TNT_POST_ITALY' => 'Nexive (TNT Post Italy)',
363
- 'NHANS_SOLUTIONS' => 'Nhans Solutions',
364
- 'NIGHTLINE' => 'Nightline',
365
- 'NIM_EXPRESS' => 'Nim Express',
366
- 'NINJA_VAN' => 'Ninja Van',
367
- 'NINJA_VAN_INDONESIA' => 'Ninja Van Indonesia',
368
- 'NINJA_VAN_MALAYSIA' => 'Ninja Van Malaysia',
369
- 'NINJA_VAN_PHILIPPINES' => 'Ninja Van Philippines',
370
- 'NINJA_VAN_THAILAND' => 'Ninja Van Thailand',
371
- 'NIPOST' => 'NiPost',
372
- 'NORSK_GLOBAL' => 'Norsk Global',
373
- 'NOVA_POSHTA' => 'Nova Poshta',
374
- 'NOVA_POSHTA_INTERNATIONAL' => 'Nova Poshta (International)',
375
- 'OCA_ARGENTINA' => 'OCA Argentina',
376
- 'OLD_DOMINION_FREIGHT_LINE' => 'Old Dominion Freight Line',
377
- 'OMNIVA' => 'Omniva',
378
- 'OMNI_PARCEL' => 'Omni Parcel',
379
- 'ONE_WORLD_EXPRESS' => 'One World Express',
380
- 'PACKLINK' => 'Packlink',
381
- 'PAL_EXPRESS_LIMITED' => 'PAL Express Limited',
382
- 'PANDU_LOGISTICS' => 'Pandu Logistics',
383
- 'PANTHER' => 'Panther',
384
- 'PANTHER_ORDER_NUMBER' => 'Panther Order Number',
385
- 'PANTHER_REFERENCE' => 'Panther Reference',
386
- 'PAQUETEXPRESS' => 'Paquetexpress',
387
- 'PARCELLEDIN' => 'Parcelled.in',
388
- 'PARCELPOINT_PTY_LTD' => 'ParcelPoint Pty Ltd',
389
- 'PARCEL_FORCE' => 'Parcel Force',
390
- 'PARCEL_POST_SINGAPORE' => 'Parcel Post Singapore',
391
- 'PAYPAL_PACKAGE' => 'PayPal Package',
392
- 'PFC_EXPRESS' => 'PFC Express',
393
- 'PICKUPP' => 'Pickupp',
394
- 'PICK_UPP_MYS_SGP' => 'PICK UPP',
395
- 'PILOT_FREIGHT_SERVICES' => 'Pilot Freight Services',
396
- 'PITNEY_BOWES' => 'Pitney Bowes',
397
- 'PIXSELL_LOGISTICS' => 'PIXSELL LOGISTICS',
398
- 'POCZTA_POLSKA' => 'Poczta Polska',
399
- 'PORTUGAL_CTT' => 'Portugal CTT',
400
- 'PORTUGAL_SEUR' => 'Portugal Seur',
401
- 'POST56' => 'Post56',
402
- 'POSTEN_NORGE_BRING' => 'Posten Norge / Bring',
403
- 'POSTE_ITALIANE' => 'Poste Italiane',
404
- 'POSTE_ITALIANE_PACCOCELERE' => 'Poste Italiane Paccocelere',
405
- 'POSTI' => 'Posti',
406
- 'POSTNL_DOMESTIC' => 'PostNL Domestic',
407
- 'POSTNL_INTERNATIONAL' => 'PostNL International',
408
- 'POSTNL_INTERNATIONAL_3S' => 'PostNL International 3S',
409
- 'POSTNORD_DENMARK' => 'PostNord Denmark',
410
- 'POSTNORD_LOGISTICS' => 'PostNord Logistics',
411
- 'POSTNORD_SWEDEN' => 'PostNord Sweden',
412
- 'POST_OF_SLOVENIA' => 'Post of Slovenia',
413
- 'POST_SERBIA' => 'Post Serbia',
414
- 'POS_INDONESIA_DOMESTIC' => 'Pos Indonesia Domestic',
415
- 'POS_INDONESIA_INTL' => "Pos Indonesia Int'l",
416
- 'POSTA_ROMANA' => 'Poșta Română',
417
- 'PROFESSIONAL_COURIERS' => 'Professional Couriers',
418
- 'PTT_POSTA' => 'PTT Posta',
419
- 'QUALITYPOST' => 'QualityPost',
420
- 'QUANTIUM' => 'Quantium',
421
- 'QXPRESS' => 'Qxpress',
422
- 'RABEN_GROUP' => 'Raben Group',
423
- 'RAF_PHILIPPINES' => 'RAF Philippines',
424
- 'RAIDEREX' => 'RaidereX',
425
- 'RAM' => 'RAM',
426
- 'REDUR_SPAIN' => 'Redur Spain',
427
- 'RED_CARPET_LOGISTICS' => 'Red Carpet Logistics',
428
- 'RINCOS' => 'Rincos',
429
- 'RL_CARRIERS' => 'RL Carriers',
430
- 'ROADBULL_LOGISTICS' => 'Roadbull Logistics',
431
- 'ROCKET_PARCEL_INTERNATIONAL' => 'Rocket Parcel International',
432
- 'RPD2MAN_DELIVERIES' => 'RPD2man Deliveries',
433
- 'RPX_INDONESIA' => 'RPX Indonesia',
434
- 'RPX_ONLINE' => 'RPX Online',
435
- 'RRD_INTERNATIONAL_LOGISTICS_USA' => 'RRD International Logistics U.S.A',
436
- 'RUSSIAN_POST' => 'Russian Post',
437
- 'RUSTON' => 'Ruston',
438
- 'RZY_EXPRESS' => 'RZY Express',
439
- 'SAFEXPRESS' => 'Safexpress',
440
- 'SAGAWA' => 'Sagawa',
441
- 'SAIA_LTL_FREIGHT' => 'Saia LTL Freight',
442
- 'SAILPOST' => 'SAILPOST',
443
- 'SAP_EXPRESS' => 'SAP EXPRESS',
444
- 'SAUDI_POST' => 'Saudi Post',
445
- 'SCUDEX_EXPRESS' => 'Scudex Express',
446
- 'SEINO' => 'Seino',
447
- 'SEKO_LOGISTICS' => 'SEKO Logistics',
448
- 'SENDING_TRANSPORTE_URGENTE_Y_COMUNICACION_SAU' => 'Sending Transporte Urgente y Comunicacion, S.A.U',
449
- 'SENDIT' => 'Sendit',
450
- 'SENDLE' => 'Sendle',
451
- 'SFC_SERVICE' => 'SFC Service',
452
- 'SF_EXPRESS' => 'S.F. Express',
453
- 'SF_INTERNATIONAL' => 'S.F International',
454
- 'SGT_CORRIERE_ESPRESSO' => 'SGT Corriere Espresso',
455
- 'SHANGHAI_WISE_SUPPLY_CHAIN_MANAGEMENT_CO_LTD' => '上海万色供应链管理有限公司(原:上海万色速递有限公司) Shanghai Wise Supply Chain Management Co., Ltd',
456
- 'SHENZHEN_JINGHUADA_LOGISTICS_CO_LTD' => 'Shenzhen Jinghuada Logistics Co., Ltd',
457
- 'SHIPPIT' => 'Shippit',
458
- 'SHIPTOR' => 'Shiptor',
459
- 'SHOPFANSRU_LLC' => 'ShopfansRU LLC',
460
- 'SHREE_MARUTI_COURIER_SERVICES_PVT_LTD' => 'Shree Maruti Courier Services Pvt Ltd',
461
- 'SHREE_TIRUPATI_COURIER_SERVICES_PVT_LTD' => 'SHREE TIRUPATI COURIER SERVICES PVT. LTD.',
462
- 'SHUNYOU_POST' => 'Shunyou Post',
463
- 'SIMPLYPOST' => 'SimplyPost',
464
- 'SINGAPORE_POST' => 'Singapore Post',
465
- 'SINGAPORE_SPEEDPOST' => 'Singapore Speedpost',
466
- 'SIODEMKA' => 'Siodemka',
467
- 'SKYBOX' => 'SKYBOX',
468
- 'SKYNET_MALAYSIA' => 'SkyNet Malaysia',
469
- 'SKYNET_WORLDWIDE_EXPRESS' => 'SkyNet Worldwide Express',
470
- 'SKYNET_WORLDWIDE_EXPRESS_UAE' => 'SkyNet Worldwide Express UAE',
471
- 'SKYNET_WORLDWIDE_EXPRESS_UK' => 'Skynet Worldwide Express UK',
472
- 'SKYNET_WORLD_WIDE_EXPRESS_SOUTH_AFRICA' => 'Skynet World Wide Express South Africa',
473
- 'SKYPOSTAL' => 'SkyPostal',
474
- 'SMOOTH_COURIERS' => 'Smooth Couriers',
475
- 'SMSA_EXPRESS' => 'SMSA Express',
476
- 'SOUTH_AFRICAN_POST_OFFICE' => 'South African Post Office',
477
- 'SPANISH_SEUR' => 'Spanish Seur',
478
- 'SPECIALISED_FREIGHT' => 'Specialised Freight',
479
- 'SPEEDEX_COURIER' => 'Speedex Courier',
480
- 'SPEED_COURIERS' => 'Speed Couriers',
481
- 'SPOTON_LOGISTICS_PVT_LTD' => 'SPOTON Logistics Pvt Ltd',
482
- 'SRE_KOREA' => 'SRE Korea',
483
- 'STARTRACK' => 'StarTrack',
484
- 'STAR_TRACK_COURIER' => 'Star Track Courier',
485
- 'STAR_TRACK_EXPRESS' => 'Star Track Express',
486
- 'STO_EXPRESS' => 'STO Express',
487
- 'SWISS_POST' => 'Swiss Post',
488
- 'TAIWAN_POST' => 'Taiwan Post',
489
- 'TAQBIN_HONG_KONG' => 'TAQBIN Hong Kong',
490
- 'TAQBIN_MALAYSIA' => 'TAQBIN Malaysia',
491
- 'TAQBIN_SINGAPORE' => 'TAQBIN Singapore',
492
- 'TCS' => 'TCS',
493
- 'TELIWAY_SIC_EXPRESS' => 'Teliway SIC Express',
494
- 'THAILAND_THAI_POST' => 'Thailand Thai Post',
495
- 'THE_COURIER_GUY' => 'The Courier Guy',
496
- 'TIKI' => 'Tiki',
497
- 'TIPSA' => 'TIPSA',
498
- 'TNT_AUSTRALIA' => 'TNT Australia',
499
- 'TNT_CLICK_ITALY' => 'TNT-Click Italy',
500
- 'TNT_FRANCE' => 'TNT France',
501
- 'TNT_ITALY' => 'TNT Italy',
502
- 'TNT_REFERENCE' => 'TNT Reference',
503
- 'TNT_UK_REFERENCE' => 'TNT UK Reference',
504
- 'TOLL_IPEC' => 'Toll IPEC',
505
- 'TOLL_PRIORITY' => 'Toll Priority',
506
- 'TOLOS' => 'Tolos',
507
- 'TRAKPAK' => 'TrakPak',
508
- 'TRANSMISSION' => 'TransMission',
509
- 'TRANS_KARGO_INTERNASIONAL' => 'Trans Kargo Internasional',
510
- 'TUFFNELLS_PARCELS_EXPRESS' => 'Tuffnells Parcels Express',
511
- 'UBI_SMART_PARCEL' => 'UBI Smart Parcel',
512
- 'UKRPOSHTA' => 'UkrPoshta',
513
- 'UK_MAIL' => 'UK Mail',
514
- 'UNITED_DELIVERY_SERVICE_LTD' => 'United Delivery Service, Ltd',
515
- 'UPS_FREIGHT' => 'UPS Freight',
516
- 'UPS_MAIL_INNOVATIONS' => 'UPS Mail Innovations',
517
- 'VIETNAM_POST' => 'Vietnam Post',
518
- 'VIETNAM_POST_EMS' => 'Vietnam Post EMS',
519
- 'VIETTELPOST' => 'ViettelPost',
520
- 'WAHANA' => 'Wahana',
521
- 'WANBEXPRESS' => 'WanbExpress',
522
- 'WEDO_LOGISTICS' => 'WeDo Logistics',
523
- 'WEPOST_LOGISTICS' => 'WePost Logistics',
524
- 'WHISTL' => 'Whistl',
525
- 'WISELOADS' => 'Wiseloads',
526
- 'WISE_EXPRESS' => 'Wise Express',
527
- 'WISHPOST' => 'WishPost',
528
- 'WNDIRECT' => 'wnDirect',
529
- 'XDP_EXPRESS' => 'XDP Express',
530
- 'XDP_EXPRESS_REFERENCE' => 'XDP Express Reference',
531
- 'XEND_EXPRESS' => 'Xend Express',
532
- 'XL_EXPRESS' => 'XL Express',
533
- 'XPOSTPH' => 'Xpost.ph',
534
- 'XPRESSBEES' => 'XpressBees',
535
- 'XQ_EXPRESS' => 'XQ Express',
536
- 'YAKIT' => 'Yakit',
537
- 'YAMATO_JAPAN' => 'Yamato Japan',
538
- 'YANWEN' => 'Yanwen',
539
- 'YODEL_DOMESTIC' => 'Yodel Domestic',
540
- 'YODEL_INTERNATIONAL' => 'Yodel International',
541
- 'YRC' => 'YRC',
542
- 'YTO_EXPRESS' => 'YTO Express',
543
- 'YUNDA_EXPRESS' => 'Yunda Express',
544
- 'YUN_EXPRESS' => 'Yun Express',
545
- 'ZEPTOEXPRESS' => 'ZeptoExpress',
546
- 'ZINC' => 'Zinc',
547
- 'ZJS_INTERNATIONAL' => 'ZJS International',
548
- 'ZTO_EXPRESS' => 'ZTO Express',
549
- 'ZYLLEM' => 'Zyllem',
550
- );
551
-
552
- /**
553
- * @see https://docs.woocommerce.com/document/shipment-tracking/#section-5
554
- */
555
- $this->shipment_tracking_carriers = array(
556
- // Australia
557
- 'Australia Post' => 'AUSTRALIA_POST',
558
- 'Fastway Couriers' => 'FASTWAY_AUSTRALIA',
559
- // Austria
560
- 'post.at' => 'OTHER',
561
- 'dhl.at' => 'DHL',
562
- 'DPD.at' => 'DPD', // TODO: may be DPD_GERMANY (because the example URL contains "tracking.dpd.de")
563
- // Brazil
564
- 'Correios' => 'BRAZIL_CORREIOS',
565
- // Belgium
566
- 'bpost' => 'BPOST', // TODO: may be BPOST_INTERNATIONAL
567
- // Canada
568
- 'Canada Post' => 'CANADA_POST',
569
- // Czech Republic
570
- 'PPL.cz' => 'OTHER',
571
- 'Česká pošta' => 'CESKA_POSTA',
572
- 'DHL.cz' => 'DHL',
573
- 'DPD.cz' => 'DPD', // TODO: may be DPD_GERMANY (because the example URL contains "tracking.dpd.de")
574
- // Finland
575
- 'Itella' => 'OTHER',
576
- // France
577
- 'Colissimo' => 'COLISSIMO',
578
- // Germany
579
- 'DHL Intraship (DE)' => 'DHL',
580
- 'Hermes' => 'HERMES_GERMANY',
581
- 'Deutsche Post DHL' => 'DEUTSCHE_POST_DHL',
582
- 'UPS Germany' => 'UPS',
583
- 'DPD.de' => 'DPD_GERMANY',
584
- // Ireland
585
- 'DPD.ie' => 'DPD_IRELAND',
586
- 'An Post' => 'AN_POST',
587
- // Italy
588
- 'BRT (Bartolini)' => 'BRT_BARTOLINI', // TODO: may be BRT_BARTOLINI_PARCEL_ID
589
- 'DHL Express' => 'DHL_EXPRESS_PIECE_ID',
590
- // India
591
- 'DTDC' => 'DTDC_INDIA',
592
- // Netherlands
593
- 'PostNL' => 'POSTNL_DOMESTIC', // TODO: may be POSTNL_INTERNATIONAL or POSTNL_INTERNATIONAL_3S
594
- 'DPD.NL' => 'DPD',
595
- 'UPS Netherlands' => 'UPS',
596
- // New Zealand
597
- 'Courier Post' => 'COURIERPOST',
598
- 'NZ Post' => 'NEW_ZEALAND_POST',
599
- 'Fastways' => 'FASTWAY_NEW_ZEALAND',
600
- 'PBT Couriers' => 'OTHER',
601
- // Poland
602
- 'InPost' => 'INPOST_PACZKOMATY',
603
- 'DPD.PL' => 'DPD_POLAND',
604
- 'Poczta Polska' => 'POCZTA_POLSKA',
605
- // Romania
606
- 'Fan Courier' => 'OTHER',
607
- 'DPD Romania' => 'DPD_ROMANIA',
608
- 'Urgent Cargus' => 'OTHER',
609
- // South Africa
610
- 'SAPO' => 'SOUTH_AFRICAN_POST_OFFICE',
611
- 'Fastway' => 'FASTWAY_SOUTH_AFRICA',
612
- // Sweden
613
- 'PostNord Sverige AB' => 'POSTNORD_SWEDEN',
614
- 'DHL.se' => 'DHL',
615
- 'Bring.se' => 'POSTEN_NORGE_BRING',
616
- 'UPS.se' => 'UPS',
617
- 'DB Schenker' => 'DB_SCHENKER_SWEDEN',
618
- // United Kingdom
619
- 'DHL' => 'DHL',
620
- 'DPD.co.uk' => 'DPD_UK',
621
- 'InterLink' => 'OTHER',
622
- 'ParcelForce' => 'PARCEL_FORCE',
623
- 'Royal Mail' => 'ROYAL_MAIL',
624
- 'TNT Express (consignment)' => 'TNT_UK_REFERENCE',
625
- 'TNT Express (reference)' => 'TNT_UK_REFERENCE',
626
- 'DHL Parcel UK' => 'DHL',
627
- // United States
628
- 'Fedex' => 'FEDEX',
629
- 'FedEx Sameday' => 'FEDEX',
630
- 'OnTrac' => 'ONTRAC',
631
- 'UPS' => 'UPS',
632
- 'USPS' => 'USPS',
633
- 'DHL US' => 'DHL_ECOMMERCE_US', // TODO: may be DHL
634
- );
635
- }
636
-
637
-
638
- /**
639
- * Gets the valid carriers.
640
- *
641
- * @since 2.1.0
642
- *
643
- * @return array key-value array with carrier codes and their labels
644
- */
645
- public function get_carrier_options() {
646
-
647
- return $this->valid_carriers;
648
- }
649
-
650
-
651
- /**
652
- * Determines whether the given carrier is one of the valid carrier options.
653
- *
654
- * @since 2.1.0
655
- *
656
- * @param string $carrier
657
- * @return bool
658
- */
659
- public function is_valid_carrier( $carrier ) {
660
-
661
- return array_key_exists( $carrier, $this->get_carrier_options() );
662
- }
663
-
664
-
665
- /**
666
- * Finds the proper Facebook carrier code, given a Shipment Tracking carrier.
667
- *
668
- * @since 2.1.0
669
- *
670
- * @param string $carrier Shipment Tracking carrier
671
- * @return string
672
- */
673
- public function convert_shipment_tracking_carrier_code( $carrier ) {
674
-
675
- if ( isset( $this->shipment_tracking_carriers[ $carrier ] ) ) {
676
- $carrier_code = $this->shipment_tracking_carriers[ $carrier ];
677
- } elseif ( in_array( $carrier, $this->get_carrier_options(), true ) ) {
678
- $carrier_code = array_search( $carrier, $this->get_carrier_options(), true );
679
- } elseif ( array_key_exists( $carrier, $this->get_carrier_options() ) ) {
680
- $carrier_code = $carrier;
681
- } else {
682
- $carrier_code = 'OTHER';
683
- }
684
-
685
- return $carrier_code;
686
- }
687
-
688
-
689
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/fbutils.php CHANGED
@@ -15,609 +15,613 @@ use WooCommerce\Facebook\Events\AAMSettings;
15
  use WooCommerce\Facebook\Events\Normalizer;
16
  use WooCommerce\Facebook\Framework\Api\Exception as ApiException;
17
 
18
- /**
19
- * FB Graph API helper functions
20
- */
21
- class WC_Facebookcommerce_Utils {
22
-
23
- const FB_RETAILER_ID_PREFIX = 'wc_post_id_';
24
- const PLUGIN_VERSION = \WC_Facebookcommerce::VERSION; // TODO: remove this in v2.0.0 {CW 2020-02-06}
25
-
26
- // TODO: this constant is no longer used and can probably be removed {WV 2020-01-21}
27
- const FB_VARIANT_IMAGE = 'fb_image';
28
- const FB_VARIANT_SIZE = 'size';
29
- const FB_VARIANT_COLOR = 'color';
30
- const FB_VARIANT_COLOUR = 'colour';
31
- const FB_VARIANT_PATTERN = 'pattern';
32
- const FB_VARIANT_GENDER = 'gender';
33
-
34
- public static $ems = null;
35
- public static $store_name = null;
36
-
37
- public static $validGenderArray =
38
- array(
39
- 'male' => 1,
40
- 'female' => 1,
41
- 'unisex' => 1,
42
- );
43
  /**
44
- * WooCommerce 2.1 support for wc_enqueue_js
45
- *
46
- * @since 1.2.1
47
- *
48
- * @access public
49
- * @param string $code
50
- * @return void
51
  */
52
- public static function wc_enqueue_js( $code ) {
53
- global $wc_queued_js;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
- if ( function_exists( 'wc_enqueue_js' ) && empty( $wc_queued_js ) ) {
56
- wc_enqueue_js( $code );
57
- } else {
58
- $wc_queued_js = $code . "\n" . $wc_queued_js;
 
59
  }
60
- }
61
 
62
- /**
63
- * Validate URLs, make relative URLs absolute
64
- *
65
- * @access public
66
- * @param string $url
67
- * @return string
68
- */
69
- public static function make_url( $url ) {
70
- if (
71
- // The first check incorrectly fails for URLs with special chars.
72
- ! filter_var( $url, FILTER_VALIDATE_URL ) &&
73
- substr( $url, 0, 4 ) !== 'http'
74
- ) {
75
- return get_site_url() . $url;
76
- } else {
77
- return $url;
 
78
  }
79
- }
80
 
81
- /**
82
- * Product ID for Dynamic Ads on Facebook can be SKU or wc_post_id_123
83
- * This function should be used to get retailer_id based on a WC_Product
84
- * from WooCommerce
85
- *
86
- * @access public
87
- * @param WC_Product|WC_Facebook_Product $woo_product
88
- * @return string
89
- */
90
- public static function get_fb_retailer_id( $woo_product ) {
91
- $woo_id = $woo_product->get_id();
92
-
93
- /*
94
- * Call $woo_product->get_id() instead of ->id to account for Variable
95
- * products, which have their own variant_ids.
96
  */
97
- $fb_retailer_id = $woo_product->get_sku() ?
98
- $woo_product->get_sku() . '_' . $woo_id :
99
- self::FB_RETAILER_ID_PREFIX . $woo_id;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
 
101
  /**
102
- * Filter facebook retailer id value.
103
- * This can be used to match retailer id generated by other Facebook plugins.
104
  *
105
- * @since 2.6.12
106
- * @param string Facebook Retailer ID.
107
- * @param WC_Product WooCommerce product.
108
  */
109
- return apply_filters( 'wc_facebook_fb_retailer_id', $fb_retailer_id, $woo_product );
110
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
 
112
- /**
113
- * Return categories for products/pixel
114
- *
115
- * @access public
116
- * @param String $id
117
- * @return Array
118
- */
119
- public static function get_product_categories( $wpid ) {
120
- $category_path = wp_get_post_terms(
121
- $wpid,
122
- 'product_cat',
123
- array( 'fields' => 'all' )
124
- );
125
- $content_category = array_values(
126
- array_map(
127
- function( $item ) {
128
- return $item->name;
129
- },
130
- $category_path
131
- )
132
- );
133
- $content_category_slice = array_slice( $content_category, -1 );
134
- $categories =
135
- empty( $content_category ) ? '""' : implode( ', ', $content_category );
136
- return array(
137
- 'name' => array_pop( $content_category_slice ),
138
- 'categories' => $categories,
139
- );
140
- }
141
 
142
- /**
143
- * Returns content id to match on for Pixel fires.
144
- *
145
- * @access public
146
- * @param WC_Product $woo_product
147
- * @return array
148
- */
149
- public static function get_fb_content_ids( $woo_product ) {
150
- return array( self::get_fb_retailer_id( $woo_product ) );
151
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
 
153
- /**
154
- * Clean up strings for FB Graph POSTing.
155
- * This function should will:
156
- * 1. Replace newlines chars/nbsp with a real space
157
- * 2. strip_tags()
158
- * 3. trim()
159
- *
160
- * @access public
161
- * @param String string
162
- * @return string
163
- */
164
- public static function clean_string( $string ) {
165
 
166
  /**
167
- * Filters whether the shortcodes should be applied for a string when syncing a product or be stripped out.
 
168
  *
169
- * @since 2.6.19
170
- *
171
- * @param bool $apply_shortcodes Shortcodes are applied if set to `true` and stripped out if set to `false`.
172
- * @param string $string String to clean up.
173
  */
174
- $apply_shortcodes = apply_filters( 'wc_facebook_string_apply_shortcodes', false, $string );
175
- if ( $apply_shortcodes ) {
176
- // Apply active shortcodes
177
- $string = do_shortcode( $string );
178
- } else {
179
- // Strip out active shortcodes
180
- $string = strip_shortcodes( $string );
 
 
 
181
  }
182
 
183
- $string = str_replace( array( '&amp%3B', '&amp;' ), '&', $string );
184
- $string = str_replace( array( "\r", '&nbsp;', "\t" ), ' ', $string );
185
- $string = wp_strip_all_tags( $string, false ); // true == remove line breaks
186
- return $string;
187
- }
 
 
 
 
188
 
189
- /**
190
- * Returns flat array of woo IDs for variable products, or
191
- * an array with a single woo ID for simple products.
192
- *
193
- * @access public
194
- * @param WC_Product|WC_Facebook_Product $woo_product
195
- * @return array
196
- */
197
- public static function get_product_array( $woo_product ) {
198
- $result = [];
199
- if ( self::is_variable_type( $woo_product->get_type() ) ) {
200
- foreach ( $woo_product->get_children() as $item_id ) {
201
- array_push( $result, $item_id );
202
  }
203
- return $result;
204
- } else {
205
- return array( $woo_product->get_id() );
206
  }
207
- }
208
 
209
- /**
210
- * Returns true if WooCommerce plugin found.
211
- *
212
- * @access public
213
- * @return bool
214
- */
215
- public static function isWoocommerceIntegration() {
216
- return class_exists( 'WooCommerce' );
217
- }
218
-
219
- /**
220
- * Returns integration dependent name.
221
- *
222
- * @access public
223
- * @return string
224
- */
225
- public static function getIntegrationName() {
226
- if ( self::isWoocommerceIntegration() ) {
227
- return 'WooCommerce';
228
- } else {
229
- return 'WordPress';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  }
231
- }
232
 
233
- /**
234
- * Returns user info for the current WP user.
235
- *
236
- * @access public
237
- * @param AAMSettings $aam_settings
238
- * @return array
239
- */
240
- public static function get_user_info( $aam_settings ) {
241
- $current_user = wp_get_current_user();
242
- if ( 0 === $current_user->ID || $aam_settings == null || ! $aam_settings->get_enable_automatic_matching() ) {
243
- // User not logged in or pixel not configured with automatic advance matching
244
- return [];
245
- } else {
246
- // Keys documented in
247
- // https://developers.facebook.com/docs/facebook-pixel/advanced/advanced-matching
248
- $user_data = array(
249
- 'em' => $current_user->user_email,
250
- 'fn' => $current_user->user_firstname,
251
- 'ln' => $current_user->user_lastname,
252
- 'external_id' => strval( $current_user->ID ),
253
  );
254
- $user_id = $current_user->ID;
255
- $user_data['ct'] = get_user_meta( $user_id, 'billing_city', true );
256
- $user_data['zp'] = get_user_meta( $user_id, 'billing_postcode', true );
257
- $user_data['country'] = get_user_meta( $user_id, 'billing_country', true );
258
- $user_data['st'] = get_user_meta( $user_id, 'billing_state', true );
259
- $user_data['ph'] = get_user_meta( $user_id, 'billing_phone', true );
260
- // Each field that is not present in AAM settings or is empty is deleted from user data
261
- foreach ( $user_data as $field => $value ) {
262
- if ( $value === null || $value === ''
263
- || ! in_array( $field, $aam_settings->get_enabled_automatic_matching_fields() )
264
- ) {
265
- unset( $user_data[ $field ] );
266
  }
 
 
 
 
 
267
  }
268
- // Country is a special case, it is returned as country in AAM settings
269
- // But used as cn in pixel
270
- if ( array_key_exists( 'country', $user_data ) ) {
271
- $country = $user_data['country'];
272
- $user_data['cn'] = $country;
273
- unset( $user_data['country'] );
 
 
 
 
 
 
 
 
 
 
274
  }
275
- $user_data = Normalizer::normalize_array( $user_data, true );
276
- return $user_data;
277
  }
278
- }
279
 
280
- /**
281
- * Utility function for development logging.
282
- */
283
- public static function fblog(
284
- $message,
285
- $object = [],
286
- $error = false,
287
- $ems = '' ) {
288
- if ( $error ) {
289
- $object['plugin_version'] = self::PLUGIN_VERSION;
290
- $object['php_version'] = phpversion();
291
  }
292
- $message = json_encode(
293
- array(
294
- 'message' => $message,
295
- 'object' => $object,
296
- )
297
- );
298
- $ems = $ems ?: self::$ems;
299
- if ( $ems ) {
300
- try {
301
- facebook_for_woocommerce()->get_api()->log($ems, $message, $error);
302
- } catch ( ApiException $e ) {
303
- $message = sprintf( 'There was an error trying to log: %s', $e->getMessage() );
304
- facebook_for_woocommerce()->log( $message );
305
- }
306
- } else {
307
- error_log(
308
- 'external merchant setting is null, something wrong here: ' .
309
- $message
310
- );
311
  }
312
- }
313
 
314
- /**
315
- * Utility function for development Tip Events logging.
316
- */
317
- public static function tip_events_log( $tip_id, $channel_id, $event, $ems = '' ) {
318
- $ems = $ems ?: self::$ems;
319
- if ( $ems ) {
320
- try {
321
- facebook_for_woocommerce()->get_api()->log_tip_event($tip_id, $channel_id, $event);
322
- } catch ( ApiException $e ) {
323
- $message = sprintf( 'There was an error while logging tip events: %s', $e->getMessage() );
324
- facebook_for_woocommerce()->log( $message );
325
  }
326
- } else {
327
- error_log( 'external merchant setting is null' );
328
  }
329
- }
330
 
331
- public static function is_variation_type( $type ) {
332
- return $type == 'variation' || $type == 'subscription_variation';
333
- }
334
-
335
- public static function is_variable_type( $type ) {
336
- return $type == 'variable' || $type == 'variable-subscription';
337
- }
 
 
 
338
 
339
- public static function check_woo_ajax_permissions( $action_text, $die ) {
340
- if ( ! current_user_can( 'manage_woocommerce' ) ) {
341
- self::log(
342
- 'Non manage_woocommerce user attempting to' . $action_text . '!',
343
- [],
344
- true
 
 
 
 
 
 
 
 
 
 
 
 
 
 
345
  );
346
- if ( $die ) {
347
- wp_die();
348
- }
349
- return false;
350
  }
351
- return true;
352
- }
353
 
354
- /**
355
- * Returns true if id is a positive non-zero integer
356
- *
357
- * @access public
358
- * @param string $pixel_id
359
- * @return bool
360
- */
361
- public static function is_valid_id( $pixel_id ) {
362
- return isset( $pixel_id ) && is_numeric( $pixel_id ) && (int) $pixel_id > 0;
363
- }
364
 
365
- /**
366
- * Helper function to query posts.
367
- */
368
- public static function get_wp_posts(
369
- $product_group_id = null,
370
- $compare_condition = null,
371
- $post_type = 'product' ) {
372
- $args = array(
373
- 'fields' => 'ids',
374
- 'meta_query' => array(
375
- ( ( $product_group_id ) ?
376
- array(
377
- 'key' => $product_group_id,
378
- 'compare' => $compare_condition,
379
- ) : []
380
- ),
381
- ),
382
- 'post_status' => 'publish',
383
- 'post_type' => $post_type,
384
- 'posts_per_page' => -1,
385
- );
386
- return get_posts( $args );
387
- }
388
 
389
- /**
390
- * Helper log function for debugging
391
- */
392
- public static function log( $message ) {
 
393
 
394
- // if this file is being included outside the plugin, or the plugin setting is disabled
395
- if ( ! function_exists( 'facebook_for_woocommerce' ) || ! facebook_for_woocommerce()->get_integration()->is_debug_mode_enabled() ) {
396
- return;
397
  }
398
 
399
- if ( is_array( $message ) || is_object( $message ) ) {
400
- $message = json_encode( $message );
401
- } else {
402
- $message = sanitize_textarea_field( $message );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
403
  }
404
 
405
- facebook_for_woocommerce()->log( $message );
406
- }
407
 
408
- // Return store name with sanitized apostrophe
409
- public static function get_store_name() {
410
- if ( self::$store_name ) {
411
- return self::$store_name;
412
- }
413
- $name = trim(
414
- str_replace(
415
- "'",
416
- "\u{2019}",
417
- html_entity_decode(
418
- get_bloginfo( 'name' ),
419
- ENT_QUOTES,
420
- 'UTF-8'
421
- )
422
- )
423
- );
424
- if ( $name ) {
425
- self::$store_name = $name;
426
- return $name;
427
- }
428
- // Fallback to site url
429
- $url = get_site_url();
430
- if ( $url ) {
431
- self::$store_name = parse_url( $url, PHP_URL_HOST );
432
- return self::$store_name;
433
- }
434
- // If site url doesn't exist, fall back to http host.
435
- if ( $_SERVER['HTTP_HOST'] ) {
436
- self::$store_name = $_SERVER['HTTP_HOST'];
437
- return self::$store_name;
438
  }
439
 
440
- // If http host doesn't exist, fall back to local host name.
441
- $url = gethostname();
442
- self::$store_name = $url;
443
- return ( self::$store_name ) ? ( self::$store_name ) : 'A Store Has No Name';
444
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
445
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
446
 
447
- /**
448
- * Get visible name for variant attribute rather than the slug
449
- *
450
- * @param int $wp_id Post ID.
451
- * @param string $label Attribute label.
452
- * @param string $default_value Default value to use if the term has no name.
453
- * @return string Term name or the default value.
454
- */
455
- public static function get_variant_option_name( $wp_id, $label, $default_value ) {
456
- $meta = get_post_meta( $wp_id, $label, true );
457
- $attribute_name = str_replace( 'attribute_', '', $label );
458
- $term = get_term_by( 'slug', $meta, $attribute_name );
459
- return $term && $term->name ? $term->name : $default_value;
460
- }
461
 
462
- /**
463
- * Get all products for synchronization tasks.
464
- *
465
- * Warning: While changing this code please make sure that it scales properly.
466
- * Sites with big product catalogs should not experience memory problems.
467
- *
468
- * @return array IDs of all product for synchronization.
469
- */
470
- public static function get_all_product_ids_for_sync() {
471
- // Get all published products ids. This includes parent products of variations.
472
- $product_args = array(
473
- 'fields' => 'ids',
474
- 'post_status' => 'publish',
475
- 'post_type' => 'product',
476
- 'posts_per_page' => -1,
477
- );
478
- $product_ids = get_posts( $product_args );
479
-
480
- // Get all variations ids with their parents ids.
481
- $variation_args = array(
482
- 'fields' => 'id=>parent',
483
- 'post_status' => 'publish',
484
- 'post_type' => 'product_variation',
485
- 'posts_per_page' => -1,
486
- );
487
- $variation_products = get_posts( $variation_args );
488
 
489
  /*
490
- * Collect all parent products.
491
- * Exclude variations which parents are not 'publish'.
492
  */
493
- $parent_product_ids = [];
494
- foreach ( $variation_products as $post_id => $parent_id ) {
495
- /*
496
- * Keep track of all parents to remove them from the list of products to sync.
497
- * Use key to automatically remove duplicated items.
498
- */
499
- $parent_product_ids[ $parent_id ] = true;
500
 
501
- // Include variations with published parents only.
502
- if ( in_array( $parent_id, $product_ids ) ) {
503
- $product_ids[] = $post_id;
504
  }
505
- }
506
-
507
- // Remove parent products because those can't be represented as Product Items.
508
- return array_diff( $product_ids, array_keys( $parent_product_ids ) );
509
- }
510
-
511
 
512
- /*
513
- * Change variant product field name from Woo taxonomy to FB name
514
- */
515
- public static function sanitize_variant_name( $name, $use_custom_data = true ) {
516
- $name = str_replace( array( 'attribute_', 'pa_' ), '', strtolower( $name ) );
 
 
 
 
 
 
 
517
 
518
- // British spelling
519
- if ( $name === self::FB_VARIANT_COLOUR ) {
520
- $name = self::FB_VARIANT_COLOR;
521
  }
522
 
523
- if ( $use_custom_data ) {
524
- switch ( $name ) {
525
- case self::FB_VARIANT_SIZE:
526
- case self::FB_VARIANT_COLOR:
527
- case self::FB_VARIANT_GENDER:
528
- case self::FB_VARIANT_PATTERN:
529
- break;
530
- default:
531
- $name = 'custom_data:' . strtolower( $name );
532
- break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
533
  }
 
534
  }
535
 
536
- return $name;
537
- }
 
538
 
539
- public static function validateGender( $gender ) {
540
- if ( $gender && ! isset( self::$validGenderArray[ $gender ] ) ) {
541
- $first_char = strtolower( substr( $gender, 0, 1 ) );
542
- // Men, Man, Boys
543
- if ( $first_char === 'm' || $first_char === 'b' ) {
544
- return 'male';
545
  }
546
- // Women, Woman, Female, Ladies
547
- if ( $first_char === 'w' || $first_char === 'f' || $first_char === 'l' ) {
548
- return 'female';
 
549
  }
550
- if ( $first_char === 'u' ) {
551
- return 'unisex';
 
 
552
  }
553
- if ( strlen( $gender ) >= 3 ) {
554
- $gender = strtolower( substr( $gender, 0, 3 ) );
555
- if ( $gender === 'gir' || $gender === 'her' ) {
556
- return 'female';
557
- }
558
- if ( $gender === 'him' || $gender === 'his' || $gender == 'guy' ) {
559
- return 'male';
560
- }
561
- }
562
- return null;
563
  }
564
- return $gender;
565
- }
566
 
567
- public static function get_fbid_post_meta( $wp_id, $fbid_type ) {
568
- return get_post_meta( $wp_id, $fbid_type, true );
569
- }
570
-
571
- public static function is_all_caps( $value ) {
572
- if ( $value === null || $value === '' ) {
573
- return true;
574
- }
575
- if ( preg_match( '/[^\\p{Common}\\p{Latin}]/u', $value ) ) {
576
- // Contains non-western characters
577
- // So, it can't be all uppercase
578
- return false;
579
  }
580
- $latin_string = preg_replace( '/[^\\p{Latin}]/u', '', $value );
581
- if ( $latin_string === '' ) {
582
- // Symbols only
583
- return true;
584
- }
585
- return strtoupper( $latin_string ) === $latin_string;
586
- }
587
 
588
- public static function decode_json( $json_string, $assoc = false ) {
589
- // Plugin requires 5.6.0 but for some user use 5.5.9 JSON_BIGINT_AS_STRING
590
- // will cause 502 issue when redirect.
591
- return version_compare( phpversion(), '5.6.0' ) >= 0
592
- ? json_decode( $json_string, $assoc, 512, JSON_BIGINT_AS_STRING )
593
- : json_decode( $json_string, $assoc, 512 );
594
- }
 
595
 
596
- public static function set_test_fail_reason( $msg, $trace ) {
597
- $reason_msg = get_transient( 'facebook_plugin_test_fail' );
598
- if ( $reason_msg ) {
599
- $msg = $reason_msg . PHP_EOL . $msg;
 
 
 
 
 
 
600
  }
601
- set_transient( 'facebook_plugin_test_fail', $msg );
602
- set_transient( 'facebook_plugin_test_stack_trace', $trace );
603
- }
604
 
605
- /**
606
- * Helper function to check time cap.
607
- */
608
- public static function check_time_cap( $from, $date_cap ) {
609
- if ( $from == null ) {
610
- return true;
611
  }
612
- $now = new DateTime( current_time( 'mysql' ) );
613
- $diff_in_day = $now->diff( new DateTime( $from ) )->format( '%a' );
614
- return is_numeric( $diff_in_day ) && (int) $diff_in_day > $date_cap;
615
  }
616
 
617
- public static function get_cached_best_tip() {
618
- $cached_best_tip = self::decode_json(
619
- get_option( 'fb_info_banner_last_best_tip', '' )
620
- );
621
- return $cached_best_tip;
622
- }
623
- }
15
  use WooCommerce\Facebook\Events\Normalizer;
16
  use WooCommerce\Facebook\Framework\Api\Exception as ApiException;
17
 
18
+ if ( ! class_exists( 'WC_Facebookcommerce_Utils' ) ) :
19
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  /**
21
+ * FB Graph API helper functions
 
 
 
 
 
 
22
  */
23
+ class WC_Facebookcommerce_Utils {
24
+
25
+ const FB_RETAILER_ID_PREFIX = 'wc_post_id_';
26
+ const PLUGIN_VERSION = \WC_Facebookcommerce::VERSION; // TODO: remove this in v2.0.0 {CW 2020-02-06}
27
+
28
+ // TODO: this constant is no longer used and can probably be removed {WV 2020-01-21}
29
+ const FB_VARIANT_IMAGE = 'fb_image';
30
+ const FB_VARIANT_SIZE = 'size';
31
+ const FB_VARIANT_COLOR = 'color';
32
+ const FB_VARIANT_COLOUR = 'colour';
33
+ const FB_VARIANT_PATTERN = 'pattern';
34
+ const FB_VARIANT_GENDER = 'gender';
35
+
36
+ public static $ems = null;
37
+ public static $store_name = null;
38
+
39
+ public static $validGenderArray =
40
+ array(
41
+ 'male' => 1,
42
+ 'female' => 1,
43
+ 'unisex' => 1,
44
+ );
45
+ /**
46
+ * WooCommerce 2.1 support for wc_enqueue_js
47
+ *
48
+ * @since 1.2.1
49
+ *
50
+ * @access public
51
+ * @param string $code
52
+ * @return void
53
+ */
54
+ public static function wc_enqueue_js( $code ) {
55
+ global $wc_queued_js;
56
 
57
+ if ( function_exists( 'wc_enqueue_js' ) && empty( $wc_queued_js ) ) {
58
+ wc_enqueue_js( $code );
59
+ } else {
60
+ $wc_queued_js = $code . "\n" . $wc_queued_js;
61
+ }
62
  }
 
63
 
64
+ /**
65
+ * Validate URLs, make relative URLs absolute
66
+ *
67
+ * @access public
68
+ * @param string $url
69
+ * @return string
70
+ */
71
+ public static function make_url( $url ) {
72
+ if (
73
+ // The first check incorrectly fails for URLs with special chars.
74
+ ! filter_var( $url, FILTER_VALIDATE_URL ) &&
75
+ substr( $url, 0, 4 ) !== 'http'
76
+ ) {
77
+ return get_site_url() . $url;
78
+ } else {
79
+ return $url;
80
+ }
81
  }
 
82
 
83
+ /**
84
+ * Product ID for Dynamic Ads on Facebook can be SKU or wc_post_id_123
85
+ * This function should be used to get retailer_id based on a WC_Product
86
+ * from WooCommerce
87
+ *
88
+ * @access public
89
+ * @param WC_Product|WC_Facebook_Product $woo_product
90
+ * @return string
 
 
 
 
 
 
 
91
  */
92
+ public static function get_fb_retailer_id( $woo_product ) {
93
+ $woo_id = $woo_product->get_id();
94
+
95
+ /*
96
+ * Call $woo_product->get_id() instead of ->id to account for Variable
97
+ * products, which have their own variant_ids.
98
+ */
99
+ $fb_retailer_id = $woo_product->get_sku() ?
100
+ $woo_product->get_sku() . '_' . $woo_id :
101
+ self::FB_RETAILER_ID_PREFIX . $woo_id;
102
+
103
+ /**
104
+ * Filter facebook retailer id value.
105
+ * This can be used to match retailer id generated by other Facebook plugins.
106
+ *
107
+ * @since 2.6.12
108
+ * @param string Facebook Retailer ID.
109
+ * @param WC_Product WooCommerce product.
110
+ */
111
+ return apply_filters( 'wc_facebook_fb_retailer_id', $fb_retailer_id, $woo_product );
112
+ }
113
 
114
  /**
115
+ * Return categories for products/pixel
 
116
  *
117
+ * @access public
118
+ * @param String $id
119
+ * @return Array
120
  */
121
+ public static function get_product_categories( $wpid ) {
122
+ $category_path = wp_get_post_terms(
123
+ $wpid,
124
+ 'product_cat',
125
+ array( 'fields' => 'all' )
126
+ );
127
+ $content_category = array_values(
128
+ array_map(
129
+ function( $item ) {
130
+ return $item->name;
131
+ },
132
+ $category_path
133
+ )
134
+ );
135
+ $content_category_slice = array_slice( $content_category, -1 );
136
+ $categories =
137
+ empty( $content_category ) ? '""' : implode( ', ', $content_category );
138
+ return array(
139
+ 'name' => array_pop( $content_category_slice ),
140
+ 'categories' => $categories,
141
+ );
142
+ }
143
 
144
+ /**
145
+ * Returns content id to match on for Pixel fires.
146
+ *
147
+ * @access public
148
+ * @param WC_Product $woo_product
149
+ * @return array
150
+ */
151
+ public static function get_fb_content_ids( $woo_product ) {
152
+ return array( self::get_fb_retailer_id( $woo_product ) );
153
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
 
155
+ /**
156
+ * Clean up strings for FB Graph POSTing.
157
+ * This function should will:
158
+ * 1. Replace newlines chars/nbsp with a real space
159
+ * 2. strip_tags()
160
+ * 3. trim()
161
+ *
162
+ * @access public
163
+ * @param String string
164
+ * @return string
165
+ */
166
+ public static function clean_string( $string ) {
167
+
168
+ /**
169
+ * Filters whether the shortcodes should be applied for a string when syncing a product or be stripped out.
170
+ *
171
+ * @since 2.6.19
172
+ *
173
+ * @param bool $apply_shortcodes Shortcodes are applied if set to `true` and stripped out if set to `false`.
174
+ * @param string $string String to clean up.
175
+ */
176
+ $apply_shortcodes = apply_filters( 'wc_facebook_string_apply_shortcodes', false, $string );
177
+ if ( $apply_shortcodes ) {
178
+ // Apply active shortcodes
179
+ $string = do_shortcode( $string );
180
+ } else {
181
+ // Strip out active shortcodes
182
+ $string = strip_shortcodes( $string );
183
+ }
184
 
185
+ $string = str_replace( array( '&amp%3B', '&amp;' ), '&', $string );
186
+ $string = str_replace( array( "\r", '&nbsp;', "\t" ), ' ', $string );
187
+ $string = wp_strip_all_tags( $string, false ); // true == remove line breaks
188
+ return $string;
189
+ }
 
 
 
 
 
 
 
190
 
191
  /**
192
+ * Returns flat array of woo IDs for variable products, or
193
+ * an array with a single woo ID for simple products.
194
  *
195
+ * @access public
196
+ * @param WC_Product|WC_Facebook_Product $woo_product
197
+ * @return array
 
198
  */
199
+ public static function get_product_array( $woo_product ) {
200
+ $result = [];
201
+ if ( self::is_variable_type( $woo_product->get_type() ) ) {
202
+ foreach ( $woo_product->get_children() as $item_id ) {
203
+ array_push( $result, $item_id );
204
+ }
205
+ return $result;
206
+ } else {
207
+ return array( $woo_product->get_id() );
208
+ }
209
  }
210
 
211
+ /**
212
+ * Returns true if WooCommerce plugin found.
213
+ *
214
+ * @access public
215
+ * @return bool
216
+ */
217
+ public static function isWoocommerceIntegration() {
218
+ return class_exists( 'WooCommerce' );
219
+ }
220
 
221
+ /**
222
+ * Returns integration dependent name.
223
+ *
224
+ * @access public
225
+ * @return string
226
+ */
227
+ public static function getIntegrationName() {
228
+ if ( self::isWoocommerceIntegration() ) {
229
+ return 'WooCommerce';
230
+ } else {
231
+ return 'WordPress';
 
 
232
  }
 
 
 
233
  }
 
234
 
235
+ /**
236
+ * Returns user info for the current WP user.
237
+ *
238
+ * @access public
239
+ * @param AAMSettings $aam_settings
240
+ * @return array
241
+ */
242
+ public static function get_user_info( $aam_settings ) {
243
+ $current_user = wp_get_current_user();
244
+ if ( 0 === $current_user->ID || $aam_settings == null || ! $aam_settings->get_enable_automatic_matching() ) {
245
+ // User not logged in or pixel not configured with automatic advance matching
246
+ return [];
247
+ } else {
248
+ // Keys documented in
249
+ // https://developers.facebook.com/docs/facebook-pixel/advanced/advanced-matching
250
+ $user_data = array(
251
+ 'em' => $current_user->user_email,
252
+ 'fn' => $current_user->user_firstname,
253
+ 'ln' => $current_user->user_lastname,
254
+ 'external_id' => strval( $current_user->ID ),
255
+ );
256
+ $user_id = $current_user->ID;
257
+ $user_data['ct'] = get_user_meta( $user_id, 'billing_city', true );
258
+ $user_data['zp'] = get_user_meta( $user_id, 'billing_postcode', true );
259
+ $user_data['country'] = get_user_meta( $user_id, 'billing_country', true );
260
+ $user_data['st'] = get_user_meta( $user_id, 'billing_state', true );
261
+ $user_data['ph'] = get_user_meta( $user_id, 'billing_phone', true );
262
+ // Each field that is not present in AAM settings or is empty is deleted from user data
263
+ foreach ( $user_data as $field => $value ) {
264
+ if ( $value === null || $value === ''
265
+ || ! in_array( $field, $aam_settings->get_enabled_automatic_matching_fields() )
266
+ ) {
267
+ unset( $user_data[ $field ] );
268
+ }
269
+ }
270
+ // Country is a special case, it is returned as country in AAM settings
271
+ // But used as cn in pixel
272
+ if ( array_key_exists( 'country', $user_data ) ) {
273
+ $country = $user_data['country'];
274
+ $user_data['cn'] = $country;
275
+ unset( $user_data['country'] );
276
+ }
277
+ $user_data = Normalizer::normalize_array( $user_data, true );
278
+ return $user_data;
279
+ }
280
  }
 
281
 
282
+ /**
283
+ * Utility function for development logging.
284
+ */
285
+ public static function fblog(
286
+ $message,
287
+ $object = [],
288
+ $error = false,
289
+ $ems = '' ) {
290
+ if ( $error ) {
291
+ $object['plugin_version'] = self::PLUGIN_VERSION;
292
+ $object['php_version'] = phpversion();
293
+ }
294
+ $message = json_encode(
295
+ array(
296
+ 'message' => $message,
297
+ 'object' => $object,
298
+ )
 
 
 
299
  );
300
+ $ems = $ems ?: self::$ems;
301
+ if ( $ems ) {
302
+ try {
303
+ facebook_for_woocommerce()->get_api()->log($ems, $message, $error);
304
+ } catch ( ApiException $e ) {
305
+ $message = sprintf( 'There was an error trying to log: %s', $e->getMessage() );
306
+ facebook_for_woocommerce()->log( $message );
 
 
 
 
 
307
  }
308
+ } else {
309
+ error_log(
310
+ 'external merchant setting is null, something wrong here: ' .
311
+ $message
312
+ );
313
  }
314
+ }
315
+
316
+ /**
317
+ * Utility function for development Tip Events logging.
318
+ */
319
+ public static function tip_events_log( $tip_id, $channel_id, $event, $ems = '' ) {
320
+ $ems = $ems ?: self::$ems;
321
+ if ( $ems ) {
322
+ try {
323
+ facebook_for_woocommerce()->get_api()->log_tip_event($tip_id, $channel_id, $event);
324
+ } catch ( ApiException $e ) {
325
+ $message = sprintf( 'There was an error while logging tip events: %s', $e->getMessage() );
326
+ facebook_for_woocommerce()->log( $message );
327
+ }
328
+ } else {
329
+ error_log( 'external merchant setting is null' );
330
  }
 
 
331
  }
 
332
 
333
+ public static function is_variation_type( $type ) {
334
+ return $type == 'variation' || $type == 'subscription_variation';
 
 
 
 
 
 
 
 
 
335
  }
336
+
337
+ public static function is_variable_type( $type ) {
338
+ return $type == 'variable' || $type == 'variable-subscription';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
339
  }
 
340
 
341
+ public static function check_woo_ajax_permissions( $action_text, $die ) {
342
+ if ( ! current_user_can( 'manage_woocommerce' ) ) {
343
+ self::log(
344
+ 'Non manage_woocommerce user attempting to' . $action_text . '!',
345
+ [],
346
+ true
347
+ );
348
+ if ( $die ) {
349
+ wp_die();
350
+ }
351
+ return false;
352
  }
353
+ return true;
 
354
  }
 
355
 
356
+ /**
357
+ * Returns true if id is a positive non-zero integer
358
+ *
359
+ * @access public
360
+ * @param string $pixel_id
361
+ * @return bool
362
+ */
363
+ public static function is_valid_id( $pixel_id ) {
364
+ return isset( $pixel_id ) && is_numeric( $pixel_id ) && (int) $pixel_id > 0;
365
+ }
366
 
367
+ /**
368
+ * Helper function to query posts.
369
+ */
370
+ public static function get_wp_posts(
371
+ $product_group_id = null,
372
+ $compare_condition = null,
373
+ $post_type = 'product' ) {
374
+ $args = array(
375
+ 'fields' => 'ids',
376
+ 'meta_query' => array(
377
+ ( ( $product_group_id ) ?
378
+ array(
379
+ 'key' => $product_group_id,
380
+ 'compare' => $compare_condition,
381
+ ) : []
382
+ ),
383
+ ),
384
+ 'post_status' => 'publish',
385
+ 'post_type' => $post_type,
386
+ 'posts_per_page' => -1,
387
  );
388
+ return get_posts( $args );
 
 
 
389
  }
 
 
390
 
391
+ /**
392
+ * Helper log function for debugging
393
+ */
394
+ public static function log( $message ) {
 
 
 
 
 
 
395
 
396
+ // if this file is being included outside the plugin, or the plugin setting is disabled
397
+ if ( ! function_exists( 'facebook_for_woocommerce' ) || ! facebook_for_woocommerce()->get_integration()->is_debug_mode_enabled() ) {
398
+ return;
399
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
400
 
401
+ if ( is_array( $message ) || is_object( $message ) ) {
402
+ $message = json_encode( $message );
403
+ } else {
404
+ $message = sanitize_textarea_field( $message );
405
+ }
406
 
407
+ facebook_for_woocommerce()->log( $message );
 
 
408
  }
409
 
410
+ // Return store name with sanitized apostrophe
411
+ public static function get_store_name() {
412
+ if ( self::$store_name ) {
413
+ return self::$store_name;
414
+ }
415
+ $name = trim(
416
+ str_replace(
417
+ "'",
418
+ "\u{2019}",
419
+ html_entity_decode(
420
+ get_bloginfo( 'name' ),
421
+ ENT_QUOTES,
422
+ 'UTF-8'
423
+ )
424
+ )
425
+ );
426
+ if ( $name ) {
427
+ self::$store_name = $name;
428
+ return $name;
429
+ }
430
+ // Fallback to site url
431
+ $url = get_site_url();
432
+ if ( $url ) {
433
+ self::$store_name = parse_url( $url, PHP_URL_HOST );
434
+ return self::$store_name;
435
+ }
436
+ // If site url doesn't exist, fall back to http host.
437
+ if ( $_SERVER['HTTP_HOST'] ) {
438
+ self::$store_name = $_SERVER['HTTP_HOST'];
439
+ return self::$store_name;
440
+ }
441
+
442
+ // If http host doesn't exist, fall back to local host name.
443
+ $url = gethostname();
444
+ self::$store_name = $url;
445
+ return ( self::$store_name ) ? ( self::$store_name ) : 'A Store Has No Name';
446
  }
447
 
 
 
448
 
449
+ /**
450
+ * Get visible name for variant attribute rather than the slug
451
+ *
452
+ * @param int $wp_id Post ID.
453
+ * @param string $label Attribute label.
454
+ * @param string $default_value Default value to use if the term has no name.
455
+ * @return string Term name or the default value.
456
+ */
457
+ public static function get_variant_option_name( $wp_id, $label, $default_value ) {
458
+ $meta = get_post_meta( $wp_id, $label, true );
459
+ $attribute_name = str_replace( 'attribute_', '', $label );
460
+ $term = get_term_by( 'slug', $meta, $attribute_name );
461
+ return $term && $term->name ? $term->name : $default_value;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  }
463
 
464
+ /**
465
+ * Get all products for synchronization tasks.
466
+ *
467
+ * Warning: While changing this code please make sure that it scales properly.
468
+ * Sites with big product catalogs should not experience memory problems.
469
+ *
470
+ * @return array IDs of all product for synchronization.
471
+ */
472
+ public static function get_all_product_ids_for_sync() {
473
+ // Get all published products ids. This includes parent products of variations.
474
+ $product_args = array(
475
+ 'fields' => 'ids',
476
+ 'post_status' => 'publish',
477
+ 'post_type' => 'product',
478
+ 'posts_per_page' => -1,
479
+ );
480
+ $product_ids = get_posts( $product_args );
481
+
482
+ // Get all variations ids with their parents ids.
483
+ $variation_args = array(
484
+ 'fields' => 'id=>parent',
485
+ 'post_status' => 'publish',
486
+ 'post_type' => 'product_variation',
487
+ 'posts_per_page' => -1,
488
+ );
489
+ $variation_products = get_posts( $variation_args );
490
 
491
+ /*
492
+ * Collect all parent products.
493
+ * Exclude variations which parents are not 'publish'.
494
+ */
495
+ $parent_product_ids = [];
496
+ foreach ( $variation_products as $post_id => $parent_id ) {
497
+ /*
498
+ * Keep track of all parents to remove them from the list of products to sync.
499
+ * Use key to automatically remove duplicated items.
500
+ */
501
+ $parent_product_ids[ $parent_id ] = true;
502
+
503
+ // Include variations with published parents only.
504
+ if ( in_array( $parent_id, $product_ids ) ) {
505
+ $product_ids[] = $post_id;
506
+ }
507
+ }
508
 
509
+ // Remove parent products because those can't be represented as Product Items.
510
+ return array_diff( $product_ids, array_keys( $parent_product_ids ) );
511
+ }
 
 
 
 
 
 
 
 
 
 
 
512
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
513
 
514
  /*
515
+ * Change variant product field name from Woo taxonomy to FB name
 
516
  */
517
+ public static function sanitize_variant_name( $name, $use_custom_data = true ) {
518
+ $name = str_replace( array( 'attribute_', 'pa_' ), '', strtolower( $name ) );
 
 
 
 
 
519
 
520
+ // British spelling
521
+ if ( $name === self::FB_VARIANT_COLOUR ) {
522
+ $name = self::FB_VARIANT_COLOR;
523
  }
 
 
 
 
 
 
524
 
525
+ if ( $use_custom_data ) {
526
+ switch ( $name ) {
527
+ case self::FB_VARIANT_SIZE:
528
+ case self::FB_VARIANT_COLOR:
529
+ case self::FB_VARIANT_GENDER:
530
+ case self::FB_VARIANT_PATTERN:
531
+ break;
532
+ default:
533
+ $name = 'custom_data:' . strtolower( $name );
534
+ break;
535
+ }
536
+ }
537
 
538
+ return $name;
 
 
539
  }
540
 
541
+ public static function validateGender( $gender ) {
542
+ if ( $gender && ! isset( self::$validGenderArray[ $gender ] ) ) {
543
+ $first_char = strtolower( substr( $gender, 0, 1 ) );
544
+ // Men, Man, Boys
545
+ if ( $first_char === 'm' || $first_char === 'b' ) {
546
+ return 'male';
547
+ }
548
+ // Women, Woman, Female, Ladies
549
+ if ( $first_char === 'w' || $first_char === 'f' || $first_char === 'l' ) {
550
+ return 'female';
551
+ }
552
+ if ( $first_char === 'u' ) {
553
+ return 'unisex';
554
+ }
555
+ if ( strlen( $gender ) >= 3 ) {
556
+ $gender = strtolower( substr( $gender, 0, 3 ) );
557
+ if ( $gender === 'gir' || $gender === 'her' ) {
558
+ return 'female';
559
+ }
560
+ if ( $gender === 'him' || $gender === 'his' || $gender == 'guy' ) {
561
+ return 'male';
562
+ }
563
+ }
564
+ return null;
565
  }
566
+ return $gender;
567
  }
568
 
569
+ public static function get_fbid_post_meta( $wp_id, $fbid_type ) {
570
+ return get_post_meta( $wp_id, $fbid_type, true );
571
+ }
572
 
573
+ public static function is_all_caps( $value ) {
574
+ if ( $value === null || $value === '' ) {
575
+ return true;
 
 
 
576
  }
577
+ if ( preg_match( '/[^\\p{Common}\\p{Latin}]/u', $value ) ) {
578
+ // Contains non-western characters
579
+ // So, it can't be all uppercase
580
+ return false;
581
  }
582
+ $latin_string = preg_replace( '/[^\\p{Latin}]/u', '', $value );
583
+ if ( $latin_string === '' ) {
584
+ // Symbols only
585
+ return true;
586
  }
587
+ return strtoupper( $latin_string ) === $latin_string;
 
 
 
 
 
 
 
 
 
588
  }
 
 
589
 
590
+ public static function decode_json( $json_string, $assoc = false ) {
591
+ // Plugin requires 5.6.0 but for some user use 5.5.9 JSON_BIGINT_AS_STRING
592
+ // will cause 502 issue when redirect.
593
+ return version_compare( phpversion(), '5.6.0' ) >= 0
594
+ ? json_decode( $json_string, $assoc, 512, JSON_BIGINT_AS_STRING )
595
+ : json_decode( $json_string, $assoc, 512 );
 
 
 
 
 
 
596
  }
 
 
 
 
 
 
 
597
 
598
+ public static function set_test_fail_reason( $msg, $trace ) {
599
+ $reason_msg = get_transient( 'facebook_plugin_test_fail' );
600
+ if ( $reason_msg ) {
601
+ $msg = $reason_msg . PHP_EOL . $msg;
602
+ }
603
+ set_transient( 'facebook_plugin_test_fail', $msg );
604
+ set_transient( 'facebook_plugin_test_stack_trace', $trace );
605
+ }
606
 
607
+ /**
608
+ * Helper function to check time cap.
609
+ */
610
+ public static function check_time_cap( $from, $date_cap ) {
611
+ if ( $from == null ) {
612
+ return true;
613
+ }
614
+ $now = new DateTime( current_time( 'mysql' ) );
615
+ $diff_in_day = $now->diff( new DateTime( $from ) )->format( '%a' );
616
+ return is_numeric( $diff_in_day ) && (int) $diff_in_day > $date_cap;
617
  }
 
 
 
618
 
619
+ public static function get_cached_best_tip() {
620
+ $cached_best_tip = self::decode_json(
621
+ get_option( 'fb_info_banner_last_best_tip', '' )
622
+ );
623
+ return $cached_best_tip;
 
624
  }
 
 
 
625
  }
626
 
627
+ endif;
 
 
 
 
 
 
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: facebook, automattic, woothemes
3
  Tags: facebook, shop, catalog, advertise, pixel, product
4
  Requires at least: 4.4
5
  Tested up to: 6.1
6
- Stable tag: 3.0.4
7
  Requires PHP: 5.6 or greater
8
  MySQL: 5.6 or greater
9
  License: GPLv2 or later
@@ -39,6 +39,17 @@ When opening a bug on GitHub, please give us as many details as possible.
39
 
40
  == Changelog ==
41
 
 
 
 
 
 
 
 
 
 
 
 
42
  = 3.0.4 - 2022-11-21 =
43
  * Dev - Ensure return value matches method signature.
44
 
3
  Tags: facebook, shop, catalog, advertise, pixel, product
4
  Requires at least: 4.4
5
  Tested up to: 6.1
6
+ Stable tag: 3.0.5
7
  Requires PHP: 5.6 or greater
8
  MySQL: 5.6 or greater
9
  License: GPLv2 or later
39
 
40
  == Changelog ==
41
 
42
+ = 3.0.5 - 2022-11-30 =
43
+ * Add - Debug tools to help reset settings, delete background options and delete catalog products.
44
+ * Add - Inbox note about Facebook menu moved under the Marketing menu.
45
+ * Dev - Add .nvmrc file.
46
+ * Fix - Facebook Product ID is different from what Facebook ID actually is.
47
+ * Fix - Prevent class redeclaration error for class WC_Facebookcommerce_Utils.
48
+ * Fix - Prevent errors in the disconnection procedure when the user id is missing.
49
+ * Tweak - Remove Facebook Orders sync functionality.
50
+ * Tweak - Update the API version set in the fbAsyncInit script in Advertise tab.
51
+ * Tweak - Update the plugin URI in the plugin file.
52
+
53
  = 3.0.4 - 2022-11-21 =
54
  * Dev - Ensure return value matches method signature.
55
 
vendor/autoload.php CHANGED
@@ -3,23 +3,10 @@
3
  // autoload.php @generated by Composer
4
 
5
  if (PHP_VERSION_ID < 50600) {
6
- if (!headers_sent()) {
7
- header('HTTP/1.1 500 Internal Server Error');
8
- }
9
- $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
10
- if (!ini_get('display_errors')) {
11
- if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
12
- fwrite(STDERR, $err);
13
- } elseif (!headers_sent()) {
14
- echo $err;
15
- }
16
- }
17
- trigger_error(
18
- $err,
19
- E_USER_ERROR
20
- );
21
  }
22
 
23
  require_once __DIR__ . '/composer/autoload_real.php';
24
 
25
- return ComposerAutoloaderInitf27dc863d9a3226468fcf31dab3c9197::getLoader();
3
  // autoload.php @generated by Composer
4
 
5
  if (PHP_VERSION_ID < 50600) {
6
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
7
+ exit(1);
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  }
9
 
10
  require_once __DIR__ . '/composer/autoload_real.php';
11
 
12
+ return ComposerAutoloaderInitea9949fe138c408a8667af28726c644c::getLoader();
vendor/composer/autoload_classmap.php CHANGED
@@ -139,16 +139,6 @@ return array(
139
  'WooCommerce\\Facebook\\API\\FBE\\Installation\\Request' => $baseDir . '/includes/API/FBE/Installation/Request.php',
140
  'WooCommerce\\Facebook\\API\\Log\\Create\\Request' => $baseDir . '/includes/API/Log/Create/Request.php',
141
  'WooCommerce\\Facebook\\API\\Log\\Create\\Response' => $baseDir . '/includes/API/Log/Create/Response.php',
142
- 'WooCommerce\\Facebook\\API\\Orders\\Abstract_Request' => $baseDir . '/includes/API/Orders/Abstract_Request.php',
143
- 'WooCommerce\\Facebook\\API\\Orders\\Acknowledge\\Request' => $baseDir . '/includes/API/Orders/Acknowledge/Request.php',
144
- 'WooCommerce\\Facebook\\API\\Orders\\Cancel\\Request' => $baseDir . '/includes/API/Orders/Cancel/Request.php',
145
- 'WooCommerce\\Facebook\\API\\Orders\\Fulfillment\\Request' => $baseDir . '/includes/API/Orders/Fulfillment/Request.php',
146
- 'WooCommerce\\Facebook\\API\\Orders\\Order' => $baseDir . '/includes/API/Orders/Order.php',
147
- 'WooCommerce\\Facebook\\API\\Orders\\Read\\Request' => $baseDir . '/includes/API/Orders/Read/Request.php',
148
- 'WooCommerce\\Facebook\\API\\Orders\\Read\\Response' => $baseDir . '/includes/API/Orders/Read/Response.php',
149
- 'WooCommerce\\Facebook\\API\\Orders\\Refund\\Request' => $baseDir . '/includes/API/Orders/Refund/Request.php',
150
- 'WooCommerce\\Facebook\\API\\Orders\\Request' => $baseDir . '/includes/API/Orders/Request.php',
151
- 'WooCommerce\\Facebook\\API\\Orders\\Response' => $baseDir . '/includes/API/Orders/Response.php',
152
  'WooCommerce\\Facebook\\API\\Pages\\Read\\Request' => $baseDir . '/includes/API/Pages/Read/Request.php',
153
  'WooCommerce\\Facebook\\API\\Pages\\Read\\Response' => $baseDir . '/includes/API/Pages/Read/Response.php',
154
  'WooCommerce\\Facebook\\API\\Pixel\\Events\\Request' => $baseDir . '/includes/API/Pixel/Events/Request.php',
@@ -203,6 +193,7 @@ return array(
203
  'WooCommerce\\Facebook\\Admin\\Abstract_Settings_Screen' => $baseDir . '/includes/Admin/Abstract_Settings_Screen.php',
204
  'WooCommerce\\Facebook\\Admin\\Enhanced_Catalog_Attribute_Fields' => $baseDir . '/includes/Admin/Enhanced_Catalog_Attribute_Fields.php',
205
  'WooCommerce\\Facebook\\Admin\\Google_Product_Category_Field' => $baseDir . '/includes/Admin/Google_Product_Category_Field.php',
 
206
  'WooCommerce\\Facebook\\Admin\\Product_Categories' => $baseDir . '/includes/Admin/Product_Categories.php',
207
  'WooCommerce\\Facebook\\Admin\\Product_Sets' => $baseDir . '/includes/Admin/Product_Sets.php',
208
  'WooCommerce\\Facebook\\Admin\\Product_Sync_Meta_Box' => $baseDir . '/includes/Admin/Product_Sync_Meta_Box.php',
@@ -215,7 +206,6 @@ return array(
215
  'WooCommerce\\Facebook\\Admin\\Settings_Screens\\Product_Sync' => $baseDir . '/includes/Admin/Settings_Screens/Product_Sync.php',
216
  'WooCommerce\\Facebook\\Admin\\Tasks\\Setup' => $baseDir . '/includes/Admin/Tasks/Setup.php',
217
  'WooCommerce\\Facebook\\Commerce' => $baseDir . '/includes/Commerce.php',
218
- 'WooCommerce\\Facebook\\Commerce\\Orders' => $baseDir . '/includes/Commerce/Orders.php',
219
  'WooCommerce\\Facebook\\Debug\\ProfilingLogger' => $baseDir . '/includes/Debug/ProfilingLogger.php',
220
  'WooCommerce\\Facebook\\Debug\\ProfilingLoggerProcess' => $baseDir . '/includes/Debug/ProfilingLoggerProcess.php',
221
  'WooCommerce\\Facebook\\Events\\AAMSettings' => $baseDir . '/includes/Events/AAMSettings.php',
@@ -243,9 +233,11 @@ return array(
243
  'WooCommerce\\Facebook\\Integrations\\Bookings' => $baseDir . '/includes/Integrations/Bookings.php',
244
  'WooCommerce\\Facebook\\Jobs\\AbstractChainedJob' => $baseDir . '/includes/Jobs/AbstractChainedJob.php',
245
  'WooCommerce\\Facebook\\Jobs\\CleanupSkyvergeFrameworkJobOptions' => $baseDir . '/includes/Jobs/CleanupSkyvergeFrameworkJobOptions.php',
 
246
  'WooCommerce\\Facebook\\Jobs\\GenerateProductFeed' => $baseDir . '/includes/Jobs/GenerateProductFeed.php',
247
  'WooCommerce\\Facebook\\Jobs\\JobManager' => $baseDir . '/includes/Jobs/JobManager.php',
248
  'WooCommerce\\Facebook\\Jobs\\LoggingTrait' => $baseDir . '/includes/Jobs/LoggingTrait.php',
 
249
  'WooCommerce\\Facebook\\Lifecycle' => $baseDir . '/includes/Lifecycle.php',
250
  'WooCommerce\\Facebook\\Locale' => $baseDir . '/includes/Locale.php',
251
  'WooCommerce\\Facebook\\ProductSets\\Sync' => $baseDir . '/includes/ProductSets/Sync.php',
@@ -262,7 +254,7 @@ return array(
262
  'WooCommerce\\Facebook\\Products\\Sync\\Background' => $baseDir . '/includes/Products/Sync/Background.php',
263
  'WooCommerce\\Facebook\\Utilities\\Background_Handle_Virtual_Products_Variations' => $baseDir . '/includes/Utilities/Background_Handle_Virtual_Products_Variations.php',
264
  'WooCommerce\\Facebook\\Utilities\\Background_Remove_Duplicate_Visibility_Meta' => $baseDir . '/includes/Utilities/Background_Remove_Duplicate_Visibility_Meta.php',
 
265
  'WooCommerce\\Facebook\\Utilities\\Heartbeat' => $baseDir . '/includes/Utilities/Heartbeat.php',
266
- 'WooCommerce\\Facebook\\Utilities\\Shipment' => $baseDir . '/includes/Utilities/Shipment.php',
267
  'WooCommerce\\Facebook\\Utilities\\Tracker' => $baseDir . '/includes/Utilities/Tracker.php',
268
  );
139
  'WooCommerce\\Facebook\\API\\FBE\\Installation\\Request' => $baseDir . '/includes/API/FBE/Installation/Request.php',
140
  'WooCommerce\\Facebook\\API\\Log\\Create\\Request' => $baseDir . '/includes/API/Log/Create/Request.php',
141
  'WooCommerce\\Facebook\\API\\Log\\Create\\Response' => $baseDir . '/includes/API/Log/Create/Response.php',
 
 
 
 
 
 
 
 
 
 
142
  'WooCommerce\\Facebook\\API\\Pages\\Read\\Request' => $baseDir . '/includes/API/Pages/Read/Request.php',
143
  'WooCommerce\\Facebook\\API\\Pages\\Read\\Response' => $baseDir . '/includes/API/Pages/Read/Response.php',
144
  'WooCommerce\\Facebook\\API\\Pixel\\Events\\Request' => $baseDir . '/includes/API/Pixel/Events/Request.php',
193
  'WooCommerce\\Facebook\\Admin\\Abstract_Settings_Screen' => $baseDir . '/includes/Admin/Abstract_Settings_Screen.php',
194
  'WooCommerce\\Facebook\\Admin\\Enhanced_Catalog_Attribute_Fields' => $baseDir . '/includes/Admin/Enhanced_Catalog_Attribute_Fields.php',
195
  'WooCommerce\\Facebook\\Admin\\Google_Product_Category_Field' => $baseDir . '/includes/Admin/Google_Product_Category_Field.php',
196
+ 'WooCommerce\\Facebook\\Admin\\Notes\\SettingsMoved' => $baseDir . '/includes/Admin/Notes/SettingsMoved.php',
197
  'WooCommerce\\Facebook\\Admin\\Product_Categories' => $baseDir . '/includes/Admin/Product_Categories.php',
198
  'WooCommerce\\Facebook\\Admin\\Product_Sets' => $baseDir . '/includes/Admin/Product_Sets.php',
199
  'WooCommerce\\Facebook\\Admin\\Product_Sync_Meta_Box' => $baseDir . '/includes/Admin/Product_Sync_Meta_Box.php',
206
  'WooCommerce\\Facebook\\Admin\\Settings_Screens\\Product_Sync' => $baseDir . '/includes/Admin/Settings_Screens/Product_Sync.php',
207
  'WooCommerce\\Facebook\\Admin\\Tasks\\Setup' => $baseDir . '/includes/Admin/Tasks/Setup.php',
208
  'WooCommerce\\Facebook\\Commerce' => $baseDir . '/includes/Commerce.php',
 
209
  'WooCommerce\\Facebook\\Debug\\ProfilingLogger' => $baseDir . '/includes/Debug/ProfilingLogger.php',
210
  'WooCommerce\\Facebook\\Debug\\ProfilingLoggerProcess' => $baseDir . '/includes/Debug/ProfilingLoggerProcess.php',
211
  'WooCommerce\\Facebook\\Events\\AAMSettings' => $baseDir . '/includes/Events/AAMSettings.php',
233
  'WooCommerce\\Facebook\\Integrations\\Bookings' => $baseDir . '/includes/Integrations/Bookings.php',
234
  'WooCommerce\\Facebook\\Jobs\\AbstractChainedJob' => $baseDir . '/includes/Jobs/AbstractChainedJob.php',
235
  'WooCommerce\\Facebook\\Jobs\\CleanupSkyvergeFrameworkJobOptions' => $baseDir . '/includes/Jobs/CleanupSkyvergeFrameworkJobOptions.php',
236
+ 'WooCommerce\\Facebook\\Jobs\\DeleteProductsFromFBCatalog' => $baseDir . '/includes/Jobs/DeleteProductsFromFBCatalog.php',
237
  'WooCommerce\\Facebook\\Jobs\\GenerateProductFeed' => $baseDir . '/includes/Jobs/GenerateProductFeed.php',
238
  'WooCommerce\\Facebook\\Jobs\\JobManager' => $baseDir . '/includes/Jobs/JobManager.php',
239
  'WooCommerce\\Facebook\\Jobs\\LoggingTrait' => $baseDir . '/includes/Jobs/LoggingTrait.php',
240
+ 'WooCommerce\\Facebook\\Jobs\\ResetAllProductsFBSettings' => $baseDir . '/includes/Jobs/ResetAllProductsFBSettings.php',
241
  'WooCommerce\\Facebook\\Lifecycle' => $baseDir . '/includes/Lifecycle.php',
242
  'WooCommerce\\Facebook\\Locale' => $baseDir . '/includes/Locale.php',
243
  'WooCommerce\\Facebook\\ProductSets\\Sync' => $baseDir . '/includes/ProductSets/Sync.php',
254
  'WooCommerce\\Facebook\\Products\\Sync\\Background' => $baseDir . '/includes/Products/Sync/Background.php',
255
  'WooCommerce\\Facebook\\Utilities\\Background_Handle_Virtual_Products_Variations' => $baseDir . '/includes/Utilities/Background_Handle_Virtual_Products_Variations.php',
256
  'WooCommerce\\Facebook\\Utilities\\Background_Remove_Duplicate_Visibility_Meta' => $baseDir . '/includes/Utilities/Background_Remove_Duplicate_Visibility_Meta.php',
257
+ 'WooCommerce\\Facebook\\Utilities\\DebugTools' => $baseDir . '/includes/Utilities/DebugTools.php',
258
  'WooCommerce\\Facebook\\Utilities\\Heartbeat' => $baseDir . '/includes/Utilities/Heartbeat.php',
 
259
  'WooCommerce\\Facebook\\Utilities\\Tracker' => $baseDir . '/includes/Utilities/Tracker.php',
260
  );
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInitf27dc863d9a3226468fcf31dab3c9197
6
  {
7
  private static $loader;
8
 
@@ -24,12 +24,12 @@ class ComposerAutoloaderInitf27dc863d9a3226468fcf31dab3c9197
24
 
25
  require __DIR__ . '/platform_check.php';
26
 
27
- spl_autoload_register(array('ComposerAutoloaderInitf27dc863d9a3226468fcf31dab3c9197', 'loadClassLoader'), true, true);
28
  self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
29
- spl_autoload_unregister(array('ComposerAutoloaderInitf27dc863d9a3226468fcf31dab3c9197', 'loadClassLoader'));
30
 
31
  require __DIR__ . '/autoload_static.php';
32
- call_user_func(\Composer\Autoload\ComposerStaticInitf27dc863d9a3226468fcf31dab3c9197::getInitializer($loader));
33
 
34
  $loader->register(true);
35
 
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInitea9949fe138c408a8667af28726c644c
6
  {
7
  private static $loader;
8
 
24
 
25
  require __DIR__ . '/platform_check.php';
26
 
27
+ spl_autoload_register(array('ComposerAutoloaderInitea9949fe138c408a8667af28726c644c', 'loadClassLoader'), true, true);
28
  self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
29
+ spl_autoload_unregister(array('ComposerAutoloaderInitea9949fe138c408a8667af28726c644c', 'loadClassLoader'));
30
 
31
  require __DIR__ . '/autoload_static.php';
32
+ call_user_func(\Composer\Autoload\ComposerStaticInitea9949fe138c408a8667af28726c644c::getInitializer($loader));
33
 
34
  $loader->register(true);
35
 
vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInitf27dc863d9a3226468fcf31dab3c9197
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'W' =>
@@ -170,16 +170,6 @@ class ComposerStaticInitf27dc863d9a3226468fcf31dab3c9197
170
  'WooCommerce\\Facebook\\API\\FBE\\Installation\\Request' => __DIR__ . '/../..' . '/includes/API/FBE/Installation/Request.php',
171
  'WooCommerce\\Facebook\\API\\Log\\Create\\Request' => __DIR__ . '/../..' . '/includes/API/Log/Create/Request.php',
172
  'WooCommerce\\Facebook\\API\\Log\\Create\\Response' => __DIR__ . '/../..' . '/includes/API/Log/Create/Response.php',
173
- 'WooCommerce\\Facebook\\API\\Orders\\Abstract_Request' => __DIR__ . '/../..' . '/includes/API/Orders/Abstract_Request.php',
174
- 'WooCommerce\\Facebook\\API\\Orders\\Acknowledge\\Request' => __DIR__ . '/../..' . '/includes/API/Orders/Acknowledge/Request.php',
175
- 'WooCommerce\\Facebook\\API\\Orders\\Cancel\\Request' => __DIR__ . '/../..' . '/includes/API/Orders/Cancel/Request.php',
176
- 'WooCommerce\\Facebook\\API\\Orders\\Fulfillment\\Request' => __DIR__ . '/../..' . '/includes/API/Orders/Fulfillment/Request.php',
177
- 'WooCommerce\\Facebook\\API\\Orders\\Order' => __DIR__ . '/../..' . '/includes/API/Orders/Order.php',
178
- 'WooCommerce\\Facebook\\API\\Orders\\Read\\Request' => __DIR__ . '/../..' . '/includes/API/Orders/Read/Request.php',
179
- 'WooCommerce\\Facebook\\API\\Orders\\Read\\Response' => __DIR__ . '/../..' . '/includes/API/Orders/Read/Response.php',
180
- 'WooCommerce\\Facebook\\API\\Orders\\Refund\\Request' => __DIR__ . '/../..' . '/includes/API/Orders/Refund/Request.php',
181
- 'WooCommerce\\Facebook\\API\\Orders\\Request' => __DIR__ . '/../..' . '/includes/API/Orders/Request.php',
182
- 'WooCommerce\\Facebook\\API\\Orders\\Response' => __DIR__ . '/../..' . '/includes/API/Orders/Response.php',
183
  'WooCommerce\\Facebook\\API\\Pages\\Read\\Request' => __DIR__ . '/../..' . '/includes/API/Pages/Read/Request.php',
184
  'WooCommerce\\Facebook\\API\\Pages\\Read\\Response' => __DIR__ . '/../..' . '/includes/API/Pages/Read/Response.php',
185
  'WooCommerce\\Facebook\\API\\Pixel\\Events\\Request' => __DIR__ . '/../..' . '/includes/API/Pixel/Events/Request.php',
@@ -234,6 +224,7 @@ class ComposerStaticInitf27dc863d9a3226468fcf31dab3c9197
234
  'WooCommerce\\Facebook\\Admin\\Abstract_Settings_Screen' => __DIR__ . '/../..' . '/includes/Admin/Abstract_Settings_Screen.php',
235
  'WooCommerce\\Facebook\\Admin\\Enhanced_Catalog_Attribute_Fields' => __DIR__ . '/../..' . '/includes/Admin/Enhanced_Catalog_Attribute_Fields.php',
236
  'WooCommerce\\Facebook\\Admin\\Google_Product_Category_Field' => __DIR__ . '/../..' . '/includes/Admin/Google_Product_Category_Field.php',
 
237
  'WooCommerce\\Facebook\\Admin\\Product_Categories' => __DIR__ . '/../..' . '/includes/Admin/Product_Categories.php',
238
  'WooCommerce\\Facebook\\Admin\\Product_Sets' => __DIR__ . '/../..' . '/includes/Admin/Product_Sets.php',
239
  'WooCommerce\\Facebook\\Admin\\Product_Sync_Meta_Box' => __DIR__ . '/../..' . '/includes/Admin/Product_Sync_Meta_Box.php',
@@ -246,7 +237,6 @@ class ComposerStaticInitf27dc863d9a3226468fcf31dab3c9197
246
  'WooCommerce\\Facebook\\Admin\\Settings_Screens\\Product_Sync' => __DIR__ . '/../..' . '/includes/Admin/Settings_Screens/Product_Sync.php',
247
  'WooCommerce\\Facebook\\Admin\\Tasks\\Setup' => __DIR__ . '/../..' . '/includes/Admin/Tasks/Setup.php',
248
  'WooCommerce\\Facebook\\Commerce' => __DIR__ . '/../..' . '/includes/Commerce.php',
249
- 'WooCommerce\\Facebook\\Commerce\\Orders' => __DIR__ . '/../..' . '/includes/Commerce/Orders.php',
250
  'WooCommerce\\Facebook\\Debug\\ProfilingLogger' => __DIR__ . '/../..' . '/includes/Debug/ProfilingLogger.php',
251
  'WooCommerce\\Facebook\\Debug\\ProfilingLoggerProcess' => __DIR__ . '/../..' . '/includes/Debug/ProfilingLoggerProcess.php',
252
  'WooCommerce\\Facebook\\Events\\AAMSettings' => __DIR__ . '/../..' . '/includes/Events/AAMSettings.php',
@@ -274,9 +264,11 @@ class ComposerStaticInitf27dc863d9a3226468fcf31dab3c9197
274
  'WooCommerce\\Facebook\\Integrations\\Bookings' => __DIR__ . '/../..' . '/includes/Integrations/Bookings.php',
275
  'WooCommerce\\Facebook\\Jobs\\AbstractChainedJob' => __DIR__ . '/../..' . '/includes/Jobs/AbstractChainedJob.php',
276
  'WooCommerce\\Facebook\\Jobs\\CleanupSkyvergeFrameworkJobOptions' => __DIR__ . '/../..' . '/includes/Jobs/CleanupSkyvergeFrameworkJobOptions.php',
 
277
  'WooCommerce\\Facebook\\Jobs\\GenerateProductFeed' => __DIR__ . '/../..' . '/includes/Jobs/GenerateProductFeed.php',
278
  'WooCommerce\\Facebook\\Jobs\\JobManager' => __DIR__ . '/../..' . '/includes/Jobs/JobManager.php',
279
  'WooCommerce\\Facebook\\Jobs\\LoggingTrait' => __DIR__ . '/../..' . '/includes/Jobs/LoggingTrait.php',
 
280
  'WooCommerce\\Facebook\\Lifecycle' => __DIR__ . '/../..' . '/includes/Lifecycle.php',
281
  'WooCommerce\\Facebook\\Locale' => __DIR__ . '/../..' . '/includes/Locale.php',
282
  'WooCommerce\\Facebook\\ProductSets\\Sync' => __DIR__ . '/../..' . '/includes/ProductSets/Sync.php',
@@ -293,17 +285,17 @@ class ComposerStaticInitf27dc863d9a3226468fcf31dab3c9197
293
  'WooCommerce\\Facebook\\Products\\Sync\\Background' => __DIR__ . '/../..' . '/includes/Products/Sync/Background.php',
294
  'WooCommerce\\Facebook\\Utilities\\Background_Handle_Virtual_Products_Variations' => __DIR__ . '/../..' . '/includes/Utilities/Background_Handle_Virtual_Products_Variations.php',
295
  'WooCommerce\\Facebook\\Utilities\\Background_Remove_Duplicate_Visibility_Meta' => __DIR__ . '/../..' . '/includes/Utilities/Background_Remove_Duplicate_Visibility_Meta.php',
 
296
  'WooCommerce\\Facebook\\Utilities\\Heartbeat' => __DIR__ . '/../..' . '/includes/Utilities/Heartbeat.php',
297
- 'WooCommerce\\Facebook\\Utilities\\Shipment' => __DIR__ . '/../..' . '/includes/Utilities/Shipment.php',
298
  'WooCommerce\\Facebook\\Utilities\\Tracker' => __DIR__ . '/../..' . '/includes/Utilities/Tracker.php',
299
  );
300
 
301
  public static function getInitializer(ClassLoader $loader)
302
  {
303
  return \Closure::bind(function () use ($loader) {
304
- $loader->prefixLengthsPsr4 = ComposerStaticInitf27dc863d9a3226468fcf31dab3c9197::$prefixLengthsPsr4;
305
- $loader->prefixDirsPsr4 = ComposerStaticInitf27dc863d9a3226468fcf31dab3c9197::$prefixDirsPsr4;
306
- $loader->classMap = ComposerStaticInitf27dc863d9a3226468fcf31dab3c9197::$classMap;
307
 
308
  }, null, ClassLoader::class);
309
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInitea9949fe138c408a8667af28726c644c
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'W' =>
170
  'WooCommerce\\Facebook\\API\\FBE\\Installation\\Request' => __DIR__ . '/../..' . '/includes/API/FBE/Installation/Request.php',
171
  'WooCommerce\\Facebook\\API\\Log\\Create\\Request' => __DIR__ . '/../..' . '/includes/API/Log/Create/Request.php',
172
  'WooCommerce\\Facebook\\API\\Log\\Create\\Response' => __DIR__ . '/../..' . '/includes/API/Log/Create/Response.php',
 
 
 
 
 
 
 
 
 
 
173
  'WooCommerce\\Facebook\\API\\Pages\\Read\\Request' => __DIR__ . '/../..' . '/includes/API/Pages/Read/Request.php',
174
  'WooCommerce\\Facebook\\API\\Pages\\Read\\Response' => __DIR__ . '/../..' . '/includes/API/Pages/Read/Response.php',
175
  'WooCommerce\\Facebook\\API\\Pixel\\Events\\Request' => __DIR__ . '/../..' . '/includes/API/Pixel/Events/Request.php',
224
  'WooCommerce\\Facebook\\Admin\\Abstract_Settings_Screen' => __DIR__ . '/../..' . '/includes/Admin/Abstract_Settings_Screen.php',
225
  'WooCommerce\\Facebook\\Admin\\Enhanced_Catalog_Attribute_Fields' => __DIR__ . '/../..' . '/includes/Admin/Enhanced_Catalog_Attribute_Fields.php',
226
  'WooCommerce\\Facebook\\Admin\\Google_Product_Category_Field' => __DIR__ . '/../..' . '/includes/Admin/Google_Product_Category_Field.php',
227
+ 'WooCommerce\\Facebook\\Admin\\Notes\\SettingsMoved' => __DIR__ . '/../..' . '/includes/Admin/Notes/SettingsMoved.php',
228
  'WooCommerce\\Facebook\\Admin\\Product_Categories' => __DIR__ . '/../..' . '/includes/Admin/Product_Categories.php',
229
  'WooCommerce\\Facebook\\Admin\\Product_Sets' => __DIR__ . '/../..' . '/includes/Admin/Product_Sets.php',
230
  'WooCommerce\\Facebook\\Admin\\Product_Sync_Meta_Box' => __DIR__ . '/../..' . '/includes/Admin/Product_Sync_Meta_Box.php',
237
  'WooCommerce\\Facebook\\Admin\\Settings_Screens\\Product_Sync' => __DIR__ . '/../..' . '/includes/Admin/Settings_Screens/Product_Sync.php',
238
  'WooCommerce\\Facebook\\Admin\\Tasks\\Setup' => __DIR__ . '/../..' . '/includes/Admin/Tasks/Setup.php',
239
  'WooCommerce\\Facebook\\Commerce' => __DIR__ . '/../..' . '/includes/Commerce.php',
 
240
  'WooCommerce\\Facebook\\Debug\\ProfilingLogger' => __DIR__ . '/../..' . '/includes/Debug/ProfilingLogger.php',
241
  'WooCommerce\\Facebook\\Debug\\ProfilingLoggerProcess' => __DIR__ . '/../..' . '/includes/Debug/ProfilingLoggerProcess.php',
242
  'WooCommerce\\Facebook\\Events\\AAMSettings' => __DIR__ . '/../..' . '/includes/Events/AAMSettings.php',
264
  'WooCommerce\\Facebook\\Integrations\\Bookings' => __DIR__ . '/../..' . '/includes/Integrations/Bookings.php',
265
  'WooCommerce\\Facebook\\Jobs\\AbstractChainedJob' => __DIR__ . '/../..' . '/includes/Jobs/AbstractChainedJob.php',
266
  'WooCommerce\\Facebook\\Jobs\\CleanupSkyvergeFrameworkJobOptions' => __DIR__ . '/../..' . '/includes/Jobs/CleanupSkyvergeFrameworkJobOptions.php',
267
+ 'WooCommerce\\Facebook\\Jobs\\DeleteProductsFromFBCatalog' => __DIR__ . '/../..' . '/includes/Jobs/DeleteProductsFromFBCatalog.php',
268
  'WooCommerce\\Facebook\\Jobs\\GenerateProductFeed' => __DIR__ . '/../..' . '/includes/Jobs/GenerateProductFeed.php',
269
  'WooCommerce\\Facebook\\Jobs\\JobManager' => __DIR__ . '/../..' . '/includes/Jobs/JobManager.php',
270
  'WooCommerce\\Facebook\\Jobs\\LoggingTrait' => __DIR__ . '/../..' . '/includes/Jobs/LoggingTrait.php',
271
+ 'WooCommerce\\Facebook\\Jobs\\ResetAllProductsFBSettings' => __DIR__ . '/../..' . '/includes/Jobs/ResetAllProductsFBSettings.php',
272
  'WooCommerce\\Facebook\\Lifecycle' => __DIR__ . '/../..' . '/includes/Lifecycle.php',
273
  'WooCommerce\\Facebook\\Locale' => __DIR__ . '/../..' . '/includes/Locale.php',
274
  'WooCommerce\\Facebook\\ProductSets\\Sync' => __DIR__ . '/../..' . '/includes/ProductSets/Sync.php',
285
  'WooCommerce\\Facebook\\Products\\Sync\\Background' => __DIR__ . '/../..' . '/includes/Products/Sync/Background.php',
286
  'WooCommerce\\Facebook\\Utilities\\Background_Handle_Virtual_Products_Variations' => __DIR__ . '/../..' . '/includes/Utilities/Background_Handle_Virtual_Products_Variations.php',
287
  'WooCommerce\\Facebook\\Utilities\\Background_Remove_Duplicate_Visibility_Meta' => __DIR__ . '/../..' . '/includes/Utilities/Background_Remove_Duplicate_Visibility_Meta.php',
288
+ 'WooCommerce\\Facebook\\Utilities\\DebugTools' => __DIR__ . '/../..' . '/includes/Utilities/DebugTools.php',
289
  'WooCommerce\\Facebook\\Utilities\\Heartbeat' => __DIR__ . '/../..' . '/includes/Utilities/Heartbeat.php',
 
290
  'WooCommerce\\Facebook\\Utilities\\Tracker' => __DIR__ . '/../..' . '/includes/Utilities/Tracker.php',
291
  );
292
 
293
  public static function getInitializer(ClassLoader $loader)
294
  {
295
  return \Closure::bind(function () use ($loader) {
296
+ $loader->prefixLengthsPsr4 = ComposerStaticInitea9949fe138c408a8667af28726c644c::$prefixLengthsPsr4;
297
+ $loader->prefixDirsPsr4 = ComposerStaticInitea9949fe138c408a8667af28726c644c::$prefixDirsPsr4;
298
+ $loader->classMap = ComposerStaticInitea9949fe138c408a8667af28726c644c::$classMap;
299
 
300
  }, null, ClassLoader::class);
301
  }
vendor/composer/installed.php CHANGED
@@ -1,9 +1,9 @@
1
  <?php return array(
2
  'root' => array(
3
  'name' => 'facebookincubator/facebook-for-woocommerce',
4
- 'pretty_version' => 'dev-trunk',
5
- 'version' => 'dev-trunk',
6
- 'reference' => 'a3b2276dff752664f94a719893daa10d3104060f',
7
  'type' => 'wordpress-plugin',
8
  'install_path' => __DIR__ . '/../../',
9
  'aliases' => array(),
@@ -20,9 +20,9 @@
20
  'dev_requirement' => false,
21
  ),
22
  'facebookincubator/facebook-for-woocommerce' => array(
23
- 'pretty_version' => 'dev-trunk',
24
- 'version' => 'dev-trunk',
25
- 'reference' => 'a3b2276dff752664f94a719893daa10d3104060f',
26
  'type' => 'wordpress-plugin',
27
  'install_path' => __DIR__ . '/../../',
28
  'aliases' => array(),
1
  <?php return array(
2
  'root' => array(
3
  'name' => 'facebookincubator/facebook-for-woocommerce',
4
+ 'pretty_version' => 'dev-release/3.0.5',
5
+ 'version' => 'dev-release/3.0.5',
6
+ 'reference' => 'a1efe7edf48cfc49e4f5a236ca16f0c7f71358b0',
7
  'type' => 'wordpress-plugin',
8
  'install_path' => __DIR__ . '/../../',
9
  'aliases' => array(),
20
  'dev_requirement' => false,
21
  ),
22
  'facebookincubator/facebook-for-woocommerce' => array(
23
+ 'pretty_version' => 'dev-release/3.0.5',
24
+ 'version' => 'dev-release/3.0.5',
25
+ 'reference' => 'a1efe7edf48cfc49e4f5a236ca16f0c7f71358b0',
26
  'type' => 'wordpress-plugin',
27
  'install_path' => __DIR__ . '/../../',
28
  'aliases' => array(),