Version Description
Download this release
Release Info
Developer | SkyVerge |
Plugin | Facebook for WooCommerce |
Version | 2.0.0 |
Comparing to | |
See all releases |
Code changes from version 1.11.4 to 2.0.0
- CONTRIBUTING.md +0 -35
- assets/css/admin/facebook-for-woocommerce-connection.css +73 -0
- assets/css/admin/facebook-for-woocommerce-products-admin.css +9 -7
- assets/image/FB-f-Logo__blue_29.png +0 -0
- assets/image/facebook.png +0 -0
- assets/image/help-center.png +0 -0
- assets/image/small-store.png +0 -0
- assets/images/background.png +0 -0
- assets/images/icon-0.png +0 -0
- assets/images/icon-1.png +0 -0
- assets/images/icon-2.png +0 -0
- assets/images/logo.png +0 -0
- assets/js/admin/facebook-for-woocommerce-products-admin.js +59 -108
- assets/js/admin/facebook-for-woocommerce-products-admin.min.js +1 -1
- assets/js/admin/facebook-for-woocommerce-settings-messenger.js +96 -0
- assets/js/admin/facebook-for-woocommerce-settings-messenger.min.js +1 -0
- assets/js/admin/facebook-for-woocommerce-settings-sync.js +181 -92
- assets/js/admin/facebook-for-woocommerce-settings-sync.min.js +1 -1
- assets/js/facebook-metabox.js +1 -1
- assets/js/facebook-metabox.min.js +1 -1
- assets/js/facebook-settings.js +0 -1099
- changelog.txt +9 -0
- class-wc-facebookcommerce.php +337 -77
- facebook-commerce-events-tracker.php +331 -68
- facebook-commerce-messenger-chat.php +2 -26
- facebook-commerce-pixel-event.php +95 -16
- facebook-commerce.php +574 -1549
- facebook-config-warmer.php +2 -0
- facebook-for-woocommerce.php +2 -2
- i18n/languages/facebook-for-woocommerce.pot +322 -334
- includes/AJAX.php +99 -246
- includes/API.php +588 -0
- includes/API/Business_Manager/Request.php +51 -0
- includes/API/Business_Manager/Response.php +49 -0
- includes/API/Catalog/Product_Group/Products/Read/Request.php +44 -0
- includes/API/Catalog/Product_Group/Products/Read/Response.php +47 -0
- includes/API/Catalog/Product_Item/Find/Request.php +65 -0
- includes/API/Catalog/Product_Item/Response.php +44 -0
- includes/API/Catalog/Request.php +51 -0
- includes/API/Catalog/Response.php +36 -0
- includes/API/Catalog/Send_Item_Updates/Request.php +124 -0
- includes/API/Catalog/Send_Item_Updates/Response.php +38 -0
- includes/API/Exceptions/Request_Limit_Reached.php +25 -0
- includes/API/FBE/Configuration/Messenger.php +153 -0
- includes/API/FBE/Configuration/Read/Response.php +44 -0
- includes/API/FBE/Configuration/Request.php +43 -0
- includes/API/FBE/Configuration/Update/Request.php +59 -0
- includes/API/FBE/Installation/Read/Request.php +42 -0
- includes/API/FBE/Installation/Read/Response.php +120 -0
- includes/API/FBE/Installation/Request.php +39 -0
- includes/API/Pages/Read/Request.php +51 -0
- includes/API/Pages/Read/Response.php +51 -0
- includes/API/Pixel/Events/Request.php +95 -0
- includes/API/Request.php +69 -0
- includes/API/Response.php +95 -0
- includes/API/Traits/Paginated_Response.php +111 -0
- includes/API/Traits/Rate_Limited_API.php +70 -0
- includes/API/Traits/Rate_Limited_Request.php +36 -0
- includes/API/Traits/Rate_Limited_Response.php +123 -0
- includes/API/User/Permissions/Delete/Request.php +39 -0
- includes/API/User/Request.php +44 -0
- includes/API/User/Response.php +23 -0
- includes/Admin.php +542 -289
- includes/Admin/Abstract_Settings_Screen.php +192 -0
- includes/Admin/Settings.php +224 -0
- includes/Admin/Settings_Screens/Connection.php +371 -0
- includes/Admin/Settings_Screens/Messenger.php +314 -0
- includes/Admin/Settings_Screens/Product_Sync.php +280 -0
- includes/Events/Event.php +332 -0
- includes/Handlers/Connection.php +820 -0
- includes/Lifecycle.php +37 -5
- includes/Products.php +88 -7
- includes/Products/Sync.php +211 -0
- includes/Products/Sync/Background.php +354 -0
- includes/Utilities/{Background_Disable_Virtual_Products_Sync.php → Background_Handle_Virtual_Products_Variations.php} +23 -30
- includes/fbgraph.php +36 -0
- includes/fbproduct.php +36 -14
- includes/test/facebook-integration-test.php +1 -0
- readme.txt +10 -1
CONTRIBUTING.md
DELETED
@@ -1,35 +0,0 @@
|
|
1 |
-
# Contributing to Facebook for WooCommerce
|
2 |
-
We want to make contributing to this project as easy and transparent as
|
3 |
-
possible.
|
4 |
-
|
5 |
-
## Pull Requests
|
6 |
-
We actively welcome your pull requests.
|
7 |
-
|
8 |
-
1. Fork the repo and create your branch from `master`.
|
9 |
-
2. If you've added code that should be tested, add tests.
|
10 |
-
3. If you've changed APIs, update the documentation.
|
11 |
-
4. Make sure your code lints.
|
12 |
-
5. If you haven't already, complete the Contributor License Agreement ("CLA").
|
13 |
-
|
14 |
-
## Contributor License Agreement ("CLA")
|
15 |
-
In order to accept your pull request, we need you to submit a CLA. You only need
|
16 |
-
to do this once to work on any of Facebook's open source projects.
|
17 |
-
|
18 |
-
Complete your CLA here: <https://code.facebook.com/cla>
|
19 |
-
|
20 |
-
## Issues
|
21 |
-
We use GitHub issues to track public bugs. Please ensure your description is
|
22 |
-
clear and has sufficient instructions to be able to reproduce the issue.
|
23 |
-
|
24 |
-
Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe
|
25 |
-
disclosure of security bugs. In those cases, please go through the process
|
26 |
-
outlined on that page and do not file a public issue.
|
27 |
-
|
28 |
-
## Coding Style
|
29 |
-
* 4 spaces for indentation rather than tabs
|
30 |
-
* 80 character line length
|
31 |
-
|
32 |
-
## License
|
33 |
-
By contributing to Facebook for WooCommerce, you agree that your contributions
|
34 |
-
will be licensed under the LICENSE file in the root directory of
|
35 |
-
this source tree.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assets/css/admin/facebook-for-woocommerce-connection.css
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#wc-facebook-connection-box {
|
2 |
+
width: 50%;
|
3 |
+
min-width: 720px;
|
4 |
+
color: rgb( 5, 5, 5 );
|
5 |
+
background: white url( '../../images/background.png' ) no-repeat;
|
6 |
+
background-position: right 30px center;
|
7 |
+
padding: 10px 15px 20px;
|
8 |
+
box-shadow: 0 0 3px rgba( 0, 0, 0, 0.2 );
|
9 |
+
margin-bottom: 20px;
|
10 |
+
}
|
11 |
+
|
12 |
+
#wc-facebook-connection-box .logo {
|
13 |
+
width: 40px;
|
14 |
+
height: 40px;
|
15 |
+
background-image: url( '../../images/logo.png' );
|
16 |
+
background-size: 100%;
|
17 |
+
margin-bottom: 10px;
|
18 |
+
}
|
19 |
+
|
20 |
+
#wc-facebook-connection-box h1 {
|
21 |
+
font-weight: bold;
|
22 |
+
font-size: 1.5em;
|
23 |
+
}
|
24 |
+
#wc-facebook-connection-box h2 {
|
25 |
+
font-size: 1.1em;
|
26 |
+
color: rgb(162, 162, 162);
|
27 |
+
margin: 0;
|
28 |
+
}
|
29 |
+
|
30 |
+
#wc-facebook-connection-box .benefits {
|
31 |
+
padding-top: 10px;
|
32 |
+
margin-bottom: 20px;
|
33 |
+
}
|
34 |
+
|
35 |
+
#wc-facebook-connection-box .benefits .benefit {
|
36 |
+
margin: 0 0 6px 0;
|
37 |
+
padding-top: 5px;
|
38 |
+
padding-left: 35px;
|
39 |
+
min-height: 26px;
|
40 |
+
background-size: 26px;
|
41 |
+
background-repeat: no-repeat;
|
42 |
+
}
|
43 |
+
|
44 |
+
#wc-facebook-connection-box .benefits .benefit-0 {
|
45 |
+
background-image: url( '../../images/icon-0.png' );
|
46 |
+
}
|
47 |
+
|
48 |
+
#wc-facebook-connection-box .benefits .benefit-1 {
|
49 |
+
background-image: url( '../../images/icon-1.png' );
|
50 |
+
}
|
51 |
+
|
52 |
+
#wc-facebook-connection-box .benefits .benefit-2 {
|
53 |
+
background-image: url( '../../images/icon-2.png' );
|
54 |
+
}
|
55 |
+
|
56 |
+
#wc-facebook-connection-box .button {
|
57 |
+
color: rgb( 5, 5, 5 );
|
58 |
+
background-color: rgb( 228, 230, 235 );
|
59 |
+
border: none;
|
60 |
+
border-radius: 6px;
|
61 |
+
padding: 4px 4em;
|
62 |
+
margin-right: 10px;
|
63 |
+
font-weight: bold;
|
64 |
+
}
|
65 |
+
|
66 |
+
#wc-facebook-connection-box .button.button-primary {
|
67 |
+
color: white;
|
68 |
+
background-color: rgb( 24, 119, 242 );
|
69 |
+
}
|
70 |
+
|
71 |
+
#wc-facebook-connection-box .uninstall {
|
72 |
+
vertical-align: middle;
|
73 |
+
}
|
assets/css/admin/facebook-for-woocommerce-products-admin.css
CHANGED
@@ -1,3 +1,7 @@
|
|
|
|
|
|
|
|
|
|
1 |
/* added #woocommerce-product-data to increase selector specificity */
|
2 |
#woocommerce-product-data .fb-product-image-source-field .wc-radios li {
|
3 |
margin-bottom: 0;
|
@@ -11,11 +15,6 @@
|
|
11 |
padding-top: 10px;
|
12 |
}
|
13 |
|
14 |
-
.woocommerce_variation .fb-sync-enabled-field .checkbox {
|
15 |
-
margin-top: 2px !important;
|
16 |
-
margin-right: 5px !important;
|
17 |
-
}
|
18 |
-
|
19 |
.woocommerce_variation .fb-product-image-source-field {
|
20 |
margin: 1em 0;
|
21 |
}
|
@@ -36,8 +35,11 @@
|
|
36 |
clear: both;
|
37 |
}
|
38 |
|
|
|
|
|
|
|
|
|
39 |
/* adjusts widths of the products table, same as WooCommerce categories and tags */
|
40 |
-
|
41 |
-
#facebook_catalog_visibility {
|
42 |
width: 11% !important;
|
43 |
}
|
1 |
+
#woocommerce-product-data .fb-product-image-source-field .wc-radios {
|
2 |
+
width: auto;
|
3 |
+
}
|
4 |
+
|
5 |
/* added #woocommerce-product-data to increase selector specificity */
|
6 |
#woocommerce-product-data .fb-product-image-source-field .wc-radios li {
|
7 |
margin-bottom: 0;
|
15 |
padding-top: 10px;
|
16 |
}
|
17 |
|
|
|
|
|
|
|
|
|
|
|
18 |
.woocommerce_variation .fb-product-image-source-field {
|
19 |
margin: 1em 0;
|
20 |
}
|
35 |
clear: both;
|
36 |
}
|
37 |
|
38 |
+
.notice .button.js-wc-plugin-framework-notice-dismiss {
|
39 |
+
margin-left: 10px;
|
40 |
+
}
|
41 |
+
|
42 |
/* adjusts widths of the products table, same as WooCommerce categories and tags */
|
43 |
+
.column-facebook_sync {
|
|
|
44 |
width: 11% !important;
|
45 |
}
|
assets/image/FB-f-Logo__blue_29.png
DELETED
Binary file
|
assets/image/facebook.png
DELETED
Binary file
|
assets/image/help-center.png
DELETED
Binary file
|
assets/image/small-store.png
DELETED
Binary file
|
assets/images/background.png
ADDED
Binary file
|
assets/images/icon-0.png
ADDED
Binary file
|
assets/images/icon-1.png
ADDED
Binary file
|
assets/images/icon-2.png
ADDED
Binary file
|
assets/images/logo.png
ADDED
Binary file
|
assets/js/admin/facebook-for-woocommerce-products-admin.js
CHANGED
@@ -16,45 +16,6 @@ jQuery( document ).ready( function( $ ) {
|
|
16 |
// products list edit screen
|
17 |
if ( 'edit-product' === pagenow ) {
|
18 |
|
19 |
-
|
20 |
-
let visibilityToggles = $( '.facebook-for-woocommerce-product-visibility-toggle' );
|
21 |
-
|
22 |
-
// init visibility toggles tooltips
|
23 |
-
visibilityToggles.tipTip( {
|
24 |
-
attribute: 'title',
|
25 |
-
edgeOffset: 5,
|
26 |
-
fadeIn: 50,
|
27 |
-
fadeOut: 50,
|
28 |
-
delay: 200
|
29 |
-
} );
|
30 |
-
|
31 |
-
// handle FB Catalog Visibility buttons
|
32 |
-
visibilityToggles.on( 'click', function( e ) {
|
33 |
-
e.preventDefault();
|
34 |
-
|
35 |
-
let action = $( this ).data( 'action' ),
|
36 |
-
visibility = 'show' === action ? 'yes' : 'no',
|
37 |
-
productID = parseInt( $( this ).data( 'product-id' ), 10 );
|
38 |
-
|
39 |
-
if ( 'show' === action ) {
|
40 |
-
$( this ).hide().next( 'button' ).show();
|
41 |
-
} else if ( 'hide' === action ) {
|
42 |
-
$( this ).hide().prev( 'button' ).show();
|
43 |
-
}
|
44 |
-
|
45 |
-
$.post( facebook_for_woocommerce_products_admin.ajax_url, {
|
46 |
-
action: 'facebook_for_woocommerce_set_products_visibility',
|
47 |
-
security: facebook_for_woocommerce_products_admin.set_product_visibility_nonce,
|
48 |
-
products: [
|
49 |
-
{
|
50 |
-
product_id: productID,
|
51 |
-
visibility: visibility
|
52 |
-
}
|
53 |
-
]
|
54 |
-
} );
|
55 |
-
} );
|
56 |
-
|
57 |
-
|
58 |
// handle bulk actions
|
59 |
let submitProductBulkAction = false;
|
60 |
|
@@ -69,7 +30,6 @@ jQuery( document ).ready( function( $ ) {
|
|
69 |
let $submitButton = $( this ),
|
70 |
chosenBulkAction = $submitButton.prev( 'select' ).val();
|
71 |
|
72 |
-
// TODO: also check `'facebook_exclude' === chosenBulkAction` once Catalog Visibility settings are available again {WV 2020-04-20}
|
73 |
if ( 'facebook_include' === chosenBulkAction ) {
|
74 |
|
75 |
let products = [];
|
@@ -96,28 +56,6 @@ jQuery( document ).ready( function( $ ) {
|
|
96 |
string: response.data
|
97 |
} );
|
98 |
|
99 |
-
// exclude from sync: offer to handle product visibility
|
100 |
-
$( '.facebook-for-woocommerce-toggle-product-visibility' ).on( 'click', function( e) {
|
101 |
-
|
102 |
-
blockModal();
|
103 |
-
|
104 |
-
if ( $( this ).hasClass( 'hide-products' ) ) {
|
105 |
-
|
106 |
-
$.each( products, function() {
|
107 |
-
|
108 |
-
let $toggle = $( '#post-' + this ).find( 'td.facebook_catalog_visibility button.facebook-for-woocommerce-product-visibility-hide' );
|
109 |
-
|
110 |
-
if ( $toggle.is( ':visible' ) ) {
|
111 |
-
$toggle.trigger( 'click' );
|
112 |
-
}
|
113 |
-
} );
|
114 |
-
}
|
115 |
-
|
116 |
-
// submit form after modal prompt action
|
117 |
-
submitProductBulkAction = true;
|
118 |
-
$submitButton.trigger( 'click' );
|
119 |
-
} );
|
120 |
-
|
121 |
} else {
|
122 |
|
123 |
// no modal displayed: submit form as normal
|
@@ -153,25 +91,70 @@ jQuery( document ).ready( function( $ ) {
|
|
153 |
}
|
154 |
|
155 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
// toggle Facebook settings fields for simple products
|
157 |
-
const
|
158 |
-
const facebookSettingsPanel =
|
159 |
|
160 |
-
|
161 |
-
|
162 |
-
|
|
|
|
|
|
|
163 |
|
164 |
-
|
|
|
|
|
165 |
|
166 |
// toggle Facebook settings fields for variations
|
167 |
$( '.woocommerce_variations' ).on( 'change', '.js-variable-fb-sync-toggle', function() {
|
168 |
-
toggleFacebookSettings( $( this ).
|
|
|
169 |
} );
|
170 |
|
171 |
$( '#woocommerce-product-data' ).on( 'woocommerce_variations_loaded', function () {
|
172 |
|
173 |
$( '.js-variable-fb-sync-toggle' ).each( function () {
|
174 |
-
toggleFacebookSettings( $( this ).
|
|
|
|
|
|
|
|
|
|
|
|
|
175 |
} );
|
176 |
} );
|
177 |
|
@@ -185,14 +168,16 @@ jQuery( document ).ready( function( $ ) {
|
|
185 |
$container.find( `.show-if-product-image-source-${imageSource}` ).closest( '.form-field' ).show();
|
186 |
} );
|
187 |
|
188 |
-
$( '.js-fb-product-image-source:checked' ).trigger( 'change' );
|
189 |
|
190 |
// trigger settings fields modifiers when variations are loaded
|
191 |
$( '#woocommerce-product-data' ).on( 'woocommerce_variations_loaded', function() {
|
192 |
$( '.js-variable-fb-sync-toggle:visible' ).trigger( 'change' );
|
193 |
$( '.js-fb-product-image-source:checked:visible' ).trigger( 'change' );
|
|
|
194 |
} );
|
195 |
|
|
|
196 |
let submitProductSave = false;
|
197 |
|
198 |
$( 'form#post input[type="submit"]' ).on( 'click', function( e ) {
|
@@ -204,13 +189,12 @@ jQuery( document ).ready( function( $ ) {
|
|
204 |
}
|
205 |
|
206 |
let $submitButton = $( this ),
|
207 |
-
$visibleCheckbox = $( 'input[name="fb_visibility"]' ),
|
208 |
productID = parseInt( $( 'input#post_ID' ).val(), 10 ),
|
209 |
productCat = [],
|
210 |
// this query will get tags when not using checkboxes
|
211 |
productTag = $( 'textarea[name="tax_input[product_tag]"]' ).length ? $( 'textarea[name="tax_input[product_tag]"]' ).val().split( ',' ) : [],
|
212 |
-
syncEnabled = $( '
|
213 |
-
varSyncEnabled = $( '.js-variable-fb-sync-toggle' ).
|
214 |
|
215 |
$( '#taxonomy-product_cat input[name="tax_input[product_cat][]"]:checked' ).each( function() {
|
216 |
productCat.push( parseInt( $( this ).val(), 10 ) );
|
@@ -234,7 +218,7 @@ jQuery( document ).ready( function( $ ) {
|
|
234 |
}, function( response ) {
|
235 |
|
236 |
// open modal if visibility checkbox is checked or if there are conflicting terms set for sync exclusion
|
237 |
-
if ( response && ! response.success &&
|
238 |
|
239 |
// close existing modals
|
240 |
$( '#wc-backbone-modal-dialog .modal-close' ).trigger( 'click' );
|
@@ -245,20 +229,6 @@ jQuery( document ).ready( function( $ ) {
|
|
245 |
string: response.data
|
246 |
} );
|
247 |
|
248 |
-
// exclude from sync: offer to handle product visibility
|
249 |
-
$( '.facebook-for-woocommerce-toggle-product-visibility' ).on( 'click', function( e) {
|
250 |
-
|
251 |
-
blockModal();
|
252 |
-
|
253 |
-
if ( $( this ).hasClass( 'hide-products' ) ) {
|
254 |
-
$visibleCheckbox.prop( 'checked', false );
|
255 |
-
}
|
256 |
-
|
257 |
-
// no modal displayed: submit form as normal
|
258 |
-
submitProductSave = true;
|
259 |
-
$submitButton.trigger( 'click' );
|
260 |
-
} );
|
261 |
-
|
262 |
} else {
|
263 |
|
264 |
// no modal displayed: submit form as normal
|
@@ -278,23 +248,4 @@ jQuery( document ).ready( function( $ ) {
|
|
278 |
}
|
279 |
|
280 |
|
281 |
-
// product list screen or individual product edit screen
|
282 |
-
if ( 'product' === pagenow || 'edit-product' === pagenow ) {
|
283 |
-
|
284 |
-
// handle the "Do not show this notice again" button
|
285 |
-
$( '.js-wc-plugin-framework-admin-notice' ).on( 'click', '.notice-dismiss-permanently', function() {
|
286 |
-
|
287 |
-
var $notice = $( this ).closest( '.js-wc-plugin-framework-admin-notice' );
|
288 |
-
|
289 |
-
$.get( ajaxurl, {
|
290 |
-
action: 'wc_plugin_framework_' + $( $notice ).data( 'plugin-id' ) + '_dismiss_notice',
|
291 |
-
messageid: $( $notice ).data( 'message-id' ),
|
292 |
-
permanently: true
|
293 |
-
} );
|
294 |
-
|
295 |
-
$notice.fadeOut();
|
296 |
-
} );
|
297 |
-
}
|
298 |
-
|
299 |
-
|
300 |
} );
|
16 |
// products list edit screen
|
17 |
if ( 'edit-product' === pagenow ) {
|
18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
// handle bulk actions
|
20 |
let submitProductBulkAction = false;
|
21 |
|
30 |
let $submitButton = $( this ),
|
31 |
chosenBulkAction = $submitButton.prev( 'select' ).val();
|
32 |
|
|
|
33 |
if ( 'facebook_include' === chosenBulkAction ) {
|
34 |
|
35 |
let products = [];
|
56 |
string: response.data
|
57 |
} );
|
58 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
} else {
|
60 |
|
61 |
// no modal displayed: submit form as normal
|
91 |
}
|
92 |
|
93 |
|
94 |
+
/**
|
95 |
+
* Toggles (shows/hides) Sync and show option and changes the select value if needed.
|
96 |
+
*
|
97 |
+
* @since 2.0.0
|
98 |
+
*
|
99 |
+
* @param {boolean} show whether the Sync and show option should be displayed or not
|
100 |
+
* @param {jQuery} $select the sync mode select
|
101 |
+
*/
|
102 |
+
function toggleSyncAndShowOption( show, $select ) {
|
103 |
+
|
104 |
+
if ( ! show ) {
|
105 |
+
|
106 |
+
// hide Sync and show option
|
107 |
+
$select.find( 'option[value=\'sync_and_show\']' ).hide();
|
108 |
+
|
109 |
+
if ( 'sync_and_show' === $select.val() ) {
|
110 |
+
// change selected option to Sync and hide
|
111 |
+
$select.val( 'sync_and_hide' );
|
112 |
+
}
|
113 |
+
|
114 |
+
} else {
|
115 |
+
|
116 |
+
// show Sync and Show option
|
117 |
+
$select.find( 'option[value=\'sync_and_show\']' ).show();
|
118 |
+
|
119 |
+
// restore originally selected option
|
120 |
+
if ( $select.prop( 'original' ) ) {
|
121 |
+
$select.val( $select.prop( 'original' ) );
|
122 |
+
}
|
123 |
+
}
|
124 |
+
}
|
125 |
+
|
126 |
+
|
127 |
// toggle Facebook settings fields for simple products
|
128 |
+
const syncModeSelect = $( '#wc_facebook_sync_mode' );
|
129 |
+
const facebookSettingsPanel = syncModeSelect.closest( '.woocommerce_options_panel' );
|
130 |
|
131 |
+
syncModeSelect.on( 'change', function() {
|
132 |
+
|
133 |
+
toggleFacebookSettings( $( this ).val() !== 'sync_disabled', facebookSettingsPanel );
|
134 |
+
syncModeSelect.prop( 'original', $( this ).val() );
|
135 |
+
|
136 |
+
} ).trigger( 'change' );
|
137 |
|
138 |
+
$( '#_virtual' ).on( 'change', function () {
|
139 |
+
toggleSyncAndShowOption( ! $( this ).prop( 'checked' ), syncModeSelect );
|
140 |
+
} ).trigger( 'change' );
|
141 |
|
142 |
// toggle Facebook settings fields for variations
|
143 |
$( '.woocommerce_variations' ).on( 'change', '.js-variable-fb-sync-toggle', function() {
|
144 |
+
toggleFacebookSettings( $( this ).val() !== 'sync_disabled', $( this ).closest( '.wc-metabox-content' ) );
|
145 |
+
$( this ).prop( 'original', $( this ).val() );
|
146 |
} );
|
147 |
|
148 |
$( '#woocommerce-product-data' ).on( 'woocommerce_variations_loaded', function () {
|
149 |
|
150 |
$( '.js-variable-fb-sync-toggle' ).each( function () {
|
151 |
+
toggleFacebookSettings( $( this ).val() !== 'sync_disabled', $( this ).closest( '.wc-metabox-content' ) );
|
152 |
+
$( this ).prop( 'original', $( this ).val() );
|
153 |
+
} );
|
154 |
+
|
155 |
+
$( '.variable_is_virtual' ).on( 'change', function () {
|
156 |
+
const jsSyncModeToggle = $( this ).closest( '.wc-metabox-content' ).find( '.js-variable-fb-sync-toggle' );
|
157 |
+
toggleSyncAndShowOption( ! $( this ).prop( 'checked' ), jsSyncModeToggle );
|
158 |
} );
|
159 |
} );
|
160 |
|
168 |
$container.find( `.show-if-product-image-source-${imageSource}` ).closest( '.form-field' ).show();
|
169 |
} );
|
170 |
|
171 |
+
$( '.js-fb-product-image-source:checked:visible' ).trigger( 'change' );
|
172 |
|
173 |
// trigger settings fields modifiers when variations are loaded
|
174 |
$( '#woocommerce-product-data' ).on( 'woocommerce_variations_loaded', function() {
|
175 |
$( '.js-variable-fb-sync-toggle:visible' ).trigger( 'change' );
|
176 |
$( '.js-fb-product-image-source:checked:visible' ).trigger( 'change' );
|
177 |
+
$( '.variable_is_virtual:visible' ).trigger( 'change' );
|
178 |
} );
|
179 |
|
180 |
+
|
181 |
let submitProductSave = false;
|
182 |
|
183 |
$( 'form#post input[type="submit"]' ).on( 'click', function( e ) {
|
189 |
}
|
190 |
|
191 |
let $submitButton = $( this ),
|
|
|
192 |
productID = parseInt( $( 'input#post_ID' ).val(), 10 ),
|
193 |
productCat = [],
|
194 |
// this query will get tags when not using checkboxes
|
195 |
productTag = $( 'textarea[name="tax_input[product_tag]"]' ).length ? $( 'textarea[name="tax_input[product_tag]"]' ).val().split( ',' ) : [],
|
196 |
+
syncEnabled = $( '#wc_facebook_sync_mode' ).val() !== 'sync_disabled',
|
197 |
+
varSyncEnabled = $( '.js-variable-fb-sync-toggle' ).val() !== 'sync_disabled';
|
198 |
|
199 |
$( '#taxonomy-product_cat input[name="tax_input[product_cat][]"]:checked' ).each( function() {
|
200 |
productCat.push( parseInt( $( this ).val(), 10 ) );
|
218 |
}, function( response ) {
|
219 |
|
220 |
// open modal if visibility checkbox is checked or if there are conflicting terms set for sync exclusion
|
221 |
+
if ( response && ! response.success && syncEnabled ) {
|
222 |
|
223 |
// close existing modals
|
224 |
$( '#wc-backbone-modal-dialog .modal-close' ).trigger( 'click' );
|
229 |
string: response.data
|
230 |
} );
|
231 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
232 |
} else {
|
233 |
|
234 |
// no modal displayed: submit form as normal
|
248 |
}
|
249 |
|
250 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
251 |
} );
|
assets/js/admin/facebook-for-woocommerce-products-admin.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
"use strict";jQuery(document).ready(function(
|
1 |
+
"use strict";jQuery(document).ready(function(r){var o=window.pagenow.length?window.pagenow:"";window.typenow.length&&window.typenow;if("edit-product"===o){var a=!1;r("input#doaction, input#doaction2").on("click",function(o){if(a)return!0;o.preventDefault();var e=r(this),c=e.prev("select").val();if("facebook_include"===c){var t=[];r.each(r('input[name="post[]"]:checked'),function(){t.push(parseInt(r(this).val(),10))}),r.post(facebook_for_woocommerce_products_admin.ajax_url,{action:"facebook_for_woocommerce_set_product_sync_bulk_action_prompt",security:facebook_for_woocommerce_products_admin.set_product_sync_bulk_action_prompt_nonce,toggle:c,products:t},function(o){o&&!o.success?(r("#wc-backbone-modal-dialog .modal-close").trigger("click"),new r.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:o.data})):(a=!0,e.trigger("click"))})}else a=!0,e.trigger("click")})}if("product"===o){var e=function(o,e){e.find(".enable-if-sync-enabled").prop("disabled",!o)},c=function(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"))},t=r("#wc_facebook_sync_mode"),n=t.closest(".woocommerce_options_panel");t.on("change",function(){e("sync_disabled"!==r(this).val(),n),t.prop("original",r(this).val())}).trigger("change"),r("#_virtual").on("change",function(){c(!r(this).prop("checked"),t)}).trigger("change"),r(".woocommerce_variations").on("change",".js-variable-fb-sync-toggle",function(){e("sync_disabled"!==r(this).val(),r(this).closest(".wc-metabox-content")),r(this).prop("original",r(this).val())}),r("#woocommerce-product-data").on("woocommerce_variations_loaded",function(){r(".js-variable-fb-sync-toggle").each(function(){e("sync_disabled"!==r(this).val(),r(this).closest(".wc-metabox-content")),r(this).prop("original",r(this).val())}),r(".variable_is_virtual").on("change",function(){var o=r(this).closest(".wc-metabox-content").find(".js-variable-fb-sync-toggle");c(!r(this).prop("checked"),o)})}),r("#woocommerce-product-data").on("change",".js-fb-product-image-source",function(){var o=r(this).closest(".woocommerce_options_panel, .wc-metabox-content"),e=r(this).val();o.find(".product-image-source-field").closest(".form-field").hide(),o.find(".show-if-product-image-source-"+e).closest(".form-field").show()}),r(".js-fb-product-image-source:checked:visible").trigger("change"),r("#woocommerce-product-data").on("woocommerce_variations_loaded",function(){r(".js-variable-fb-sync-toggle:visible").trigger("change"),r(".js-fb-product-image-source:checked:visible").trigger("change"),r(".variable_is_virtual:visible").trigger("change")});var s=!1;r('form#post input[type="submit"]').on("click",function(o){if(s)return!0;o.preventDefault();var e=r(this),c=parseInt(r("input#post_ID").val(),10),t=[],a=r('textarea[name="tax_input[product_tag]"]').length?r('textarea[name="tax_input[product_tag]"]').val().split(","):[],n="sync_disabled"!==r("#wc_facebook_sync_mode").val(),i="sync_disabled"!==r(".js-variable-fb-sync-toggle").val();r('#taxonomy-product_cat input[name="tax_input[product_cat][]"]:checked').each(function(){t.push(parseInt(r(this).val(),10))}),r('#taxonomy-product_tag input[name="tax_input[product_tag][]"]:checked').each(function(){a.push(parseInt(r(this).val(),10))}),0<c?r.post(facebook_for_woocommerce_products_admin.ajax_url,{action:"facebook_for_woocommerce_set_product_sync_prompt",security:facebook_for_woocommerce_products_admin.set_product_sync_prompt_nonce,sync_enabled:n?"enabled":"disabled",var_sync_enabled:i?"enabled":"disabled",product:c,categories:t,tags:a},function(o){o&&!o.success&&n?(r("#wc-backbone-modal-dialog .modal-close").trigger("click"),new r.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:o.data})):(s=!0,e.trigger("click"))}):(s=!0,e.trigger("click"))})}});
|
assets/js/admin/facebook-for-woocommerce-settings-messenger.js
ADDED
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery( document ).ready( function( $ ) {
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Toggles availability of input in setting groups.
|
5 |
+
*
|
6 |
+
* @param {boolean} enable whether fields in this group should be enabled or not
|
7 |
+
*/
|
8 |
+
function toggleSettingOptions( enable ) {
|
9 |
+
|
10 |
+
$( '.messenger-field' ).each( function() {
|
11 |
+
|
12 |
+
let $element = $( this );
|
13 |
+
|
14 |
+
if ( $( this ).hasClass( 'wc-enhanced-select' ) ) {
|
15 |
+
$element = $( this ).next( 'span.select2-container' );
|
16 |
+
}
|
17 |
+
|
18 |
+
if ( enable ) {
|
19 |
+
$element.css( 'pointer-events', 'all' ).css( 'opacity', '1.0' );
|
20 |
+
} else {
|
21 |
+
$element.css( 'pointer-events', 'none' ).css( 'opacity', '0.4' );
|
22 |
+
}
|
23 |
+
} );
|
24 |
+
}
|
25 |
+
|
26 |
+
if ( $( 'form.wc-facebook-settings' ).hasClass( 'disconnected' ) ) {
|
27 |
+
toggleSettingOptions( false );
|
28 |
+
}
|
29 |
+
|
30 |
+
$( 'input#wc_facebook_enable_messenger' ).on( 'change', function ( e ) {
|
31 |
+
|
32 |
+
if ( $( 'form.wc-facebook-settings' ).hasClass( 'disconnected' ) ) {
|
33 |
+
$( this ).css( 'pointer-events', 'none' ).css( 'opacity', '0.4' );
|
34 |
+
return;
|
35 |
+
}
|
36 |
+
|
37 |
+
toggleSettingOptions( $( this ).is( ':checked' ) );
|
38 |
+
|
39 |
+
} ).trigger( 'change' );
|
40 |
+
|
41 |
+
// adds a character counter on the Messenger greeting textarea
|
42 |
+
$( 'textarea#wc_facebook_messenger_greeting' ).on( 'focus change keyup keydown keypress', function() {
|
43 |
+
|
44 |
+
const maxChars = parseInt( $( this ).attr( 'maxlength' ), 10 );
|
45 |
+
let chars = $( this ).val().length,
|
46 |
+
$counter = $( 'span.characters-counter' ),
|
47 |
+
$warning = $counter.find( 'span' );
|
48 |
+
|
49 |
+
$counter.html( chars + ' / ' + maxChars + '<br/>' ).append( $warning ).css( 'display', 'block' );
|
50 |
+
|
51 |
+
if ( chars > maxChars ) {
|
52 |
+
$counter.css( 'color', '#DC3232' ).find( 'span' ).show();
|
53 |
+
} else {
|
54 |
+
$counter.css( 'color', '#999999' ).find( 'span' ).hide();
|
55 |
+
}
|
56 |
+
|
57 |
+
} );
|
58 |
+
|
59 |
+
|
60 |
+
// init the color picker
|
61 |
+
$( '#wc_facebook_messenger_color_hex' )
|
62 |
+
|
63 |
+
.iris( {
|
64 |
+
change: function( event, ui ) {
|
65 |
+
$( this ).parent().find( '.colorpickpreview' ).css( { backgroundColor: ui.color.toString() } );
|
66 |
+
},
|
67 |
+
hide: true,
|
68 |
+
border: true
|
69 |
+
})
|
70 |
+
|
71 |
+
.on( 'click focus', function( event ) {
|
72 |
+
event.stopPropagation();
|
73 |
+
$( '.iris-picker' ).hide();
|
74 |
+
$( this ).closest( 'td' ).find( '.iris-picker' ).show();
|
75 |
+
$( this ).data( 'original-value', $( this ).val() );
|
76 |
+
} )
|
77 |
+
|
78 |
+
.on( 'change', function() {
|
79 |
+
|
80 |
+
if ( $( this ).is( '.iris-error' ) ) {
|
81 |
+
|
82 |
+
var original_value = $( this ).data( 'original-value' );
|
83 |
+
|
84 |
+
if ( original_value.match( /^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/ ) ) {
|
85 |
+
$( this ).val( $( this ).data( 'original-value' ) ).change();
|
86 |
+
} else {
|
87 |
+
$( this ).val( '' ).change();
|
88 |
+
}
|
89 |
+
}
|
90 |
+
} );
|
91 |
+
|
92 |
+
$( 'body' ).on( 'click', function() {
|
93 |
+
$( '.iris-picker' ).hide();
|
94 |
+
} );
|
95 |
+
|
96 |
+
} );
|
assets/js/admin/facebook-for-woocommerce-settings-messenger.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
"use strict";jQuery(document).ready(function(c){function s(s){c(".messenger-field").each(function(){var e=c(this);c(this).hasClass("wc-enhanced-select")&&(e=c(this).next("span.select2-container")),s?e.css("pointer-events","all").css("opacity","1.0"):e.css("pointer-events","none").css("opacity","0.4")})}c("form.wc-facebook-settings").hasClass("disconnected")&&s(!1),c("input#wc_facebook_enable_messenger").on("change",function(e){c("form.wc-facebook-settings").hasClass("disconnected")?c(this).css("pointer-events","none").css("opacity","0.4"):s(c(this).is(":checked"))}).trigger("change"),c("textarea#wc_facebook_messenger_greeting").on("focus change keyup keydown keypress",function(){var e=parseInt(c(this).attr("maxlength"),10),s=c(this).val().length,n=c("span.characters-counter"),i=n.find("span");n.html(s+" / "+e+"<br/>").append(i).css("display","block"),e<s?n.css("color","#DC3232").find("span").show():n.css("color","#999999").find("span").hide()}),c("#wc_facebook_messenger_color_hex").iris({change:function(e,s){c(this).parent().find(".colorpickpreview").css({backgroundColor:s.color.toString()})},hide:!0,border:!0}).on("click focus",function(e){e.stopPropagation(),c(".iris-picker").hide(),c(this).closest("td").find(".iris-picker").show(),c(this).data("original-value",c(this).val())}).on("change",function(){c(this).is(".iris-error")&&(c(this).data("original-value").match(/^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/)?c(this).val(c(this).data("original-value")).change():c(this).val("").change())}),c("body").on("click",function(){c(".iris-picker").hide()})});
|
assets/js/admin/facebook-for-woocommerce-settings-sync.js
CHANGED
@@ -9,12 +9,6 @@
|
|
9 |
|
10 |
jQuery( document ).ready( function( $ ) {
|
11 |
|
12 |
-
// run script only on Facebook Settings page
|
13 |
-
if ( $( 'input[name="section"][value="facebookcommerce"]' ).closest( 'form' ).length === 0 ) {
|
14 |
-
return;
|
15 |
-
}
|
16 |
-
|
17 |
-
|
18 |
/**
|
19 |
* Gets any new excluded categories being added.
|
20 |
*
|
@@ -22,11 +16,11 @@ jQuery( document ).ready( function( $ ) {
|
|
22 |
*/
|
23 |
function getExcludedCategoriesAdded() {
|
24 |
|
25 |
-
const newCategoryIDs = $( '#
|
26 |
let oldCategoryIDs = [];
|
27 |
|
28 |
-
if ( window.
|
29 |
-
oldCategoryIDs = window.
|
30 |
}
|
31 |
|
32 |
// return IDs that are in the new value that were not in the saved value
|
@@ -41,11 +35,11 @@ jQuery( document ).ready( function( $ ) {
|
|
41 |
*/
|
42 |
function getExcludedTagsAdded() {
|
43 |
|
44 |
-
const newTagIDs = $( '#
|
45 |
let oldTagIDs = [];
|
46 |
|
47 |
-
if ( window.
|
48 |
-
oldTagIDs = window.
|
49 |
}
|
50 |
|
51 |
// return IDs that are in the new value that were not in the saved value
|
@@ -56,12 +50,11 @@ jQuery( document ).ready( function( $ ) {
|
|
56 |
/**
|
57 |
* Toggles availability of input in setting groups.
|
58 |
*
|
59 |
-
* @param {Object[]} $elements group of jQuery elements (fields or buttons) to toggle
|
60 |
* @param {boolean} enable whether fields in this group should be enabled or not
|
61 |
*/
|
62 |
-
function toggleSettingOptions(
|
63 |
|
64 |
-
$(
|
65 |
|
66 |
let $element = $( this );
|
67 |
|
@@ -77,52 +70,33 @@ jQuery( document ).ready( function( $ ) {
|
|
77 |
} );
|
78 |
}
|
79 |
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
toggleSettingOptions( $( '.product-sync-field' ).not( '.toggle-fields-group' ), $( this ).is( ':checked' ) );
|
85 |
-
} else if ( $( this ).hasClass( 'messenger-field' ) ) {
|
86 |
-
toggleSettingOptions( $( '.messenger-field' ).not( '.toggle-fields-group' ), $( this ).is( ':checked' ) );
|
87 |
-
} else if ( $( this ).hasClass( 'resync-schedule-field' ) ) {
|
88 |
-
toggleSettingOptions( $( '.resync-schedule-field' ).not( '.toggle-fields-group' ), $( this ).is( ':checked' ) );
|
89 |
-
}
|
90 |
-
} ).trigger( 'change' );
|
91 |
-
|
92 |
-
|
93 |
-
// adds a leading zero to time picker fields
|
94 |
-
$( '#woocommerce_facebookcommerce_scheduled_resync_hours, #woocommerce_facebookcommerce_scheduled_resync_minutes' ).on( 'input change keyup keydown keypress click', function() {
|
95 |
|
96 |
-
|
|
|
97 |
|
98 |
-
if (
|
99 |
-
$( this ).
|
|
|
100 |
}
|
101 |
|
102 |
-
|
103 |
-
|
104 |
|
105 |
-
|
106 |
-
$( 'textarea#woocommerce_facebookcommerce_messenger_greeting' ).on( 'focus change keyup keydown keypress', function() {
|
107 |
-
|
108 |
-
const maxChars = parseInt( window.facebookAdsToolboxConfig.messengerGreetingMaxCharacters, 10 );
|
109 |
-
let chars = $( this ).val().length,
|
110 |
-
$counter = $( 'span.characters-counter' ),
|
111 |
-
$warning = $counter.find( 'span' );
|
112 |
-
|
113 |
-
$counter.html( chars + ' / ' + maxChars + '<br/>' ).append( $warning ).css( 'display', 'block' );
|
114 |
-
|
115 |
-
if ( chars > maxChars ) {
|
116 |
-
$counter.css( 'color', '#DC3232' ).find( 'span' ).show();
|
117 |
-
} else {
|
118 |
-
$counter.css( 'color', '#999999' ).find( 'span' ).hide();
|
119 |
-
}
|
120 |
-
} );
|
121 |
|
122 |
|
123 |
let submitSettingsSave = false;
|
124 |
|
125 |
-
$( '
|
126 |
|
127 |
if ( ! submitSettingsSave ) {
|
128 |
e.preventDefault();
|
@@ -159,47 +133,9 @@ jQuery( document ).ready( function( $ ) {
|
|
159 |
|
160 |
blockModal();
|
161 |
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
let product_cats = [], product_tags = [];
|
166 |
-
|
167 |
-
$( categoriesAdded ).each( function() {
|
168 |
-
product_cats.push( {
|
169 |
-
term_id: this,
|
170 |
-
taxonomy: 'product_cat',
|
171 |
-
visibility: false
|
172 |
-
} );
|
173 |
-
} );
|
174 |
-
|
175 |
-
$( tagsAdded ).each( function() {
|
176 |
-
product_tags.push( {
|
177 |
-
term_id: this,
|
178 |
-
taxonomy: 'product_tag',
|
179 |
-
visibility: false
|
180 |
-
} );
|
181 |
-
} );
|
182 |
-
|
183 |
-
$.post( facebook_for_woocommerce_settings_sync.ajax_url, {
|
184 |
-
action: 'facebook_for_woocommerce_set_products_visibility',
|
185 |
-
security: facebook_for_woocommerce_settings_sync.set_product_visibility_nonce,
|
186 |
-
product_categories: product_cats,
|
187 |
-
product_tags: product_tags,
|
188 |
-
}, function ( response ) {
|
189 |
-
|
190 |
-
if ( ! response || ! response.success ) {
|
191 |
-
console.log( response )
|
192 |
-
}
|
193 |
-
|
194 |
-
submitSettingsSave = true;
|
195 |
-
$submitButton.trigger( 'click' );
|
196 |
-
} );
|
197 |
-
|
198 |
-
} else {
|
199 |
-
|
200 |
-
submitSettingsSave = true;
|
201 |
-
$submitButton.trigger( 'click' );
|
202 |
-
}
|
203 |
} );
|
204 |
|
205 |
} else {
|
@@ -218,4 +154,157 @@ jQuery( document ).ready( function( $ ) {
|
|
218 |
}
|
219 |
} );
|
220 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
221 |
} );
|
9 |
|
10 |
jQuery( document ).ready( function( $ ) {
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Gets any new excluded categories being added.
|
14 |
*
|
16 |
*/
|
17 |
function getExcludedCategoriesAdded() {
|
18 |
|
19 |
+
const newCategoryIDs = $( '#wc_facebook_excluded_product_category_ids' ).val();
|
20 |
let oldCategoryIDs = [];
|
21 |
|
22 |
+
if ( window.facebook_for_woocommerce_settings_sync && window.facebook_for_woocommerce_settings_sync.excluded_category_ids ) {
|
23 |
+
oldCategoryIDs = window.facebook_for_woocommerce_settings_sync.excluded_category_ids;
|
24 |
}
|
25 |
|
26 |
// return IDs that are in the new value that were not in the saved value
|
35 |
*/
|
36 |
function getExcludedTagsAdded() {
|
37 |
|
38 |
+
const newTagIDs = $( '#wc_facebook_excluded_product_tag_ids' ).val();
|
39 |
let oldTagIDs = [];
|
40 |
|
41 |
+
if ( window.facebook_for_woocommerce_settings_sync && window.facebook_for_woocommerce_settings_sync.excluded_tag_ids ) {
|
42 |
+
oldTagIDs = window.facebook_for_woocommerce_settings_sync.excluded_tag_ids;
|
43 |
}
|
44 |
|
45 |
// return IDs that are in the new value that were not in the saved value
|
50 |
/**
|
51 |
* Toggles availability of input in setting groups.
|
52 |
*
|
|
|
53 |
* @param {boolean} enable whether fields in this group should be enabled or not
|
54 |
*/
|
55 |
+
function toggleSettingOptions( enable ) {
|
56 |
|
57 |
+
$( '.product-sync-field' ).each( function() {
|
58 |
|
59 |
let $element = $( this );
|
60 |
|
70 |
} );
|
71 |
}
|
72 |
|
73 |
+
$( '.woocommerce-help-tip' ).tipTip( {
|
74 |
+
'attribute': 'data-tip',
|
75 |
+
'fadeIn': 50,
|
76 |
+
'fadeOut': 50,
|
77 |
+
'delay': 200
|
78 |
+
} );
|
79 |
|
80 |
+
if ( $( 'form.wc-facebook-settings' ).hasClass( 'disconnected' ) ) {
|
81 |
+
toggleSettingOptions( false );
|
82 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
|
84 |
+
// toggle availability of options withing field groups
|
85 |
+
$( 'input#wc_facebook_enable_product_sync' ).on( 'change', function ( e ) {
|
86 |
|
87 |
+
if ( $( 'form.wc-facebook-settings' ).hasClass( 'disconnected' ) ) {
|
88 |
+
$( this ).css( 'pointer-events', 'none' ).css( 'opacity', '0.4' );
|
89 |
+
return;
|
90 |
}
|
91 |
|
92 |
+
toggleSettingOptions( $( this ).is( ':checked' ) );
|
|
|
93 |
|
94 |
+
} ).trigger( 'change' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
|
96 |
|
97 |
let submitSettingsSave = false;
|
98 |
|
99 |
+
$( 'input[name="save_product_sync_settings"]' ).on( 'click', function ( e ) {
|
100 |
|
101 |
if ( ! submitSettingsSave ) {
|
102 |
e.preventDefault();
|
133 |
|
134 |
blockModal();
|
135 |
|
136 |
+
submitSettingsSave = true;
|
137 |
+
$submitButton.trigger( 'click' );
|
138 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
} );
|
140 |
|
141 |
} else {
|
154 |
}
|
155 |
} );
|
156 |
|
157 |
+
// mark as in-progress if syncing when the page is loaded
|
158 |
+
if ( facebook_for_woocommerce_settings_sync.sync_in_progress ) {
|
159 |
+
syncInProgress();
|
160 |
+
}
|
161 |
+
|
162 |
+
// handle the sync button click
|
163 |
+
$( '#woocommerce-facebook-settings-sync-products' ).click( function( event ) {
|
164 |
+
|
165 |
+
event.preventDefault();
|
166 |
+
|
167 |
+
if ( confirm( facebook_for_woocommerce_settings_sync.i18n.confirm_sync ) ) {
|
168 |
+
|
169 |
+
setProductSyncStatus();
|
170 |
+
|
171 |
+
let startTime = Date.now();
|
172 |
+
|
173 |
+
$.post( facebook_for_woocommerce_settings_sync.ajax_url, {
|
174 |
+
action: 'wc_facebook_sync_products',
|
175 |
+
nonce: facebook_for_woocommerce_settings_sync.sync_products_nonce,
|
176 |
+
}, function ( response ) {
|
177 |
+
|
178 |
+
console.log( response );
|
179 |
+
|
180 |
+
if ( ! response.success ) {
|
181 |
+
|
182 |
+
let error = facebook_for_woocommerce_settings_sync.i18n.general_error;
|
183 |
+
|
184 |
+
if ( response.data && response.data.length > 0 ) {
|
185 |
+
error = response.data;
|
186 |
+
}
|
187 |
+
|
188 |
+
clearSyncInProgress( error );
|
189 |
+
|
190 |
+
} else {
|
191 |
+
|
192 |
+
// get the current sync status after a successful response but make sure to wait at least 10 seconds since the button was pressed
|
193 |
+
setTimeout( getSyncStatus, Math.max( 0, 10000 - ( Date.now() - startTime ) ) );
|
194 |
+
}
|
195 |
+
|
196 |
+
} ).fail( function() {
|
197 |
+
|
198 |
+
clearSyncInProgress( facebook_for_woocommerce_settings_sync.i18n.general_error );
|
199 |
+
|
200 |
+
} );
|
201 |
+
}
|
202 |
+
|
203 |
+
} );
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Sets the UI as sync in progress and starts an interval to check the background sync status.
|
207 |
+
*
|
208 |
+
* @since 2.0.0
|
209 |
+
*
|
210 |
+
* @param count number of items remaining
|
211 |
+
*/
|
212 |
+
function syncInProgress( count = null ) {
|
213 |
+
|
214 |
+
setProductSyncStatus( count );
|
215 |
+
|
216 |
+
if ( ! window.syncStatusInterval ) {
|
217 |
+
window.syncStatusInterval = setInterval( getSyncStatus, 10000 );
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Sets the UI as sync in progress.
|
223 |
+
*
|
224 |
+
* @since 2.0.0
|
225 |
+
*
|
226 |
+
* @param count number of items remaining
|
227 |
+
*/
|
228 |
+
function setProductSyncStatus( count = null ) {
|
229 |
+
|
230 |
+
toggleSettingOptions( false );
|
231 |
+
|
232 |
+
$( 'input#wc_facebook_enable_product_sync, input[name="save_product_sync_settings"]' ).css( 'pointer-events', 'none' ).css( 'opacity', '0.4' );
|
233 |
+
|
234 |
+
let message = facebook_for_woocommerce_settings_sync.i18n.sync_in_progress;
|
235 |
+
|
236 |
+
if ( count ) {
|
237 |
+
|
238 |
+
if ( count > 1 ) {
|
239 |
+
message = message + facebook_for_woocommerce_settings_sync.i18n.sync_remaining_items_plural;
|
240 |
+
} else {
|
241 |
+
message = message + facebook_for_woocommerce_settings_sync.i18n.sync_remaining_items_singular
|
242 |
+
}
|
243 |
+
|
244 |
+
message = message.replace( '{count}', count );
|
245 |
+
}
|
246 |
+
|
247 |
+
// set products sync status
|
248 |
+
$( '#sync_progress' ).show().html( message ).css( 'color', 'inherit' );
|
249 |
+
|
250 |
+
facebook_for_woocommerce_settings_sync.sync_in_progress = true;
|
251 |
+
}
|
252 |
+
|
253 |
+
/**
|
254 |
+
* Clears any UI for sync in progress.
|
255 |
+
*
|
256 |
+
* @since 2.0.0
|
257 |
+
*
|
258 |
+
* @param error message to display
|
259 |
+
*/
|
260 |
+
function clearSyncInProgress( error = '' ) {
|
261 |
+
|
262 |
+
facebook_for_woocommerce_settings_sync.sync_in_progress = false;
|
263 |
+
|
264 |
+
clearInterval( window.syncStatusInterval );
|
265 |
+
|
266 |
+
window.syncStatusInterval = null;
|
267 |
+
|
268 |
+
toggleSettingOptions( true );
|
269 |
+
|
270 |
+
$( 'input#wc_facebook_enable_product_sync, input[name="save_product_sync_settings"]' ).css( 'pointer-events', 'all' ).css( 'opacity', '1' );
|
271 |
+
|
272 |
+
if ( error ) {
|
273 |
+
$( '#sync_progress' ).show().html( error ).css( 'color', '#DC3232' );
|
274 |
+
} else {
|
275 |
+
$( '#sync_progress' ).hide();
|
276 |
+
}
|
277 |
+
}
|
278 |
+
|
279 |
+
/**
|
280 |
+
* Gets the current sync status.
|
281 |
+
*
|
282 |
+
* @since 2.0.0
|
283 |
+
*/
|
284 |
+
function getSyncStatus() {
|
285 |
+
|
286 |
+
if ( ! facebook_for_woocommerce_settings_sync.sync_in_progress ) {
|
287 |
+
return;
|
288 |
+
}
|
289 |
+
|
290 |
+
$.post( facebook_for_woocommerce_settings_sync.ajax_url, {
|
291 |
+
action: 'wc_facebook_get_sync_status',
|
292 |
+
nonce: facebook_for_woocommerce_settings_sync.sync_status_nonce,
|
293 |
+
}, function ( response ) {
|
294 |
+
|
295 |
+
console.log( response );
|
296 |
+
|
297 |
+
if ( response.success ) {
|
298 |
+
|
299 |
+
// the returned data represents the number of products remaining
|
300 |
+
if ( response.data > 0 ) {
|
301 |
+
syncInProgress( response.data );
|
302 |
+
} else {
|
303 |
+
clearSyncInProgress();
|
304 |
+
}
|
305 |
+
}
|
306 |
+
|
307 |
+
} );
|
308 |
+
}
|
309 |
+
|
310 |
} );
|
assets/js/admin/facebook-for-woocommerce-settings-sync.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
"use strict";jQuery(document).ready(function(a){
|
1 |
+
"use strict";jQuery(document).ready(function(a){function n(e){a(".product-sync-field").each(function(){var o=a(this);a(this).hasClass("wc-enhanced-select")&&(o=a(this).next("span.select2-container")),e?o.css("pointer-events","all").css("opacity","1.0"):o.css("pointer-events","none").css("opacity","0.4")})}a(".woocommerce-help-tip").tipTip({attribute:"data-tip",fadeIn:50,fadeOut:50,delay:200}),a("form.wc-facebook-settings").hasClass("disconnected")&&n(!1),a("input#wc_facebook_enable_product_sync").on("change",function(o){a("form.wc-facebook-settings").hasClass("disconnected")?a(this).css("pointer-events","none").css("opacity","0.4"):n(a(this).is(":checked"))}).trigger("change");var i=!1;function e(o){s(0<arguments.length&&void 0!==o?o:null),window.syncStatusInterval||(window.syncStatusInterval=setInterval(_,1e4))}function s(o){var e=0<arguments.length&&void 0!==o?o:null;n(!1),a('input#wc_facebook_enable_product_sync, input[name="save_product_sync_settings"]').css("pointer-events","none").css("opacity","0.4");var c=facebook_for_woocommerce_settings_sync.i18n.sync_in_progress;e&&(c=(c+=1<e?facebook_for_woocommerce_settings_sync.i18n.sync_remaining_items_plural:facebook_for_woocommerce_settings_sync.i18n.sync_remaining_items_singular).replace("{count}",e)),a("#sync_progress").show().html(c).css("color","inherit"),facebook_for_woocommerce_settings_sync.sync_in_progress=!0}function t(o){var e=0<arguments.length&&void 0!==o?o:"";facebook_for_woocommerce_settings_sync.sync_in_progress=!1,clearInterval(window.syncStatusInterval),n(!(window.syncStatusInterval=null)),a('input#wc_facebook_enable_product_sync, input[name="save_product_sync_settings"]').css("pointer-events","all").css("opacity","1"),e?a("#sync_progress").show().html(e).css("color","#DC3232"):a("#sync_progress").hide()}function _(){facebook_for_woocommerce_settings_sync.sync_in_progress&&a.post(facebook_for_woocommerce_settings_sync.ajax_url,{action:"wc_facebook_get_sync_status",nonce:facebook_for_woocommerce_settings_sync.sync_status_nonce},function(o){console.log(o),o.success&&(0<o.data?e(o.data):t())})}a('input[name="save_product_sync_settings"]').on("click",function(o){if(i)return!0;o.preventDefault();var e,c,n,s,t=a(this),_=(n=a("#wc_facebook_excluded_product_category_ids").val(),s=[],window.facebook_for_woocommerce_settings_sync&&window.facebook_for_woocommerce_settings_sync.excluded_category_ids&&(s=window.facebook_for_woocommerce_settings_sync.excluded_category_ids),a(n).not(s).get()),r=(e=a("#wc_facebook_excluded_product_tag_ids").val(),c=[],window.facebook_for_woocommerce_settings_sync&&window.facebook_for_woocommerce_settings_sync.excluded_tag_ids&&(c=window.facebook_for_woocommerce_settings_sync.excluded_tag_ids),a(e).not(c).get());0<_.length||0<r.length?a.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:_,tags:r},function(o){o&&!o.success?(a("#wc-backbone-modal-dialog .modal-close").trigger("click"),new a.WCBackboneModal.View({target:"facebook-for-woocommerce-modal",string:o.data}),a(".facebook-for-woocommerce-confirm-settings-change").on("click",function(){blockModal(),i=!0,t.trigger("click")})):(i=!0,t.trigger("click"))}):(i=!0,t.trigger("click"))}),facebook_for_woocommerce_settings_sync.sync_in_progress&&e(),a("#woocommerce-facebook-settings-sync-products").click(function(o){if(o.preventDefault(),confirm(facebook_for_woocommerce_settings_sync.i18n.confirm_sync)){s();var c=Date.now();a.post(facebook_for_woocommerce_settings_sync.ajax_url,{action:"wc_facebook_sync_products",nonce:facebook_for_woocommerce_settings_sync.sync_products_nonce},function(o){if(console.log(o),o.success)setTimeout(_,Math.max(0,1e4-(Date.now()-c)));else{var e=facebook_for_woocommerce_settings_sync.i18n.general_error;o.data&&0<o.data.length&&(e=o.data),t(e)}}).fail(function(){t(facebook_for_woocommerce_settings_sync.i18n.general_error)})}})});
|
assets/js/facebook-metabox.js
CHANGED
@@ -60,7 +60,7 @@ function fb_reset_product(wp_id) {
|
|
60 |
function fb_delete_product(wp_id) {
|
61 |
if (confirm(
|
62 |
'Are you sure you want to delete this product on Facebook? If you only want to "hide" the product, ' +
|
63 |
-
'
|
64 |
'this product will be recreated. To permanently remove this product from Facebook, hit "OK" and close the window.' +
|
65 |
'This will not delete the product from WooCommerce.'
|
66 |
)) {
|
60 |
function fb_delete_product(wp_id) {
|
61 |
if (confirm(
|
62 |
'Are you sure you want to delete this product on Facebook? If you only want to "hide" the product, ' +
|
63 |
+
'change the "Facebook sync" setting to "Sync and hide" and hit "Update". If you delete a product on Facebook and hit "Update" after, ' +
|
64 |
'this product will be recreated. To permanently remove this product from Facebook, hit "OK" and close the window.' +
|
65 |
'This will not delete the product from WooCommerce.'
|
66 |
)) {
|
assets/js/facebook-metabox.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
"use strict";function ajax(e){var o=1<arguments.length&&void 0!==arguments[1]?arguments[1]:null,t=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null,a=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null,n=Object.assign({},{action:e},o);jQuery.post(ajaxurl,n,function(e){t&&t(e)}).fail(function(e){a&&a(e)})}function fb_reset_product(e){if(confirm("Resetting Facebook metadata will not remove this product from your shop. If you have duplicated another product and are trying to publish a new Facebook product, click OK to proceed. Otherwise, Facebook metadata will be restored when this product is updated again.")){var o=document.querySelector("#fb_metadata");return o&&(o.innerHTML="<b>This product is not yet synced to Facebook.</b>"),ajax("ajax_reset_single_fb_product",{wp_id:e,_ajax_nonce:wc_facebook_metabox_jsx.nonce})}}function fb_delete_product(e){if(confirm('Are you sure you want to delete this product on Facebook? If you only want to "hide" the product,
|
1 |
+
"use strict";function ajax(e){var o=1<arguments.length&&void 0!==arguments[1]?arguments[1]:null,t=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null,a=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null,n=Object.assign({},{action:e},o);jQuery.post(ajaxurl,n,function(e){t&&t(e)}).fail(function(e){a&&a(e)})}function fb_reset_product(e){if(confirm("Resetting Facebook metadata will not remove this product from your shop. If you have duplicated another product and are trying to publish a new Facebook product, click OK to proceed. Otherwise, Facebook metadata will be restored when this product is updated again.")){var o=document.querySelector("#fb_metadata");return o&&(o.innerHTML="<b>This product is not yet synced to Facebook.</b>"),ajax("ajax_reset_single_fb_product",{wp_id:e,_ajax_nonce:wc_facebook_metabox_jsx.nonce})}}function fb_delete_product(e){if(confirm('Are you sure you want to delete this product on Facebook? If you only want to "hide" the product, change the "Facebook sync" setting to "Sync and hide" and hit "Update". If you delete a product on Facebook and hit "Update" after, this product will be recreated. To permanently remove this product from Facebook, hit "OK" and close the window.This will not delete the product from WooCommerce.')){var o=document.querySelector("#fb_metadata");return o&&(o.innerHTML="<b>This product is not yet synced to Facebook.</b>"),ajax("ajax_delete_fb_product",{wp_id:e,_ajax_nonce:wc_facebook_metabox_jsx.nonce})}}
|
assets/js/facebook-settings.js
DELETED
@@ -1,1099 +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 |
-
var fb_sync_no_response_count = 0;
|
11 |
-
var fb_show_advanced_options = false;
|
12 |
-
|
13 |
-
|
14 |
-
function openPopup() {
|
15 |
-
var width = 1153;
|
16 |
-
var height = 808;
|
17 |
-
var topPos = screen.height / 2 - height / 2;
|
18 |
-
var leftPos = screen.width / 2 - width / 2;
|
19 |
-
window.originParam = window.location.protocol + '//' + window.location.host;
|
20 |
-
var popupUrl;
|
21 |
-
if (window.facebookAdsToolboxConfig.popupOrigin.includes( 'staticxx' )) {
|
22 |
-
window.facebookAdsToolboxConfig.popupOrigin = 'https://www.facebook.com/';
|
23 |
-
}
|
24 |
-
window.facebookAdsToolboxConfig.popupOrigin = prepend_protocol(
|
25 |
-
window.facebookAdsToolboxConfig.popupOrigin
|
26 |
-
);
|
27 |
-
popupUrl = window.facebookAdsToolboxConfig.popupOrigin;
|
28 |
-
|
29 |
-
var path = '/ads/dia';
|
30 |
-
var page = window.open( popupUrl + '/login.php?display=popup&next=' + encodeURIComponent( popupUrl + path + '?origin=' + window.originParam + ' &merchant_settings_id=' + window.facebookAdsToolboxConfig.diaSettingId ), 'DiaWizard', ['toolbar=no', 'location=no', 'directories=no', 'status=no', 'menubar=no', 'scrollbars=no', 'resizable=no', 'copyhistory=no', 'width=' + width, 'height=' + height, 'top=' + topPos, 'left=' + leftPos].join( ',' ) );
|
31 |
-
|
32 |
-
return function (type, params) {
|
33 |
-
page.postMessage(
|
34 |
-
{
|
35 |
-
type: type,
|
36 |
-
params: params
|
37 |
-
},
|
38 |
-
window.facebookAdsToolboxConfig.popupOrigin
|
39 |
-
);
|
40 |
-
};
|
41 |
-
}
|
42 |
-
|
43 |
-
function prepend_protocol(url) {
|
44 |
-
// Preprend https if the url begis with //www.
|
45 |
-
if (url.indexOf( '//www.' ) === 0) {
|
46 |
-
url = 'https:' + url;
|
47 |
-
}
|
48 |
-
return url;
|
49 |
-
}
|
50 |
-
|
51 |
-
|
52 |
-
/**
|
53 |
-
* Gets the input Element that holds the value for the Pixel ID setting.
|
54 |
-
*
|
55 |
-
* @returns {(Element|null)}
|
56 |
-
*/
|
57 |
-
function get_pixel_id_box() {
|
58 |
-
|
59 |
-
return document.querySelector( '#woocommerce_facebookcommerce_facebook_pixel_id' );
|
60 |
-
}
|
61 |
-
|
62 |
-
|
63 |
-
/**
|
64 |
-
* Gets the input Element that holds the value for the Use Advanced Matching setting.
|
65 |
-
*
|
66 |
-
* @returns {(Element|null)}
|
67 |
-
*/
|
68 |
-
function get_pixel_use_pii_id_box() {
|
69 |
-
|
70 |
-
return document.querySelector( '#woocommerce_facebookcommerce_enable_advanced_matching' );
|
71 |
-
}
|
72 |
-
|
73 |
-
|
74 |
-
/**
|
75 |
-
* Gets the input Element that holds the value for the Facebook page setting.
|
76 |
-
*
|
77 |
-
* @return {(Element|null)}
|
78 |
-
*/
|
79 |
-
function get_page_id_box() {
|
80 |
-
|
81 |
-
return document.querySelector( '#woocommerce_facebookcommerce_facebook_page_id' );
|
82 |
-
}
|
83 |
-
|
84 |
-
|
85 |
-
/*
|
86 |
-
* Ajax helper function.
|
87 |
-
* Takes optional payload for POST and optional callback.
|
88 |
-
*/
|
89 |
-
function ajax(action, payload = null, callback = null, failcallback = null) {
|
90 |
-
var data = Object.assign(
|
91 |
-
{},
|
92 |
-
{
|
93 |
-
'action': action,
|
94 |
-
},
|
95 |
-
payload
|
96 |
-
);
|
97 |
-
|
98 |
-
// Since Wordpress 2.8 ajaxurl is always defined in admin header and
|
99 |
-
// points to admin-ajax.php
|
100 |
-
jQuery.post(
|
101 |
-
ajaxurl,
|
102 |
-
data,
|
103 |
-
function(response) {
|
104 |
-
if (callback) {
|
105 |
-
callback( response );
|
106 |
-
}
|
107 |
-
}
|
108 |
-
).fail(
|
109 |
-
function(errorResponse){
|
110 |
-
if (failcallback) {
|
111 |
-
failcallback( errorResponse );
|
112 |
-
}
|
113 |
-
}
|
114 |
-
);
|
115 |
-
}
|
116 |
-
|
117 |
-
var settings = {'facebook_for_woocommerce' : 1};
|
118 |
-
var pixel_settings = {'facebook_for_woocommerce' : 1};
|
119 |
-
|
120 |
-
function facebookConfig() {
|
121 |
-
window.sendToFacebook = openPopup();
|
122 |
-
window.diaConfig = { 'clientSetup': window.facebookAdsToolboxConfig };
|
123 |
-
}
|
124 |
-
|
125 |
-
function fb_flush(){
|
126 |
-
console.log( "Removing all FBIDs from all products!" );
|
127 |
-
return ajax(
|
128 |
-
'ajax_reset_all_fb_products',
|
129 |
-
{"_ajax_nonce": wc_facebook_settings_jsx.nonce},
|
130 |
-
null,
|
131 |
-
function fb_flushFailCallback(error) {
|
132 |
-
console.log('Failed to reset all FB products');
|
133 |
-
}
|
134 |
-
);
|
135 |
-
}
|
136 |
-
|
137 |
-
|
138 |
-
/**
|
139 |
-
* Shows a confirm dialog and starts product sync if the user selectes OK.
|
140 |
-
*
|
141 |
-
* @param {String} verbose an identifier for the confirmation message to display
|
142 |
-
*/
|
143 |
-
function sync_confirm(verbose = null) {
|
144 |
-
|
145 |
-
let msg = '';
|
146 |
-
|
147 |
-
switch (verbose) {
|
148 |
-
|
149 |
-
case 'fb_force_resync':
|
150 |
-
msg = facebook_for_woocommerce_settings_sync.i18n.confirm_resync;
|
151 |
-
break;
|
152 |
-
|
153 |
-
case 'fb_test_product_sync':
|
154 |
-
msg = facebook_for_woocommerce_settings_sync.i18n.confirm_sync_test;
|
155 |
-
break;
|
156 |
-
|
157 |
-
default:
|
158 |
-
msg = facebook_for_woocommerce_settings_sync.i18n.confirm_sync;
|
159 |
-
}
|
160 |
-
|
161 |
-
if ( confirm( msg ) ) {
|
162 |
-
|
163 |
-
sync_all_products( window.facebookAdsToolboxConfig.feed.hasClientSideFeedUpload, verbose == 'fb_test_product_sync' );
|
164 |
-
|
165 |
-
window.fb_sync_start_time = new Date().getTime();
|
166 |
-
}
|
167 |
-
}
|
168 |
-
|
169 |
-
/*
|
170 |
-
* Launch the confirm dialog immediately if the param is in the URL.
|
171 |
-
* TODO: restore after migration to FBE 2.0
|
172 |
-
*
|
173 |
-
if (window.location.href.includes( "fb_force_resync" )) {
|
174 |
-
window.onload = function() { sync_confirm( "fb_force_resync" ); };
|
175 |
-
} else if (window.location.href.includes( "fb_test_product_sync" )) {
|
176 |
-
// Test products sync by feed.
|
177 |
-
window.is_test = true;
|
178 |
-
window.onload = function() { sync_confirm( "fb_test_product_sync" ); };
|
179 |
-
}
|
180 |
-
*/
|
181 |
-
|
182 |
-
|
183 |
-
/**
|
184 |
-
* Sends Ajax request to the backend to initiate product sync.
|
185 |
-
*
|
186 |
-
* @param {boolean} feed whether products should be synced using feed or not
|
187 |
-
* @param {boolean} test whether this is a sync test
|
188 |
-
*/
|
189 |
-
function sync_all_products($using_feed = false, $is_test = false) {
|
190 |
-
|
191 |
-
window.fb_connected = true;
|
192 |
-
sync_in_progress();
|
193 |
-
|
194 |
-
let data = {};
|
195 |
-
|
196 |
-
if ( $using_feed ) {
|
197 |
-
|
198 |
-
window.facebookAdsToolboxConfig.feed.hasClientSideFeedUpload = true;
|
199 |
-
window.feed_upload = true;
|
200 |
-
|
201 |
-
ping_feed_status_queue();
|
202 |
-
|
203 |
-
if ( $is_test ) {
|
204 |
-
|
205 |
-
data = { action: 'ajax_test_sync_products_using_feed' };
|
206 |
-
|
207 |
-
} else {
|
208 |
-
|
209 |
-
data = {
|
210 |
-
action: 'ajax_sync_all_fb_products_using_feed',
|
211 |
-
_ajax_nonce: wc_facebook_settings_jsx.nonce,
|
212 |
-
};
|
213 |
-
|
214 |
-
}
|
215 |
-
|
216 |
-
} else {
|
217 |
-
|
218 |
-
check_background_processor_status();
|
219 |
-
|
220 |
-
data = {
|
221 |
-
action: 'ajax_sync_all_fb_products',
|
222 |
-
_ajax_nonce: wc_facebook_settings_jsx.nonce,
|
223 |
-
};
|
224 |
-
}
|
225 |
-
|
226 |
-
jQuery.post( ajaxurl, data ).then( function( response ) {
|
227 |
-
|
228 |
-
// something is wrong if we are syncing products using feed and the response is empty or indicates a failure
|
229 |
-
// we ignore empty responses if using the background processor because in those cases the request does not return a response when the operation is successful
|
230 |
-
if ( ( ! response && $using_feed ) || ( response && false === response.success ) ) {
|
231 |
-
|
232 |
-
// no need to check the queue or upload status
|
233 |
-
clearInterval( window.fb_pings );
|
234 |
-
clearInterval( window.fb_feed_pings );
|
235 |
-
|
236 |
-
// enable Manage connection and Sync products buttons when sync stops
|
237 |
-
jQuery( '#woocommerce-facebook-settings-manage-connection, #woocommerce-facebook-settings-sync-products' ).css( 'pointer-events', 'auto' );
|
238 |
-
|
239 |
-
let message;
|
240 |
-
|
241 |
-
if ( response && response.data && response.data.error ) {
|
242 |
-
message = response.data.error;
|
243 |
-
} else {
|
244 |
-
message = facebook_for_woocommerce_settings_sync.i18n.general_error;
|
245 |
-
}
|
246 |
-
|
247 |
-
jQuery( '#sync_progress' ).show().html( '<span style="color: #DC3232">' + message + '</span>' );
|
248 |
-
}
|
249 |
-
} );
|
250 |
-
}
|
251 |
-
|
252 |
-
|
253 |
-
// Reset all state
|
254 |
-
function delete_all_settings(callback = null, failcallback = null) {
|
255 |
-
|
256 |
-
if (get_pixel_id_box()) {
|
257 |
-
get_pixel_id_box().value = '';
|
258 |
-
}
|
259 |
-
if (get_pixel_use_pii_id_box()) {
|
260 |
-
get_pixel_use_pii_id_box().checked = false;
|
261 |
-
}
|
262 |
-
|
263 |
-
if (get_page_id_box()) {
|
264 |
-
get_page_id_box().value = '';
|
265 |
-
}
|
266 |
-
|
267 |
-
// reset messenger settings to their default values
|
268 |
-
jQuery( '#woocommerce_facebookcommerce_enable_messenger' ).prop( 'checked', false ).trigger( 'change' );
|
269 |
-
|
270 |
-
jQuery( '.messenger-field' ).each( function () {
|
271 |
-
|
272 |
-
if ( typeof jQuery( this ).data( 'default' ) !== 'undefined' ) {
|
273 |
-
jQuery( this ).val( jQuery( this ).data( 'default' ) ).trigger( 'change' );
|
274 |
-
}
|
275 |
-
} );
|
276 |
-
|
277 |
-
window.facebookAdsToolboxConfig.pixel.pixelId = '';
|
278 |
-
window.facebookAdsToolboxConfig.diaSettingId = '';
|
279 |
-
window.fb_connected = false;
|
280 |
-
|
281 |
-
not_connected();
|
282 |
-
|
283 |
-
console.log( 'Deleting all settings and removing all FBIDs!' );
|
284 |
-
return ajax(
|
285 |
-
'ajax_delete_fb_settings',
|
286 |
-
{
|
287 |
-
"_ajax_nonce": wc_facebook_settings_jsx.nonce,
|
288 |
-
},
|
289 |
-
callback,
|
290 |
-
failcallback
|
291 |
-
);
|
292 |
-
}
|
293 |
-
|
294 |
-
// save_settings and save_settings_and_sync should only be called once
|
295 |
-
// after all variables are set up in the settings global variable
|
296 |
-
// if called multiple times, race conditions might occur
|
297 |
-
// ---
|
298 |
-
// It's also called again if the pixel id is ever changed or pixel pii is
|
299 |
-
// enabled or disabled.
|
300 |
-
function save_settings(callback = null, failcallback = null, localsettings = null){
|
301 |
-
if ( ! localsettings) {
|
302 |
-
localsettings = settings;
|
303 |
-
}
|
304 |
-
localsettings["_ajax_nonce"] = wc_facebook_settings_jsx.nonce;
|
305 |
-
ajax(
|
306 |
-
'ajax_save_fb_settings',
|
307 |
-
localsettings,
|
308 |
-
function(response){
|
309 |
-
if (callback) {
|
310 |
-
callback( response );
|
311 |
-
}
|
312 |
-
},
|
313 |
-
function(errorResponse){
|
314 |
-
if (failcallback) {
|
315 |
-
failcallback( errorResponse );
|
316 |
-
}
|
317 |
-
}
|
318 |
-
);
|
319 |
-
}
|
320 |
-
|
321 |
-
// save_settings wrapper for plugins as we do not need to:
|
322 |
-
// 1. sync products again after plugin is configured
|
323 |
-
// 2. check api_key, which is from facebook and is only necessary
|
324 |
-
// for following sync products
|
325 |
-
function save_settings_for_plugin(callback, failcallback) {
|
326 |
-
save_settings(
|
327 |
-
function(response){
|
328 |
-
if (response && true === response.success ) {
|
329 |
-
console.log( response );
|
330 |
-
callback( response );
|
331 |
-
} else {
|
332 |
-
console.log( 'Fail response on save_settings_for_plugin' );
|
333 |
-
failcallback( response );
|
334 |
-
}
|
335 |
-
},
|
336 |
-
function(errorResponse){
|
337 |
-
console.log( 'Ajax error while saving settings:' + JSON.stringify( errorResponse ) );
|
338 |
-
failcallback( errorResponse );
|
339 |
-
}
|
340 |
-
);
|
341 |
-
}
|
342 |
-
|
343 |
-
// see comments in save_settings function above
|
344 |
-
function save_settings_and_sync(message) {
|
345 |
-
if ('api_key' in settings) {
|
346 |
-
save_settings(
|
347 |
-
function(response){
|
348 |
-
if (response && response.includes( 'settings_saved' )) {
|
349 |
-
console.log( response );
|
350 |
-
// Final acks
|
351 |
-
window.sendToFacebook( 'ack set pixel', message.params );
|
352 |
-
window.sendToFacebook( 'ack set page access token', message.params );
|
353 |
-
window.sendToFacebook( 'ack set merchant settings', message.params );
|
354 |
-
// sync_all_products( true ); TODO: reinstate when switching back to FBE 2
|
355 |
-
} else {
|
356 |
-
window.sendToFacebook( 'fail save_settings', response );
|
357 |
-
console.log( 'Fail response on save_settings_and_sync' );
|
358 |
-
}
|
359 |
-
},
|
360 |
-
function(errorResponse){
|
361 |
-
console.log( 'Ajax error while saving settings:' + JSON.stringify( errorResponse ) );
|
362 |
-
window.sendToFacebook( 'fail save_settings_ajax', JSON.stringify( errorResponse ) );
|
363 |
-
}
|
364 |
-
);
|
365 |
-
}
|
366 |
-
}
|
367 |
-
|
368 |
-
|
369 |
-
/**
|
370 |
-
* Prepares UI for product sync.
|
371 |
-
*/
|
372 |
-
function sync_in_progress() {
|
373 |
-
|
374 |
-
// temporarily disable Manage connection and Sync products buttons
|
375 |
-
jQuery( '#woocommerce-facebook-settings-manage-connection, #woocommerce-facebook-settings-sync-products' ).css( 'pointer-events', 'none' );
|
376 |
-
|
377 |
-
// set products sync status
|
378 |
-
jQuery( '#sync_progress' ).show().html( facebook_for_woocommerce_settings_sync.i18n.sync_in_progress );
|
379 |
-
}
|
380 |
-
|
381 |
-
|
382 |
-
/**
|
383 |
-
* Hides sync progress and enable Manage connection and Sync products buttons.
|
384 |
-
*/
|
385 |
-
function sync_not_in_progress() {
|
386 |
-
|
387 |
-
// enable Manage connection and Sync products buttons when sync is complete
|
388 |
-
jQuery( '#woocommerce-facebook-settings-manage-connection, #woocommerce-facebook-settings-sync-products' ).css( 'pointer-events', 'auto' );
|
389 |
-
|
390 |
-
// Remove sync progress.
|
391 |
-
jQuery( '#sync_progress' ).empty().hide();
|
392 |
-
}
|
393 |
-
|
394 |
-
|
395 |
-
/**
|
396 |
-
* Shows Facebook fancy box if the store is still not connected to Facebook.
|
397 |
-
*
|
398 |
-
* Also hides the integration settings fields.
|
399 |
-
*/
|
400 |
-
function not_connected() {
|
401 |
-
|
402 |
-
jQuery( '#fbsetup' ).show();
|
403 |
-
jQuery( '#integration-settings' ).hide();
|
404 |
-
jQuery( '.woocommerce-save-button' ).hide();
|
405 |
-
}
|
406 |
-
|
407 |
-
function addAnEventListener(obj,evt,func) {
|
408 |
-
if ('addEventListener' in obj) {
|
409 |
-
obj.addEventListener( evt,func, false );
|
410 |
-
} else if ('attachEvent' in obj) {// IE
|
411 |
-
obj.attachEvent( 'on' + evt,func );
|
412 |
-
}
|
413 |
-
}
|
414 |
-
|
415 |
-
function setMerchantSettings(message) {
|
416 |
-
if ( ! message.params.setting_id) {
|
417 |
-
console.error( 'Facebook Extension Error: got no setting_id', message.params );
|
418 |
-
window.sendToFacebook( 'fail set merchant settings', message.params );
|
419 |
-
return;
|
420 |
-
}
|
421 |
-
|
422 |
-
settings.external_merchant_settings_id = message.params.setting_id;
|
423 |
-
|
424 |
-
// Immediately set in case button is clicked again
|
425 |
-
window.facebookAdsToolboxConfig.diaSettingId = message.params.setting_id;
|
426 |
-
// Ack merchant settings happens after settings are saved
|
427 |
-
}
|
428 |
-
|
429 |
-
function setCatalog(message) {
|
430 |
-
if ( ! message.params.catalog_id) {
|
431 |
-
console.error( 'Facebook Extension Error: got no catalog_id', message.params );
|
432 |
-
window.sendToFacebook( 'fail set catalog', message.params );
|
433 |
-
return;
|
434 |
-
}
|
435 |
-
|
436 |
-
settings.product_catalog_id = message.params.catalog_id;
|
437 |
-
|
438 |
-
window.sendToFacebook( 'ack set catalog', message.params );
|
439 |
-
}
|
440 |
-
|
441 |
-
|
442 |
-
function setPixel(message) {
|
443 |
-
if ( ! message.params.pixel_id) {
|
444 |
-
console.error( 'Facebook Ads Extension Error: got no pixel_id', message.params );
|
445 |
-
window.sendToFacebook( 'fail set pixel', message.params );
|
446 |
-
return;
|
447 |
-
}
|
448 |
-
if (get_pixel_id_box()) {
|
449 |
-
get_pixel_id_box().value = message.params.pixel_id;
|
450 |
-
}
|
451 |
-
|
452 |
-
settings.pixel_id = message.params.pixel_id;
|
453 |
-
pixel_settings.pixel_id = settings.pixel_id;
|
454 |
-
if (message.params.pixel_use_pii !== undefined) {
|
455 |
-
if (get_pixel_use_pii_id_box()) {
|
456 |
-
// !! will explicitly convert truthy/falsy values to a boolean
|
457 |
-
get_pixel_use_pii_id_box().checked = ! ! message.params.pixel_use_pii;
|
458 |
-
}
|
459 |
-
settings.pixel_use_pii = message.params.pixel_use_pii;
|
460 |
-
pixel_settings.pixel_use_pii = settings.pixel_use_pii;
|
461 |
-
}
|
462 |
-
|
463 |
-
// We need this to support changing the pixel id after setup.
|
464 |
-
save_settings(
|
465 |
-
function(response){
|
466 |
-
if (response && true === response.success ) {
|
467 |
-
window.sendToFacebook( 'ack set pixel', message.params );
|
468 |
-
} //may not get settings_saved if we try to save pixel before an API key
|
469 |
-
},
|
470 |
-
function(errorResponse){
|
471 |
-
console.log( errorResponse );
|
472 |
-
window.sendToFacebook( 'fail set pixel', errorResponse );
|
473 |
-
},
|
474 |
-
pixel_settings
|
475 |
-
);
|
476 |
-
}
|
477 |
-
|
478 |
-
function genFeed( message ) {
|
479 |
-
|
480 |
-
console.log( 'generating feed' );
|
481 |
-
|
482 |
-
jQuery.get( window.facebookAdsToolboxConfig.feedPrepared.feedUrl + '®enerate=true' )
|
483 |
-
.done( function( json ) {
|
484 |
-
window.sendToFacebook( 'ack feed', message.params );
|
485 |
-
} )
|
486 |
-
.fail( function( xhr, ajaxOptions, thronwError ) {
|
487 |
-
window.sendToFacebook( 'fail feed', message.params );
|
488 |
-
} );
|
489 |
-
}
|
490 |
-
|
491 |
-
function setAccessTokenAndPageId(message) {
|
492 |
-
if ( ! message.params.page_token) {
|
493 |
-
console.error(
|
494 |
-
'Facebook Ads Extension Error: got no page_token',
|
495 |
-
message.params
|
496 |
-
);
|
497 |
-
window.sendToFacebook( 'fail set page access token', message.params );
|
498 |
-
return;
|
499 |
-
}
|
500 |
-
|
501 |
-
if (get_page_id_box()) {
|
502 |
-
get_page_id_box().value = message.params.page_id;
|
503 |
-
}
|
504 |
-
|
505 |
-
settings.api_key = message.params.page_token;
|
506 |
-
settings.page_id = message.params.page_id;
|
507 |
-
// Ack token in "save_settings_and_sync" for final ack
|
508 |
-
|
509 |
-
window.facebookAdsToolboxConfig.tokenExpired = false;
|
510 |
-
|
511 |
-
if ( document.querySelector( '#connection-message-invalid' ) ) {
|
512 |
-
document.querySelector( '#connection-message-invalid' ).style.display = 'none';
|
513 |
-
}
|
514 |
-
|
515 |
-
if ( document.querySelector( '#connection-message-refresh' ) ) {
|
516 |
-
document.querySelector( '#connection-message-refresh' ).style.display = 'block';
|
517 |
-
}
|
518 |
-
}
|
519 |
-
|
520 |
-
function setMsgerChatSetup( data ) {
|
521 |
-
|
522 |
-
if ( data.hasOwnProperty( 'is_messenger_chat_plugin_enabled' ) ) {
|
523 |
-
|
524 |
-
settings.is_messenger_chat_plugin_enabled = data.is_messenger_chat_plugin_enabled;
|
525 |
-
|
526 |
-
jQuery( '#woocommerce_facebookcommerce_enable_messenger' ).prop( 'checked', data.is_messenger_chat_plugin_enabled ).trigger( 'change' );
|
527 |
-
}
|
528 |
-
|
529 |
-
if (data.hasOwnProperty( 'facebook_jssdk_version' )) {
|
530 |
-
settings.facebook_jssdk_version =
|
531 |
-
data.facebook_jssdk_version;
|
532 |
-
}
|
533 |
-
if (data.hasOwnProperty( 'page_id' )) {
|
534 |
-
settings.fb_page_id = data.page_id;
|
535 |
-
}
|
536 |
-
|
537 |
-
if ( data.hasOwnProperty( 'customization' ) ) {
|
538 |
-
|
539 |
-
const customization = data.customization;
|
540 |
-
|
541 |
-
if ( customization.hasOwnProperty( 'greetingTextCode' ) ) {
|
542 |
-
|
543 |
-
settings.msger_chat_customization_greeting_text_code = customization.greetingTextCode;
|
544 |
-
|
545 |
-
jQuery( '#woocommerce_facebookcommerce_messenger_greeting' ).val( customization.greetingTextCode ).trigger( 'change' );
|
546 |
-
}
|
547 |
-
|
548 |
-
if ( customization.hasOwnProperty( 'locale' ) ) {
|
549 |
-
|
550 |
-
settings.msger_chat_customization_locale = customization.locale;
|
551 |
-
|
552 |
-
jQuery( '#woocommerce_facebookcommerce_messenger_locale' ).val( customization.locale ).trigger( 'change' );
|
553 |
-
}
|
554 |
-
|
555 |
-
if ( customization.hasOwnProperty( 'themeColorCode' ) ) {
|
556 |
-
|
557 |
-
settings.msger_chat_customization_theme_color_code = customization.themeColorCode;
|
558 |
-
|
559 |
-
jQuery( '#woocommerce_facebookcommerce_messenger_color_hex' ).val( customization.themeColorCode ).trigger( 'change' );
|
560 |
-
}
|
561 |
-
}
|
562 |
-
}
|
563 |
-
|
564 |
-
function setFeedMigrated(message) {
|
565 |
-
|
566 |
-
if ( ! message.params.hasOwnProperty( 'feed_migrated' ) ) {
|
567 |
-
|
568 |
-
console.error(
|
569 |
-
'Facebook Extension Error: feed migrated not received',
|
570 |
-
message.params
|
571 |
-
);
|
572 |
-
|
573 |
-
window.sendToFacebook( 'fail set feed migrated', message.params );
|
574 |
-
return;
|
575 |
-
}
|
576 |
-
|
577 |
-
settings.feed_migrated = message.params.feed_migrated;
|
578 |
-
window.facebookAdsToolboxConfig.feedPrepared.feedMigrated = message.params.feed_migrated;
|
579 |
-
|
580 |
-
jQuery( '#woocommerce-facebook-settings-sync-products' ).hide();
|
581 |
-
jQuery( '.notice.wc-facebook-migrate-notice' ).hide();
|
582 |
-
|
583 |
-
save_settings_for_plugin(
|
584 |
-
function( response ) {
|
585 |
-
window.sendToFacebook( 'ack set feed migrated', event.data );
|
586 |
-
},
|
587 |
-
function( response ) {
|
588 |
-
window.sendToFacebook( 'fail set feed migrated', event.data );
|
589 |
-
}
|
590 |
-
);
|
591 |
-
}
|
592 |
-
|
593 |
-
function iFrameListener( event ) {
|
594 |
-
|
595 |
-
const origin = event.origin || event.originalEvent.origin;
|
596 |
-
|
597 |
-
if ( origin !== window.facebookAdsToolboxConfig.popupOrigin ) {
|
598 |
-
|
599 |
-
// Fix for web.facebook.com
|
600 |
-
if ( urlFromSameDomain( origin, window.facebookAdsToolboxConfig.popupOrigin ) ) {
|
601 |
-
|
602 |
-
window.facebookAdsToolboxConfig.popupOrigin = origin;
|
603 |
-
|
604 |
-
// otherwise bail if not a message from facebook.com
|
605 |
-
} else {
|
606 |
-
|
607 |
-
return;
|
608 |
-
}
|
609 |
-
}
|
610 |
-
|
611 |
-
switch (event.data.type) {
|
612 |
-
case 'reset':
|
613 |
-
delete_all_settings(
|
614 |
-
function(res){
|
615 |
-
if (res && event.data.params) {
|
616 |
-
if (res === 'Settings Deleted') {
|
617 |
-
window.sendToFacebook( 'ack reset', event.data.params );
|
618 |
-
} else {
|
619 |
-
console.log( res );
|
620 |
-
alert( res );
|
621 |
-
}
|
622 |
-
} else {
|
623 |
-
console.log( "Got no response from delete_all_settings" );
|
624 |
-
}
|
625 |
-
},
|
626 |
-
function(err){
|
627 |
-
console.error( err );
|
628 |
-
}
|
629 |
-
);
|
630 |
-
break;
|
631 |
-
case 'get dia settings':
|
632 |
-
window.sendToFacebook( 'dia settings', window.diaConfig );
|
633 |
-
break;
|
634 |
-
case 'set catalog':
|
635 |
-
setCatalog( event.data );
|
636 |
-
break;
|
637 |
-
case 'set feed migrated':
|
638 |
-
setFeedMigrated( event.data );
|
639 |
-
break;
|
640 |
-
case 'set pixel':
|
641 |
-
setPixel( event.data );
|
642 |
-
break;
|
643 |
-
case 'gen feed':
|
644 |
-
genFeed( event.data );
|
645 |
-
break;
|
646 |
-
|
647 |
-
// simulate this success response so FBE considers setup complete
|
648 |
-
case 'set page access token':
|
649 |
-
window.sendToFacebook( 'ack set page access token', event.data.params );
|
650 |
-
break;
|
651 |
-
|
652 |
-
case 'set page':
|
653 |
-
setPage( event.data );
|
654 |
-
break;
|
655 |
-
|
656 |
-
case 'set merchant settings':
|
657 |
-
|
658 |
-
setMerchantSettings( event.data );
|
659 |
-
|
660 |
-
// this should be the final message sent, so save the settings at this point
|
661 |
-
save_settings(
|
662 |
-
function( response ) {
|
663 |
-
|
664 |
-
console.log( response );
|
665 |
-
|
666 |
-
if ( response && true === response.success ) {
|
667 |
-
|
668 |
-
// final acks
|
669 |
-
if ( settings.pixel_id ) {
|
670 |
-
window.sendToFacebook( 'ack set pixel', event.data.params );
|
671 |
-
}
|
672 |
-
|
673 |
-
if ( settings.page_id ) {
|
674 |
-
window.sendToFacebook( 'ack set page', event.data.params );
|
675 |
-
}
|
676 |
-
|
677 |
-
if ( settings.external_merchant_settings_id ) {
|
678 |
-
|
679 |
-
window.sendToFacebook( 'ack set merchant settings', event.data.params );
|
680 |
-
|
681 |
-
// hide Facebook fancy box and show integration settings
|
682 |
-
jQuery( '#fbsetup' ).hide();
|
683 |
-
jQuery( '#integration-settings' ).show();
|
684 |
-
jQuery( '.woocommerce-save-button' ).show();
|
685 |
-
}
|
686 |
-
|
687 |
-
} else {
|
688 |
-
|
689 |
-
window.sendToFacebook( 'fail save_settings', response );
|
690 |
-
|
691 |
-
console.log( 'Fail response on save_settings' );
|
692 |
-
}
|
693 |
-
},
|
694 |
-
function( errorResponse ){
|
695 |
-
|
696 |
-
console.log( 'Ajax error while saving settings:' + JSON.stringify( errorResponse ) );
|
697 |
-
|
698 |
-
window.sendToFacebook( 'fail save_settings_ajax', JSON.stringify( errorResponse ) );
|
699 |
-
}
|
700 |
-
);
|
701 |
-
|
702 |
-
break;
|
703 |
-
|
704 |
-
case 'set msger chat':
|
705 |
-
setMsgerChatSetup( event.data.params );
|
706 |
-
save_settings_for_plugin(
|
707 |
-
function(response) {
|
708 |
-
window.sendToFacebook( 'ack msger chat', event.data );
|
709 |
-
},
|
710 |
-
function(response) {
|
711 |
-
window.sendToFacebook( 'fail msger chat', event.data );
|
712 |
-
}
|
713 |
-
);
|
714 |
-
break;
|
715 |
-
}
|
716 |
-
}
|
717 |
-
|
718 |
-
addAnEventListener( window,'message',iFrameListener );
|
719 |
-
|
720 |
-
/**
|
721 |
-
* Sets the page parameters received from FBE.
|
722 |
-
*
|
723 |
-
* @since 1.11.0
|
724 |
-
*
|
725 |
-
* @param {Object} message
|
726 |
-
*/
|
727 |
-
function setPage( message ) {
|
728 |
-
|
729 |
-
if ( ! message.params.hasOwnProperty( 'page_id' ) ) {
|
730 |
-
|
731 |
-
console.error(
|
732 |
-
'Facebook Extension Error: page ID not received',
|
733 |
-
message.params
|
734 |
-
);
|
735 |
-
|
736 |
-
window.sendToFacebook( 'fail set page', message.params );
|
737 |
-
return;
|
738 |
-
}
|
739 |
-
|
740 |
-
settings.page_id = message.params.page_id;
|
741 |
-
|
742 |
-
jQuery( '#woocommerce_facebookcommerce_facebook_page_id' ).val( settings.page_id );
|
743 |
-
}
|
744 |
-
|
745 |
-
function urlFromSameDomain(url1, url2) {
|
746 |
-
if ( ! url1.startsWith( 'http' ) || ! url2.startsWith( 'http' )) {
|
747 |
-
return false;
|
748 |
-
}
|
749 |
-
var u1 = parseURL( url1 );
|
750 |
-
var u2 = parseURL( url2 );
|
751 |
-
var u1host = u1.host.replace( /^\w+\./, 'www.' );
|
752 |
-
var u2host = u2.host.replace( /^\w+\./, 'www.' );
|
753 |
-
return u1.protocol === u2.protocol && u1host === u2host;
|
754 |
-
}
|
755 |
-
|
756 |
-
function parseURL(url) {
|
757 |
-
var parser = document.createElement( 'a' );
|
758 |
-
parser.href = url;
|
759 |
-
return parser;
|
760 |
-
}
|
761 |
-
|
762 |
-
|
763 |
-
/**
|
764 |
-
* Setups an interval to check the status a product sync being executed in the background.
|
765 |
-
*
|
766 |
-
* @since 1.10.0
|
767 |
-
*/
|
768 |
-
function check_background_processor_status() {
|
769 |
-
|
770 |
-
if ( ! window.facebookAdsToolboxConfig.feed.hasClientSideFeedUpload ) {
|
771 |
-
|
772 |
-
// sanity check to remove any running intervals
|
773 |
-
clearInterval( window.fb_pings );
|
774 |
-
|
775 |
-
window.fb_pings = setInterval( function() {
|
776 |
-
console.log( "Pinging queue..." );
|
777 |
-
check_queues();
|
778 |
-
}, 10000 );
|
779 |
-
}
|
780 |
-
}
|
781 |
-
|
782 |
-
|
783 |
-
function ping_feed_status_queue(count = 0) {
|
784 |
-
|
785 |
-
// sanity check to remove any running intervals
|
786 |
-
clearInterval( window.fb_feed_pings );
|
787 |
-
|
788 |
-
window.fb_feed_pings = setInterval(
|
789 |
-
function() {
|
790 |
-
console.log( 'Pinging feed uploading queue...' );
|
791 |
-
check_feed_upload_queue( count );
|
792 |
-
},
|
793 |
-
30000 * (1 << count)
|
794 |
-
);
|
795 |
-
}
|
796 |
-
|
797 |
-
function product_sync_complete( $sync_progress_element ) {
|
798 |
-
|
799 |
-
sync_not_in_progress();
|
800 |
-
|
801 |
-
$sync_progress_element.empty().hide();
|
802 |
-
|
803 |
-
clearInterval( window.fb_pings );
|
804 |
-
}
|
805 |
-
|
806 |
-
|
807 |
-
/**
|
808 |
-
* Checks the status a product sync being executed in the background.
|
809 |
-
*/
|
810 |
-
function check_queues() {
|
811 |
-
ajax(
|
812 |
-
'ajax_fb_background_check_queue',
|
813 |
-
{
|
814 |
-
"request_time": new Date().getTime(),
|
815 |
-
"_ajax_nonce": wc_facebook_settings_jsx.nonce,
|
816 |
-
},
|
817 |
-
function( response ) {
|
818 |
-
if ( window.feed_upload ) {
|
819 |
-
clearInterval( window.fb_pings );
|
820 |
-
return;
|
821 |
-
}
|
822 |
-
|
823 |
-
const $sync_progress_element = jQuery( '#sync_progress' );
|
824 |
-
|
825 |
-
var res = parse_response_check_connection( response );
|
826 |
-
if ( !res ) {
|
827 |
-
if ( fb_sync_no_response_count++ > 5 ) {
|
828 |
-
clearInterval( window.fb_pings );
|
829 |
-
}
|
830 |
-
return;
|
831 |
-
}
|
832 |
-
fb_sync_no_response_count = 0;
|
833 |
-
|
834 |
-
if ( res ) {
|
835 |
-
if ( !res.background ) {
|
836 |
-
console.log( "No background sync found, disabling pings" );
|
837 |
-
clearInterval( window.fb_pings );
|
838 |
-
}
|
839 |
-
|
840 |
-
var processing = !!res.processing; // explicit boolean conversion
|
841 |
-
var remaining = res.remaining;
|
842 |
-
|
843 |
-
if ( processing ) {
|
844 |
-
|
845 |
-
let message = '';
|
846 |
-
|
847 |
-
if ( 1 === remaining ) {
|
848 |
-
message = facebook_for_woocommerce_settings_sync.i18n.sync_remaining_items_singular;
|
849 |
-
} else {
|
850 |
-
message = facebook_for_woocommerce_settings_sync.i18n.sync_remaining_items_plural;
|
851 |
-
}
|
852 |
-
|
853 |
-
$sync_progress_element.show().html( message.replace( '{count}', remaining ) );
|
854 |
-
|
855 |
-
if ( remaining === 0 ) {
|
856 |
-
product_sync_complete( $sync_progress_element );
|
857 |
-
}
|
858 |
-
|
859 |
-
} else {
|
860 |
-
// Not processing, none remaining. Either long complete, or just completed
|
861 |
-
if ( window.fb_sync_start_time && res.request_time ) {
|
862 |
-
var request_time = new Date( parseInt( res.request_time ) );
|
863 |
-
if ( window.fb_sync_start_time > request_time ) {
|
864 |
-
// Old ping, do nothing.
|
865 |
-
console.log( "OLD PING" );
|
866 |
-
return;
|
867 |
-
}
|
868 |
-
}
|
869 |
-
|
870 |
-
if ( remaining === 0 ) {
|
871 |
-
product_sync_complete( $sync_progress_element );
|
872 |
-
}
|
873 |
-
}
|
874 |
-
}
|
875 |
-
}
|
876 |
-
);
|
877 |
-
}
|
878 |
-
|
879 |
-
function parse_response_check_connection(res) {
|
880 |
-
if (res) {
|
881 |
-
console.log( res );
|
882 |
-
var response = res.substring( res.indexOf( "{" ) ); // Trim leading extra chars (rnrnr)
|
883 |
-
response = JSON.parse( response );
|
884 |
-
if ( ! response.connected && ! window.fb_connected) {
|
885 |
-
not_connected();
|
886 |
-
return null;
|
887 |
-
}
|
888 |
-
return response;
|
889 |
-
}
|
890 |
-
return null;
|
891 |
-
}
|
892 |
-
|
893 |
-
function check_feed_upload_queue(check_num) {
|
894 |
-
ajax(
|
895 |
-
'ajax_check_feed_upload_status',
|
896 |
-
{
|
897 |
-
"_ajax_nonce": wc_facebook_settings_jsx.nonce,
|
898 |
-
},
|
899 |
-
function(response) {
|
900 |
-
const $sync_progress_element = jQuery( '#sync_progress' );
|
901 |
-
|
902 |
-
var res = parse_response_check_connection( response );
|
903 |
-
|
904 |
-
clearInterval( window.fb_feed_pings );
|
905 |
-
|
906 |
-
if (res) {
|
907 |
-
var status = res.status;
|
908 |
-
switch (status) {
|
909 |
-
case 'complete':
|
910 |
-
window.feed_upload = false;
|
911 |
-
if (window.is_test) {
|
912 |
-
display_test_result();
|
913 |
-
} else {
|
914 |
-
product_sync_complete( $sync_progress_element );
|
915 |
-
}
|
916 |
-
break;
|
917 |
-
case 'in progress':
|
918 |
-
|
919 |
-
$sync_progress_element.show().html( facebook_for_woocommerce_settings_sync.i18n.sync_in_progress );
|
920 |
-
|
921 |
-
ping_feed_status_queue( check_num + 1 );
|
922 |
-
break;
|
923 |
-
|
924 |
-
default:
|
925 |
-
|
926 |
-
// enable Manage connection and Sync products buttons when sync stops
|
927 |
-
jQuery( '#woocommerce-facebook-settings-manage-connection, #woocommerce-facebook-settings-sync-products' ).css( 'pointer-events', 'auto' );
|
928 |
-
|
929 |
-
jQuery( '#sync_progress' ).show().html( '<span style="color: #DC3232">' + facebook_for_woocommerce_settings_sync.i18n.feed_upload_error + '</span>' );
|
930 |
-
|
931 |
-
window.feed_upload = false;
|
932 |
-
if (window.is_test) {
|
933 |
-
display_test_result();
|
934 |
-
}
|
935 |
-
}
|
936 |
-
}
|
937 |
-
}
|
938 |
-
);
|
939 |
-
}
|
940 |
-
|
941 |
-
function display_test_result() {
|
942 |
-
ajax(
|
943 |
-
'ajax_display_test_result',
|
944 |
-
{
|
945 |
-
"_ajax_nonce": wc_facebook_settings_jsx.nonce
|
946 |
-
},
|
947 |
-
function(response) {
|
948 |
-
const $sync_progress_element = jQuery( '#sync_progress' );
|
949 |
-
|
950 |
-
var sync_complete_element = document.querySelector( '#sync_complete' );
|
951 |
-
var res = parse_response_check_connection( response );
|
952 |
-
if (res) {
|
953 |
-
var status = res.pass;
|
954 |
-
switch (status) {
|
955 |
-
case 'true':
|
956 |
-
sync_not_in_progress();
|
957 |
-
if (sync_complete_element) {
|
958 |
-
sync_complete_element.style.display = '';
|
959 |
-
sync_complete_element.innerHTML = facebook_for_woocommerce_settings_sync.i18n.integration_test_sucessful;
|
960 |
-
}
|
961 |
-
|
962 |
-
$sync_progress_element.empty().hide();
|
963 |
-
|
964 |
-
window.is_test = false;
|
965 |
-
break;
|
966 |
-
case 'in progress':
|
967 |
-
|
968 |
-
$sync_progress_element.show().html( facebook_for_woocommerce_settings_sync.i18n.integration_test_in_progress );
|
969 |
-
|
970 |
-
ping_feed_status_queue();
|
971 |
-
break;
|
972 |
-
default:
|
973 |
-
window.debug_info = res.debug_info + '<br/>' + res.stack_trace;
|
974 |
-
if (sync_complete_element) {
|
975 |
-
sync_complete_element.style.display = '';
|
976 |
-
sync_complete_element.innerHTML = facebook_for_woocommerce_settings_sync.i18n.integration_test_failed;
|
977 |
-
}
|
978 |
-
|
979 |
-
$sync_progress_element.empty().hide();
|
980 |
-
|
981 |
-
if (document.querySelector( '#debug_info' )) {
|
982 |
-
document.querySelector( '#debug_info' ).style.display = '';
|
983 |
-
}
|
984 |
-
window.is_test = false;
|
985 |
-
}
|
986 |
-
}
|
987 |
-
}
|
988 |
-
);
|
989 |
-
}
|
990 |
-
|
991 |
-
function show_debug_info() {
|
992 |
-
var stack_trace_element = document.querySelector( '#stack_trace' );
|
993 |
-
if (stack_trace_element) {
|
994 |
-
stack_trace_element.innerHTML = window.debug_info;
|
995 |
-
}
|
996 |
-
if (document.querySelector( '#debug_info' )) {
|
997 |
-
document.querySelector( '#debug_info' ).style.display = 'none';
|
998 |
-
}
|
999 |
-
window.debug_info = '';
|
1000 |
-
}
|
1001 |
-
|
1002 |
-
function fbe_init_nux_messages() {
|
1003 |
-
var jQuery = window.jQuery;
|
1004 |
-
jQuery(
|
1005 |
-
function() {
|
1006 |
-
jQuery.each(
|
1007 |
-
jQuery( '.nux-message' ),
|
1008 |
-
function(_index, nux_msg) {
|
1009 |
-
var nux_msg_elem = jQuery( nux_msg );
|
1010 |
-
var targetid = nux_msg_elem.data( 'target' );
|
1011 |
-
var target_elem = jQuery( '#' + targetid );
|
1012 |
-
var t_pos = target_elem.position();
|
1013 |
-
var t_half_height = target_elem.height() / 2;
|
1014 |
-
var t_width = target_elem.outerWidth();
|
1015 |
-
nux_msg_elem.css(
|
1016 |
-
{
|
1017 |
-
'top': '' + Math.ceil( t_pos.top + t_half_height ) + 'px',
|
1018 |
-
'left': '' + Math.ceil( t_pos.left + t_width ) + 'px',
|
1019 |
-
'display': 'block'
|
1020 |
-
}
|
1021 |
-
);
|
1022 |
-
jQuery( '.nux-message-close-btn', nux_msg_elem ).click(
|
1023 |
-
function() {
|
1024 |
-
jQuery( nux_msg ).hide();
|
1025 |
-
}
|
1026 |
-
);
|
1027 |
-
}
|
1028 |
-
);
|
1029 |
-
}
|
1030 |
-
);
|
1031 |
-
}
|
1032 |
-
|
1033 |
-
function saveAutoSyncSchedule() {
|
1034 |
-
var isChecked = document.getElementsByClassName( 'autosyncCheck' )[0].checked;
|
1035 |
-
var timebox = document.getElementsByClassName( 'autosyncTime' )[0];
|
1036 |
-
var button = document.getElementsByClassName( 'autosyncSaveButton' )[0];
|
1037 |
-
var saved = document.getElementsByClassName( 'autosyncSavedNotice' )[0];
|
1038 |
-
|
1039 |
-
if ( ! isChecked) {
|
1040 |
-
timebox.setAttribute( 'disabled', true );
|
1041 |
-
} else {
|
1042 |
-
timebox.removeAttribute( 'disabled' );
|
1043 |
-
saved.style.transition = '';
|
1044 |
-
saved.style.opacity = 1;
|
1045 |
-
// Fade out the small 'Saved' after 3 seconds.
|
1046 |
-
setTimeout(
|
1047 |
-
function() {
|
1048 |
-
saved.style.opacity = 0;
|
1049 |
-
saved.style.transition = 'opacity 5s';}
|
1050 |
-
,
|
1051 |
-
3000
|
1052 |
-
);
|
1053 |
-
}
|
1054 |
-
|
1055 |
-
ajax( 'ajax_schedule_force_resync',
|
1056 |
-
{
|
1057 |
-
"enabled": isChecked ? 1 : 0,
|
1058 |
-
"time" : timebox.value,
|
1059 |
-
"_ajax_nonce": wc_facebook_settings_jsx.nonce,
|
1060 |
-
}
|
1061 |
-
);
|
1062 |
-
}
|
1063 |
-
|
1064 |
-
|
1065 |
-
function syncShortDescription() {
|
1066 |
-
var isChecked = document.getElementsByClassName( 'syncShortDescription' )[0].checked;
|
1067 |
-
ajax(
|
1068 |
-
'ajax_update_fb_option',
|
1069 |
-
{
|
1070 |
-
"option": "fb_sync_short_description",
|
1071 |
-
"option_value": isChecked ? 1 : 0,
|
1072 |
-
"_ajax_nonce": wc_facebook_settings_jsx.nonce,
|
1073 |
-
},
|
1074 |
-
null,
|
1075 |
-
function syncShortDescriptionFailCallback(error) {
|
1076 |
-
document.getElementsByClassName( 'syncShortDescription' )[0].checked = ! isChecked;
|
1077 |
-
console.log( 'Failed to sync Short Description' );
|
1078 |
-
}
|
1079 |
-
);
|
1080 |
-
}
|
1081 |
-
|
1082 |
-
jQuery( document ).ready( function( $ ) {
|
1083 |
-
|
1084 |
-
// when a "manage connection" link is click from a notice
|
1085 |
-
$( '.notice .wc-facebook-manage-connection' ).click( function( event ) {
|
1086 |
-
|
1087 |
-
event.preventDefault();
|
1088 |
-
|
1089 |
-
facebookConfig();
|
1090 |
-
} );
|
1091 |
-
|
1092 |
-
$( '#woocommerce-facebook-settings-sync-products' ).click( function( event ) {
|
1093 |
-
|
1094 |
-
event.preventDefault();
|
1095 |
-
|
1096 |
-
sync_confirm();
|
1097 |
-
} );
|
1098 |
-
|
1099 |
-
} );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
changelog.txt
CHANGED
@@ -1,5 +1,14 @@
|
|
1 |
*** Facebook for WooCommerce Changelog ***
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
2020.06.04 - version 1.11.4
|
4 |
* Fix - Do not sync variations for draft variable products created by duplicating products
|
5 |
* Fix - Do not log an error when the product is null on add to cart redirect
|
1 |
*** Facebook for WooCommerce Changelog ***
|
2 |
|
3 |
+
2020.07.30 - version 2.0.0
|
4 |
+
* Tweak - Show Facebook options for virtual products and variations
|
5 |
+
* Tweak - Hide "Sync and show" option for virtual products and variations
|
6 |
+
* Tweak - On upgrade, automatically set sync-enabled and visible virtual products and virtual variations to Sync and hide
|
7 |
+
* Tweak - Allow to bulk enable sync for virtual products, but automatically set them to Sync and hide
|
8 |
+
* Fix - Use the plugin version instead of a timestamp as the version number for enqueued scripts and stylesheets
|
9 |
+
* Fix - Use the short description of the parent product for product variations that don't have a description or Facebook description
|
10 |
+
* Fix - Prevent an error when YITH Booking and Appointment for WooCommerce plugin is active
|
11 |
+
|
12 |
2020.06.04 - version 1.11.4
|
13 |
* Fix - Do not sync variations for draft variable products created by duplicating products
|
14 |
* Fix - Do not log an error when the product is null on add to cart redirect
|
class-wc-facebookcommerce.php
CHANGED
@@ -8,8 +8,9 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
|
|
11 |
use SkyVerge\WooCommerce\Facebook\Lifecycle;
|
12 |
-
use SkyVerge\WooCommerce\Facebook\Utilities\
|
13 |
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
14 |
|
15 |
if ( ! class_exists( 'WC_Facebookcommerce' ) ) :
|
@@ -20,7 +21,7 @@ if ( ! class_exists( 'WC_Facebookcommerce' ) ) :
|
|
20 |
|
21 |
|
22 |
/** @var string the plugin version */
|
23 |
-
const VERSION = '
|
24 |
|
25 |
/** @var string for backwards compatibility TODO: remove this in v2.0.0 {CW 2020-02-06} */
|
26 |
const PLUGIN_VERSION = self::VERSION;
|
@@ -31,27 +32,42 @@ if ( ! class_exists( 'WC_Facebookcommerce' ) ) :
|
|
31 |
/** @var string the integration ID */
|
32 |
const INTEGRATION_ID = 'facebookcommerce';
|
33 |
|
34 |
-
/** @var string the integration class name (including namespaces) */
|
35 |
-
const INTEGRATION_CLASS = '\\WC_Facebookcommerce_Integration';
|
36 |
-
|
37 |
|
38 |
/** @var \WC_Facebookcommerce singleton instance */
|
39 |
protected static $instance;
|
40 |
|
|
|
|
|
|
|
41 |
/** @var \WC_Facebookcommerce_Integration instance */
|
42 |
private $integration;
|
43 |
|
44 |
/** @var \SkyVerge\WooCommerce\Facebook\Admin admin handler instance */
|
45 |
private $admin;
|
46 |
|
|
|
|
|
|
|
47 |
/** @var \SkyVerge\WooCommerce\Facebook\AJAX Ajax handler instance */
|
48 |
private $ajax;
|
49 |
|
50 |
/** @var \SkyVerge\WooCommerce\Facebook\Products\Feed product feed handler */
|
51 |
private $product_feed;
|
52 |
|
53 |
-
/** @var
|
54 |
-
protected $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
|
56 |
|
57 |
/**
|
@@ -80,21 +96,28 @@ if ( ! class_exists( 'WC_Facebookcommerce' ) ) :
|
|
80 |
*/
|
81 |
public function init() {
|
82 |
|
83 |
-
|
84 |
|
85 |
-
|
86 |
-
define( 'WOOCOMMERCE_FACEBOOK_PLUGIN_SETTINGS_URL', admin_url( 'admin.php?page=wc-settings&tab=integration§ion=facebookcommerce' ) );
|
87 |
-
}
|
88 |
|
89 |
include_once 'facebook-commerce.php';
|
90 |
|
|
|
|
|
|
|
|
|
91 |
require_once __DIR__ . '/includes/Integrations/Integrations.php';
|
92 |
require_once __DIR__ . '/includes/Products.php';
|
93 |
require_once __DIR__ . '/includes/Products/Feed.php';
|
|
|
|
|
94 |
require_once __DIR__ . '/includes/fbproductfeed.php';
|
95 |
require_once __DIR__ . '/facebook-commerce-messenger-chat.php';
|
|
|
96 |
|
97 |
-
$this->product_feed
|
|
|
|
|
98 |
|
99 |
if ( is_ajax() ) {
|
100 |
|
@@ -103,18 +126,27 @@ if ( ! class_exists( 'WC_Facebookcommerce' ) ) :
|
|
103 |
$this->ajax = new \SkyVerge\WooCommerce\Facebook\AJAX();
|
104 |
}
|
105 |
|
106 |
-
// register the WooCommerce integration
|
107 |
-
add_filter( 'woocommerce_integrations', [ $this, 'add_woocommerce_integration' ] );
|
108 |
-
|
109 |
$this->integrations = new \SkyVerge\WooCommerce\Facebook\Integrations\Integrations( $this );
|
110 |
|
111 |
-
if ( 'yes' !== get_option( '
|
112 |
|
113 |
-
require_once __DIR__ . '/
|
114 |
-
require_once __DIR__ . '/vendor/skyverge/wc-plugin-framework/woocommerce/utilities/class-sv-wp-background-job-handler.php';
|
115 |
-
require_once __DIR__ . '/includes/Utilities/Background_Disable_Virtual_Products_Sync.php';
|
116 |
|
117 |
-
$this->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
}
|
119 |
}
|
120 |
}
|
@@ -144,70 +176,274 @@ if ( ! class_exists( 'WC_Facebookcommerce' ) ) :
|
|
144 |
|
145 |
parent::add_admin_notices();
|
146 |
|
147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
|
149 |
-
|
150 |
-
|
|
|
|
|
|
|
151 |
|
152 |
-
|
|
|
|
|
|
|
|
|
153 |
|
154 |
-
|
|
|
155 |
|
156 |
$message = sprintf(
|
157 |
-
/* translators: Placeholders
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
|
|
|
|
|
|
|
|
162 |
);
|
163 |
|
164 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
165 |
|
166 |
$message = sprintf(
|
167 |
-
|
168 |
-
__( '%1$sHeads up!%2$s
|
169 |
'<strong>', '</strong>',
|
170 |
-
'<a href="' . esc_url( $this->
|
171 |
-
'<a href="' . esc_url( $docs_url ) . '" target="_blank">', '</a>'
|
172 |
);
|
|
|
|
|
|
|
|
|
|
|
173 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
|
175 |
-
$this->get_admin_notice_handler()->add_admin_notice( $message,
|
176 |
-
'
|
177 |
-
'notice_class' => 'notice-info wc-facebook-migrate-notice',
|
178 |
] );
|
179 |
}
|
180 |
}
|
181 |
|
182 |
|
|
|
|
|
|
|
|
|
|
|
183 |
/**
|
184 |
-
*
|
185 |
*
|
186 |
-
* @
|
187 |
*
|
188 |
-
* @
|
189 |
-
*
|
190 |
-
* @param
|
191 |
-
* @return string[]
|
192 |
*/
|
193 |
-
public function
|
194 |
|
195 |
-
|
196 |
-
|
|
|
197 |
}
|
198 |
|
199 |
-
$
|
200 |
-
|
201 |
-
return $integrations;
|
202 |
}
|
203 |
|
204 |
|
205 |
-
|
206 |
-
new WP_Facebook_Integration();
|
207 |
-
}
|
208 |
|
209 |
|
210 |
-
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
211 |
|
212 |
|
213 |
/**
|
@@ -250,40 +486,68 @@ if ( ! class_exists( 'WC_Facebookcommerce' ) ) :
|
|
250 |
|
251 |
|
252 |
/**
|
253 |
-
* Gets the background
|
|
|
|
|
254 |
*
|
255 |
-
* @
|
256 |
*/
|
257 |
-
public function
|
258 |
|
259 |
-
return $this->
|
260 |
}
|
261 |
|
262 |
|
263 |
/**
|
264 |
-
* Gets the
|
265 |
*
|
266 |
-
* @since
|
267 |
*
|
268 |
-
* @return \
|
269 |
*/
|
270 |
-
public function
|
271 |
|
272 |
-
|
|
|
273 |
|
274 |
-
$integrations = null === WC()->integrations ? [] : WC()->integrations->get_integrations();
|
275 |
-
$integration = self::INTEGRATION_CLASS;
|
276 |
|
277 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
|
279 |
-
|
|
|
280 |
|
281 |
-
} else {
|
282 |
|
283 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
284 |
|
285 |
-
|
286 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
287 |
}
|
288 |
|
289 |
return $this->integration;
|
@@ -300,7 +564,7 @@ if ( ! class_exists( 'WC_Facebookcommerce' ) ) :
|
|
300 |
*/
|
301 |
public function get_settings_url( $plugin_id = null ) {
|
302 |
|
303 |
-
return admin_url( 'admin.php?page=wc-
|
304 |
}
|
305 |
|
306 |
|
@@ -381,11 +645,7 @@ if ( ! class_exists( 'WC_Facebookcommerce' ) ) :
|
|
381 |
*/
|
382 |
public function is_plugin_settings() {
|
383 |
|
384 |
-
|
385 |
-
$tab = Framework\SV_WC_Helper::get_requested_value( 'tab' );
|
386 |
-
$section = Framework\SV_WC_Helper::get_requested_value( 'section' );
|
387 |
-
|
388 |
-
return is_admin() && 'wc-settings' === $page && 'integration' === $tab && self::INTEGRATION_ID === $section;
|
389 |
}
|
390 |
|
391 |
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
use SkyVerge\WooCommerce\Facebook\API;
|
12 |
use SkyVerge\WooCommerce\Facebook\Lifecycle;
|
13 |
+
use SkyVerge\WooCommerce\Facebook\Utilities\Background_Handle_Virtual_Products_Variations;
|
14 |
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
15 |
|
16 |
if ( ! class_exists( 'WC_Facebookcommerce' ) ) :
|
21 |
|
22 |
|
23 |
/** @var string the plugin version */
|
24 |
+
const VERSION = '2.0.0';
|
25 |
|
26 |
/** @var string for backwards compatibility TODO: remove this in v2.0.0 {CW 2020-02-06} */
|
27 |
const PLUGIN_VERSION = self::VERSION;
|
32 |
/** @var string the integration ID */
|
33 |
const INTEGRATION_ID = 'facebookcommerce';
|
34 |
|
|
|
|
|
|
|
35 |
|
36 |
/** @var \WC_Facebookcommerce singleton instance */
|
37 |
protected static $instance;
|
38 |
|
39 |
+
/** @var SkyVerge\WooCommerce\Facebook\API instance */
|
40 |
+
private $api;
|
41 |
+
|
42 |
/** @var \WC_Facebookcommerce_Integration instance */
|
43 |
private $integration;
|
44 |
|
45 |
/** @var \SkyVerge\WooCommerce\Facebook\Admin admin handler instance */
|
46 |
private $admin;
|
47 |
|
48 |
+
/** @var \SkyVerge\WooCommerce\Facebook\Admin\Settings */
|
49 |
+
private $admin_settings;
|
50 |
+
|
51 |
/** @var \SkyVerge\WooCommerce\Facebook\AJAX Ajax handler instance */
|
52 |
private $ajax;
|
53 |
|
54 |
/** @var \SkyVerge\WooCommerce\Facebook\Products\Feed product feed handler */
|
55 |
private $product_feed;
|
56 |
|
57 |
+
/** @var Background_Handle_Virtual_Products_Variations instance */
|
58 |
+
protected $background_handle_virtual_products_variations;
|
59 |
+
|
60 |
+
/** @var \SkyVerge\WooCommerce\Facebook\Products\Sync products sync handler */
|
61 |
+
private $products_sync_handler;
|
62 |
+
|
63 |
+
/** @var \SkyVerge\WooCommerce\Facebook\Products\Sync\Background background sync handler */
|
64 |
+
private $sync_background_handler;
|
65 |
+
|
66 |
+
/** @var \SkyVerge\WooCommerce\Facebook\Handlers\Connection connection handler */
|
67 |
+
private $connection_handler;
|
68 |
+
|
69 |
+
/** @var \SkyVerge\WooCommerce\Facebook\Integrations\Integrations integrations handler */
|
70 |
+
private $integrations;
|
71 |
|
72 |
|
73 |
/**
|
96 |
*/
|
97 |
public function init() {
|
98 |
|
99 |
+
add_action( 'init', [ $this, 'get_integration' ] );
|
100 |
|
101 |
+
if ( \WC_Facebookcommerce_Utils::isWoocommerceIntegration() ) {
|
|
|
|
|
102 |
|
103 |
include_once 'facebook-commerce.php';
|
104 |
|
105 |
+
require_once $this->get_framework_path() . '/utilities/class-sv-wp-async-request.php';
|
106 |
+
require_once $this->get_framework_path() . '/utilities/class-sv-wp-background-job-handler.php';
|
107 |
+
|
108 |
+
require_once __DIR__ . '/includes/Handlers/Connection.php';
|
109 |
require_once __DIR__ . '/includes/Integrations/Integrations.php';
|
110 |
require_once __DIR__ . '/includes/Products.php';
|
111 |
require_once __DIR__ . '/includes/Products/Feed.php';
|
112 |
+
require_once __DIR__ . '/includes/Products/Sync.php';
|
113 |
+
require_once __DIR__ . '/includes/Products/Sync/Background.php';
|
114 |
require_once __DIR__ . '/includes/fbproductfeed.php';
|
115 |
require_once __DIR__ . '/facebook-commerce-messenger-chat.php';
|
116 |
+
require_once __DIR__ . '/includes/Events/Event.php';
|
117 |
|
118 |
+
$this->product_feed = new \SkyVerge\WooCommerce\Facebook\Products\Feed();
|
119 |
+
$this->products_sync_handler = new \SkyVerge\WooCommerce\Facebook\Products\Sync();
|
120 |
+
$this->sync_background_handler = new \SkyVerge\WooCommerce\Facebook\Products\Sync\Background();
|
121 |
|
122 |
if ( is_ajax() ) {
|
123 |
|
126 |
$this->ajax = new \SkyVerge\WooCommerce\Facebook\AJAX();
|
127 |
}
|
128 |
|
|
|
|
|
|
|
129 |
$this->integrations = new \SkyVerge\WooCommerce\Facebook\Integrations\Integrations( $this );
|
130 |
|
131 |
+
if ( 'yes' !== get_option( 'wc_facebook_background_handle_virtual_products_variations_complete', 'no' ) ) {
|
132 |
|
133 |
+
require_once __DIR__ . '/includes/Utilities/Background_Handle_Virtual_Products_Variations.php';
|
|
|
|
|
134 |
|
135 |
+
$this->background_handle_virtual_products_variations = new Background_Handle_Virtual_Products_Variations();
|
136 |
+
}
|
137 |
+
|
138 |
+
$this->connection_handler = new \SkyVerge\WooCommerce\Facebook\Handlers\Connection( $this );
|
139 |
+
|
140 |
+
// load admin handlers, before admin_init
|
141 |
+
if ( is_admin() ) {
|
142 |
+
|
143 |
+
require_once __DIR__ . '/includes/Admin/Settings.php';
|
144 |
+
require_once __DIR__ . '/includes/Admin/Abstract_Settings_Screen.php';
|
145 |
+
require_once __DIR__ . '/includes/Admin/Settings_Screens/Connection.php';
|
146 |
+
require_once __DIR__ . '/includes/Admin/Settings_Screens/Product_Sync.php';
|
147 |
+
require_once __DIR__ . '/includes/Admin/Settings_Screens/Messenger.php';
|
148 |
+
|
149 |
+
$this->admin_settings = new \SkyVerge\WooCommerce\Facebook\Admin\Settings();
|
150 |
}
|
151 |
}
|
152 |
}
|
176 |
|
177 |
parent::add_admin_notices();
|
178 |
|
179 |
+
// inform users who are not connected to Facebook
|
180 |
+
if ( ! $this->get_connection_handler()->is_connected() ) {
|
181 |
+
|
182 |
+
// users who've never connected to FBE 2 but have previously connected to FBE 1
|
183 |
+
if ( ! $this->get_connection_handler()->has_previously_connected_fbe_2() && $this->get_connection_handler()->has_previously_connected_fbe_1() ) {
|
184 |
+
|
185 |
+
$message = sprintf(
|
186 |
+
/* translators: Placeholders %1$s - opening strong HTML tag, %2$s - closing strong HTML tag, %3$s - opening link HTML tag, %4$s - closing link HTML tag */
|
187 |
+
__( '%1$sHeads up!%2$s You\'re ready to migrate to a more secure, reliable Facebook for WooCommerce connection. Please %3$sclick here%4$s to reconnect!', 'facebook-for-woocommerce' ),
|
188 |
+
'<strong>', '</strong>',
|
189 |
+
'<a href="' . esc_url( $this->get_connection_handler()->get_connect_url() ) . '">', '</a>'
|
190 |
+
);
|
191 |
+
|
192 |
+
$this->get_admin_notice_handler()->add_admin_notice( $message, self::PLUGIN_ID . '_migrate_to_v2_0', [
|
193 |
+
'dismissible' => false,
|
194 |
+
'notice_class' => 'notice-info',
|
195 |
+
] );
|
196 |
+
|
197 |
+
// direct these users to the new plugin settings page
|
198 |
+
if ( ! $this->is_plugin_settings() ) {
|
199 |
|
200 |
+
$message = sprintf(
|
201 |
+
/* translators: Placeholders %1$s - opening link HTML tag, %2$s - closing link HTML tag */
|
202 |
+
__( 'For your convenience, the Facebook for WooCommerce settings are now located under %1$sWooCommerce > Facebook%2$s.', 'facebook-for-woocommerce' ),
|
203 |
+
'<a href="' . esc_url( facebook_for_woocommerce()->get_settings_url() ) . '">', '</a>'
|
204 |
+
);
|
205 |
|
206 |
+
$this->get_admin_notice_handler()->add_admin_notice( $message, self::PLUGIN_ID . '_relocated_settings', [
|
207 |
+
'dismissible' => true,
|
208 |
+
'notice_class' => 'notice-info',
|
209 |
+
] );
|
210 |
+
}
|
211 |
|
212 |
+
// otherwise, a general getting started message
|
213 |
+
} elseif ( ! $this->is_plugin_settings() ) {
|
214 |
|
215 |
$message = sprintf(
|
216 |
+
/* translators: Placeholders %1$s - opening strong HTML tag, %2$s - closing strong HTML tag, %3$s - opening link HTML tag, %4$s - closing link HTML tag */
|
217 |
+
esc_html__(
|
218 |
+
'%1$sFacebook for WooCommerce is almost ready.%2$s To complete your configuration, %3$scomplete the setup steps%4$s.',
|
219 |
+
'facebook-for-woocommerce'
|
220 |
+
),
|
221 |
+
'<strong>',
|
222 |
+
'</strong>',
|
223 |
+
'<a href="' . esc_url( facebook_for_woocommerce()->get_settings_url() ) . '">',
|
224 |
+
'</a>'
|
225 |
);
|
226 |
|
227 |
+
$this->get_admin_notice_handler()->add_admin_notice( $message, self::PLUGIN_ID . '_get_started', [
|
228 |
+
'dismissible' => true,
|
229 |
+
'notice_class' => 'notice-info',
|
230 |
+
] );
|
231 |
+
}
|
232 |
+
|
233 |
+
// notices for those connected to FBE 2
|
234 |
+
} else {
|
235 |
+
|
236 |
+
// if upgraders had messenger enabled and one of the removed settings was customized, alert them to reconfigure
|
237 |
+
if (
|
238 |
+
$this->get_integration()->get_external_merchant_settings_id()
|
239 |
+
&& $this->get_integration()->is_messenger_enabled()
|
240 |
+
&& ( '#0084ff' !== $this->get_integration()->get_messenger_color_hex() || ! in_array( $this->get_integration()->get_messenger_greeting(), [ 'Hi! How can we help you?', "Hi! We're here to answer any questions you may have.", '' ], true ) )
|
241 |
+
) {
|
242 |
|
243 |
$message = sprintf(
|
244 |
+
/* translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s - <a> tag, %4$s - </a> tag */
|
245 |
+
__( '%1$sHeads up!%2$s If you\'ve customized your Facebook Messenger color or greeting settings, please update those settings again from the %3$sManage Connection%4$s area.', 'facebook-for-woocommerce' ),
|
246 |
'<strong>', '</strong>',
|
247 |
+
'<a href="' . esc_url( $this->get_connection_handler()->get_manage_url() ) . '" target="_blank">', '</a>'
|
|
|
248 |
);
|
249 |
+
|
250 |
+
$this->get_admin_notice_handler()->add_admin_notice( $message, 'update_messenger', [
|
251 |
+
'always_show_on_settings' => false,
|
252 |
+
'notice_class' => 'notice-info',
|
253 |
+
] );
|
254 |
}
|
255 |
+
}
|
256 |
+
|
257 |
+
// if the connection is otherwise invalid, but there is an access token
|
258 |
+
if ( get_transient( 'wc_facebook_connection_invalid' ) && $this->get_connection_handler()->is_connected() ) {
|
259 |
+
|
260 |
+
$message = sprintf(
|
261 |
+
/* translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s - <a> tag, %4$s - </a> tag */
|
262 |
+
__( '%1$sHeads up!%2$s Your connection to Facebook is no longer valid. Please %3$sclick here%4$s to securely reconnect your account and continue syncing products.', 'facebook-for-woocommerce' ),
|
263 |
+
'<strong>', '</strong>',
|
264 |
+
'<a href="' . esc_url( $this->get_connection_handler()->get_connect_url() ) . '">', '</a>'
|
265 |
+
);
|
266 |
|
267 |
+
$this->get_admin_notice_handler()->add_admin_notice( $message, 'connection_invalid', [
|
268 |
+
'notice_class' => 'notice-error',
|
|
|
269 |
] );
|
270 |
}
|
271 |
}
|
272 |
|
273 |
|
274 |
+
public function add_wordpress_integration() {
|
275 |
+
new WP_Facebook_Integration();
|
276 |
+
}
|
277 |
+
|
278 |
+
|
279 |
/**
|
280 |
+
* Logs an API request.
|
281 |
*
|
282 |
+
* @since 2.0.0
|
283 |
*
|
284 |
+
* @param array $request request data
|
285 |
+
* @param array $response response data
|
286 |
+
* @param null $log_id log ID
|
|
|
287 |
*/
|
288 |
+
public function log_api_request( $request, $response, $log_id = null ) {
|
289 |
|
290 |
+
// bail if logging isn't enabled
|
291 |
+
if ( ! $this->get_integration() || ! $this->get_integration()->is_debug_mode_enabled() ) {
|
292 |
+
return;
|
293 |
}
|
294 |
|
295 |
+
parent::log_api_request( $request, $response, $log_id );
|
|
|
|
|
296 |
}
|
297 |
|
298 |
|
299 |
+
/** Getter methods ********************************************************************************************/
|
|
|
|
|
300 |
|
301 |
|
302 |
+
/**
|
303 |
+
* Gets the API instance.
|
304 |
+
*
|
305 |
+
* @since 2.0.0
|
306 |
+
*
|
307 |
+
* @return \SkyVerge\WooCommerce\Facebook\API
|
308 |
+
* @throws Framework\SV_WC_API_Exception
|
309 |
+
*/
|
310 |
+
public function get_api() {
|
311 |
+
|
312 |
+
if ( ! is_object( $this->api ) ) {
|
313 |
+
|
314 |
+
if ( ! $this->get_connection_handler()->get_access_token() ) {
|
315 |
+
throw new Framework\SV_WC_API_Exception( __( 'Cannot create the API instance because the access token is missing.', 'facebook-for-woocommerce' ) );
|
316 |
+
}
|
317 |
+
|
318 |
+
if ( ! class_exists( API\Traits\Rate_Limited_API::class ) ) {
|
319 |
+
require_once __DIR__ . '/includes/API/Traits/Rate_Limited_API.php';
|
320 |
+
}
|
321 |
+
|
322 |
+
if ( ! class_exists( API\Traits\Rate_Limited_Request::class ) ) {
|
323 |
+
require_once __DIR__ . '/includes/API/Traits/Rate_Limited_Request.php';
|
324 |
+
}
|
325 |
+
|
326 |
+
if ( ! class_exists( API\Traits\Rate_Limited_Response::class ) ) {
|
327 |
+
require_once __DIR__ . '/includes/API/Traits/Rate_Limited_Response.php';
|
328 |
+
}
|
329 |
+
|
330 |
+
if ( ! trait_exists( API\Traits\Paginated_Response::class, false ) ) {
|
331 |
+
require_once __DIR__ . '/includes/API/Traits/Paginated_Response.php';
|
332 |
+
}
|
333 |
+
|
334 |
+
if ( ! class_exists( API::class ) ) {
|
335 |
+
require_once __DIR__ . '/includes/API.php';
|
336 |
+
}
|
337 |
+
|
338 |
+
if ( ! class_exists( API\Request::class ) ) {
|
339 |
+
require_once __DIR__ . '/includes/API/Request.php';
|
340 |
+
}
|
341 |
+
|
342 |
+
if ( ! class_exists( API\Response::class ) ) {
|
343 |
+
require_once __DIR__ . '/includes/API/Response.php';
|
344 |
+
}
|
345 |
+
|
346 |
+
if ( ! class_exists( API\Pixel\Events\Request::class ) ) {
|
347 |
+
require_once __DIR__ . '/includes/API/Pixel/Events/Request.php';
|
348 |
+
}
|
349 |
+
|
350 |
+
if ( ! class_exists( API\Business_Manager\Request::class ) ) {
|
351 |
+
require_once __DIR__ . '/includes/API/Business_Manager/Request.php';
|
352 |
+
}
|
353 |
+
|
354 |
+
if ( ! class_exists( API\Business_Manager\Response::class ) ) {
|
355 |
+
require_once __DIR__ . '/includes/API/Business_Manager/Response.php';
|
356 |
+
}
|
357 |
+
|
358 |
+
if ( ! class_exists( API\Catalog\Request::class ) ) {
|
359 |
+
require_once __DIR__ . '/includes/API/Catalog/Request.php';
|
360 |
+
}
|
361 |
+
|
362 |
+
if ( ! class_exists( API\Catalog\Response::class ) ) {
|
363 |
+
require_once __DIR__ . '/includes/API/Catalog/Response.php';
|
364 |
+
}
|
365 |
+
|
366 |
+
if ( ! class_exists( API\Catalog\Send_Item_Updates\Request::class ) ) {
|
367 |
+
require_once __DIR__ . '/includes/API/Catalog/Send_Item_Updates/Request.php';
|
368 |
+
}
|
369 |
+
|
370 |
+
if ( ! class_exists( API\Catalog\Send_Item_Updates\Response::class ) ) {
|
371 |
+
require_once __DIR__ . '/includes/API/Catalog/Send_Item_Updates/Response.php';
|
372 |
+
}
|
373 |
+
|
374 |
+
if ( ! class_exists( API\Catalog\Product_Group\Products\Read\Request::class ) ) {
|
375 |
+
require_once __DIR__ . '/includes/API/Catalog/Product_Group/Products/Read/Request.php';
|
376 |
+
}
|
377 |
+
|
378 |
+
if ( ! class_exists( API\Catalog\Product_Group\Products\Read\Response::class ) ) {
|
379 |
+
require_once __DIR__ . '/includes/API/Catalog/Product_Group/Products/Read/Response.php';
|
380 |
+
}
|
381 |
+
|
382 |
+
if ( ! class_exists( API\Catalog\Product_Item\Response::class ) ) {
|
383 |
+
require_once __DIR__ . '/includes/API/Catalog/Product_Item/Response.php';
|
384 |
+
}
|
385 |
+
|
386 |
+
if ( ! class_exists( API\Catalog\Product_Item\Find\Request::class ) ) {
|
387 |
+
require_once __DIR__ . '/includes/API/Catalog/Product_Item/Find/Request.php';
|
388 |
+
}
|
389 |
+
|
390 |
+
if ( ! class_exists( API\User\Request::class ) ) {
|
391 |
+
require_once __DIR__ . '/includes/API/User/Request.php';
|
392 |
+
}
|
393 |
+
|
394 |
+
if ( ! class_exists( API\User\Response::class ) ) {
|
395 |
+
require_once __DIR__ . '/includes/API/User/Response.php';
|
396 |
+
}
|
397 |
+
|
398 |
+
if ( ! class_exists( API\User\Permissions\Delete\Request::class ) ) {
|
399 |
+
require_once __DIR__ . '/includes/API/User/Permissions/Delete/Request.php';
|
400 |
+
}
|
401 |
+
|
402 |
+
if ( ! class_exists( API\FBE\Installation\Request::class ) ) {
|
403 |
+
require_once __DIR__ . '/includes/API/FBE/Installation/Request.php';
|
404 |
+
}
|
405 |
+
|
406 |
+
if ( ! class_exists( API\FBE\Installation\Read\Request::class ) ) {
|
407 |
+
require_once __DIR__ . '/includes/API/FBE/Installation/Read/Request.php';
|
408 |
+
}
|
409 |
+
|
410 |
+
if ( ! class_exists( API\FBE\Installation\Read\Response::class ) ) {
|
411 |
+
require_once __DIR__ . '/includes/API/FBE/Installation/Read/Response.php';
|
412 |
+
}
|
413 |
+
|
414 |
+
if ( ! class_exists( API\FBE\Configuration\Request::class ) ) {
|
415 |
+
require_once __DIR__ . '/includes/API/FBE/Configuration/Request.php';
|
416 |
+
}
|
417 |
+
|
418 |
+
if ( ! class_exists( API\FBE\Configuration\Messenger::class ) ) {
|
419 |
+
require_once __DIR__ . '/includes/API/FBE/Configuration/Messenger.php';
|
420 |
+
}
|
421 |
+
|
422 |
+
if ( ! class_exists( API\FBE\Configuration\Read\Response::class ) ) {
|
423 |
+
require_once __DIR__ . '/includes/API/FBE/Configuration/Read/Response.php';
|
424 |
+
}
|
425 |
+
|
426 |
+
if ( ! class_exists( API\FBE\Configuration\Update\Request::class ) ) {
|
427 |
+
require_once __DIR__ . '/includes/API/FBE/Configuration/Update/Request.php';
|
428 |
+
}
|
429 |
+
|
430 |
+
if ( ! class_exists( API\Pages\Read\Request::class ) ) {
|
431 |
+
require_once __DIR__ . '/includes/API/Pages/Read/Request.php';
|
432 |
+
}
|
433 |
+
|
434 |
+
if ( ! class_exists( API\Pages\Read\Response::class ) ) {
|
435 |
+
require_once __DIR__ . '/includes/API/Pages/Read/Response.php';
|
436 |
+
}
|
437 |
+
|
438 |
+
if ( ! class_exists( API\Exceptions\Request_Limit_Reached::class ) ) {
|
439 |
+
require_once __DIR__ . '/includes/API/Exceptions/Request_Limit_Reached.php';
|
440 |
+
}
|
441 |
+
|
442 |
+
$this->api = new SkyVerge\WooCommerce\Facebook\API( $this->get_connection_handler()->get_access_token() );
|
443 |
+
}
|
444 |
+
|
445 |
+
return $this->api;
|
446 |
+
}
|
447 |
|
448 |
|
449 |
/**
|
486 |
|
487 |
|
488 |
/**
|
489 |
+
* Gets the background handle virtual products and variations handler instance.
|
490 |
+
*
|
491 |
+
* @since 2.0.0
|
492 |
*
|
493 |
+
* @return Background_Handle_Virtual_Products_Variations
|
494 |
*/
|
495 |
+
public function get_background_handle_virtual_products_variations_instance() {
|
496 |
|
497 |
+
return $this->background_handle_virtual_products_variations;
|
498 |
}
|
499 |
|
500 |
|
501 |
/**
|
502 |
+
* Gets the products sync handler.
|
503 |
*
|
504 |
+
* @since 2.0.0
|
505 |
*
|
506 |
+
* @return \SkyVerge\WooCommerce\Facebook\Products\Sync
|
507 |
*/
|
508 |
+
public function get_products_sync_handler() {
|
509 |
|
510 |
+
return $this->products_sync_handler;
|
511 |
+
}
|
512 |
|
|
|
|
|
513 |
|
514 |
+
/**
|
515 |
+
* Gets the products sync background handler.
|
516 |
+
*
|
517 |
+
* @since 2.0.0
|
518 |
+
*
|
519 |
+
* @return \SkyVerge\WooCommerce\Facebook\Products\Sync\Background
|
520 |
+
*/
|
521 |
+
public function get_products_sync_background_handler() {
|
522 |
|
523 |
+
return $this->sync_background_handler;
|
524 |
+
}
|
525 |
|
|
|
526 |
|
527 |
+
/**
|
528 |
+
* Gets the connection handler.
|
529 |
+
*
|
530 |
+
* @since 2.0.0
|
531 |
+
*
|
532 |
+
* @return \SkyVerge\WooCommerce\Facebook\Handlers\Connection
|
533 |
+
*/
|
534 |
+
public function get_connection_handler() {
|
535 |
|
536 |
+
return $this->connection_handler;
|
537 |
+
}
|
538 |
+
|
539 |
+
|
540 |
+
/**
|
541 |
+
* Gets the integration instance.
|
542 |
+
*
|
543 |
+
* @since 1.10.0
|
544 |
+
*
|
545 |
+
* @return \WC_Facebookcommerce_Integration instance
|
546 |
+
*/
|
547 |
+
public function get_integration() {
|
548 |
+
|
549 |
+
if ( null === $this->integration ) {
|
550 |
+
$this->integration = new WC_Facebookcommerce_Integration();
|
551 |
}
|
552 |
|
553 |
return $this->integration;
|
564 |
*/
|
565 |
public function get_settings_url( $plugin_id = null ) {
|
566 |
|
567 |
+
return admin_url( 'admin.php?page=wc-facebook' );
|
568 |
}
|
569 |
|
570 |
|
645 |
*/
|
646 |
public function is_plugin_settings() {
|
647 |
|
648 |
+
return is_admin() && \SkyVerge\WooCommerce\Facebook\Admin\Settings::PAGE_ID === Framework\SV_WC_Helper::get_requested_value( 'page' );
|
|
|
|
|
|
|
|
|
649 |
}
|
650 |
|
651 |
|
facebook-commerce-events-tracker.php
CHANGED
@@ -8,6 +8,9 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
|
|
|
|
|
|
11 |
if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
12 |
|
13 |
if ( ! class_exists( 'WC_Facebookcommerce_Utils' ) ) {
|
@@ -24,6 +27,10 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
24 |
const FB_PRIORITY_HIGH = 2;
|
25 |
const FB_PRIORITY_LOW = 11;
|
26 |
|
|
|
|
|
|
|
|
|
27 |
public function __construct( $user_info ) {
|
28 |
$this->pixel = new WC_Facebookcommerce_Pixel( $user_info );
|
29 |
|
@@ -111,7 +118,8 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
111 |
*/
|
112 |
public function inject_view_category_event() {
|
113 |
global $wp_query;
|
114 |
-
|
|
|
115 |
return;
|
116 |
}
|
117 |
|
@@ -127,11 +135,20 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
127 |
// if any product is a variant, fire the pixel with
|
128 |
// content_type: product_group
|
129 |
$content_type = 'product';
|
130 |
-
$product_ids =
|
|
|
|
|
131 |
foreach ( $products as $product ) {
|
|
|
132 |
if ( ! $product ) {
|
133 |
continue;
|
134 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
135 |
$product_ids = array_merge(
|
136 |
$product_ids,
|
137 |
WC_Facebookcommerce_Utils::get_fb_content_ids( $product )
|
@@ -141,56 +158,141 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
141 |
}
|
142 |
}
|
143 |
|
144 |
-
$categories =
|
145 |
-
WC_Facebookcommerce_Utils::get_product_categories( get_the_ID() );
|
146 |
|
147 |
-
$
|
148 |
-
|
149 |
-
|
|
|
150 |
'content_name' => $categories['name'],
|
151 |
'content_category' => $categories['categories'],
|
152 |
'content_ids' => json_encode( array_slice( $product_ids, 0, 10 ) ),
|
153 |
'content_type' => $content_type,
|
154 |
-
|
155 |
-
|
156 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
}
|
158 |
|
159 |
/**
|
160 |
* Triggers Search for result pages (deduped)
|
|
|
|
|
161 |
*/
|
162 |
public function inject_search_event() {
|
|
|
163 |
if ( ! self::$isEnabled ) {
|
164 |
return;
|
165 |
}
|
166 |
|
167 |
-
if ( ! is_admin() && is_search() && get_search_query()
|
|
|
168 |
if ( $this->pixel->is_last_event( 'Search' ) ) {
|
169 |
return;
|
170 |
}
|
171 |
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
176 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
177 |
}
|
|
|
|
|
178 |
}
|
179 |
|
|
|
180 |
/**
|
181 |
-
*
|
|
|
|
|
182 |
*/
|
183 |
public function actually_inject_search_event() {
|
184 |
-
if ( ! self::$isEnabled ) {
|
185 |
-
return;
|
186 |
-
}
|
187 |
|
188 |
-
$this->
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
)
|
193 |
-
|
|
|
194 |
}
|
195 |
|
196 |
|
@@ -219,13 +321,33 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
219 |
$content_type = 'product';
|
220 |
}
|
221 |
|
222 |
-
$
|
223 |
-
|
224 |
-
|
225 |
-
'
|
226 |
-
'
|
227 |
-
|
228 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
229 |
}
|
230 |
|
231 |
|
@@ -253,13 +375,29 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
253 |
return;
|
254 |
}
|
255 |
|
256 |
-
$
|
257 |
-
'
|
258 |
-
'
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
263 |
}
|
264 |
|
265 |
|
@@ -294,13 +432,22 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
294 |
|
295 |
if ( self::$isEnabled ) {
|
296 |
|
297 |
-
$
|
298 |
'content_ids' => $this->get_cart_content_ids(),
|
|
|
299 |
'content_type' => 'product',
|
300 |
'contents' => $this->get_cart_contents(),
|
301 |
'value' => $this->get_cart_total(),
|
302 |
'currency' => get_woocommerce_currency(),
|
303 |
-
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
304 |
|
305 |
$fragments['div.wc-facebook-pixel-event-placeholder'] = '<div class="wc-facebook-pixel-event-placeholder">' . $script . '</div>';
|
306 |
}
|
@@ -344,12 +491,19 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
344 |
|
345 |
$params = [
|
346 |
'content_ids' => $this->get_cart_content_ids(),
|
|
|
347 |
'content_type' => 'product',
|
348 |
'contents' => $this->get_cart_contents(),
|
349 |
'value' => $this->get_cart_total(),
|
350 |
'currency' => get_woocommerce_currency(),
|
351 |
];
|
352 |
|
|
|
|
|
|
|
|
|
|
|
|
|
353 |
$script = $this->pixel->get_conditional_one_time_event_script( 'AddToCart', $params, 'added_to_cart' );
|
354 |
|
355 |
$fragments['div.wc-facebook-pixel-event-placeholder'] = '<div class="wc-facebook-pixel-event-placeholder">' . $script . '</div>';
|
@@ -451,13 +605,42 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
451 |
return;
|
452 |
}
|
453 |
|
454 |
-
$
|
455 |
-
|
456 |
-
'
|
457 |
-
'
|
458 |
-
|
459 |
-
|
460 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
461 |
}
|
462 |
|
463 |
|
@@ -477,7 +660,9 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
477 |
*/
|
478 |
public function inject_purchase_event( $order_id ) {
|
479 |
|
480 |
-
|
|
|
|
|
481 |
return;
|
482 |
}
|
483 |
|
@@ -505,16 +690,17 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
505 |
return;
|
506 |
}
|
507 |
|
508 |
-
$content_type
|
509 |
-
$
|
510 |
-
$
|
511 |
-
$
|
512 |
|
513 |
foreach ( $order->get_items() as $item ) {
|
514 |
|
515 |
if ( $product = isset( $item['product_id'] ) ? wc_get_product( $item['product_id'] ) : null ) {
|
516 |
|
517 |
-
$product_ids[]
|
|
|
518 |
|
519 |
if ( 'product_group' !== $content_type && $product->is_type( 'variable' ) ) {
|
520 |
$content_type = 'product_group';
|
@@ -527,18 +713,28 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
527 |
$content->quantity = $quantity;
|
528 |
|
529 |
$contents[] = $content;
|
530 |
-
$num_items += $quantity;
|
531 |
}
|
532 |
}
|
533 |
|
534 |
-
$
|
535 |
-
'
|
536 |
-
'
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
542 |
|
543 |
$this->inject_subscribe_event( $order_id );
|
544 |
|
@@ -566,13 +762,25 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
566 |
foreach ( wcs_get_subscriptions_for_order( $order_id ) as $subscription ) {
|
567 |
|
568 |
// TODO consider 'StartTrial' event for free trial Subscriptions, which is the same as here (minus sign_up_fee) and tracks "when a person starts a free trial of a product or service" {FN 2020-03-20}
|
|
|
569 |
|
570 |
// TODO consider including (int|float) 'predicted_ltv': "Predicted lifetime value of a subscriber as defined by the advertiser and expressed as an exact value." {FN 2020-03-20}
|
571 |
-
$
|
572 |
-
'
|
573 |
-
'
|
574 |
-
|
575 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
576 |
}
|
577 |
}
|
578 |
|
@@ -614,6 +822,35 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
614 |
}
|
615 |
|
616 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
617 |
/**
|
618 |
* Gets the cart content items count.
|
619 |
*
|
@@ -653,6 +890,32 @@ if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
|
653 |
}
|
654 |
|
655 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
656 |
/**
|
657 |
* Gets the cart content data.
|
658 |
*
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
use SkyVerge\WooCommerce\Facebook\Events\Event;
|
12 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
13 |
+
|
14 |
if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) :
|
15 |
|
16 |
if ( ! class_exists( 'WC_Facebookcommerce_Utils' ) ) {
|
27 |
const FB_PRIORITY_HIGH = 2;
|
28 |
const FB_PRIORITY_LOW = 11;
|
29 |
|
30 |
+
/** @var Event search event instance */
|
31 |
+
private $search_event;
|
32 |
+
|
33 |
+
|
34 |
public function __construct( $user_info ) {
|
35 |
$this->pixel = new WC_Facebookcommerce_Pixel( $user_info );
|
36 |
|
118 |
*/
|
119 |
public function inject_view_category_event() {
|
120 |
global $wp_query;
|
121 |
+
|
122 |
+
if ( ! self::$isEnabled || ! is_product_category() ) {
|
123 |
return;
|
124 |
}
|
125 |
|
135 |
// if any product is a variant, fire the pixel with
|
136 |
// content_type: product_group
|
137 |
$content_type = 'product';
|
138 |
+
$product_ids = [];
|
139 |
+
$contents = [];
|
140 |
+
|
141 |
foreach ( $products as $product ) {
|
142 |
+
|
143 |
if ( ! $product ) {
|
144 |
continue;
|
145 |
}
|
146 |
+
|
147 |
+
$contents[] = [
|
148 |
+
'id' => \WC_Facebookcommerce_Utils::get_fb_retailer_id( $product ),
|
149 |
+
'quantity' => 1, // consider category results a quantity of 1
|
150 |
+
];
|
151 |
+
|
152 |
$product_ids = array_merge(
|
153 |
$product_ids,
|
154 |
WC_Facebookcommerce_Utils::get_fb_content_ids( $product )
|
158 |
}
|
159 |
}
|
160 |
|
161 |
+
$categories = WC_Facebookcommerce_Utils::get_product_categories( get_the_ID() );
|
|
|
162 |
|
163 |
+
$event_name = 'ViewCategory';
|
164 |
+
$event_data = [
|
165 |
+
'event_name' => $event_name,
|
166 |
+
'custom_data' => [
|
167 |
'content_name' => $categories['name'],
|
168 |
'content_category' => $categories['categories'],
|
169 |
'content_ids' => json_encode( array_slice( $product_ids, 0, 10 ) ),
|
170 |
'content_type' => $content_type,
|
171 |
+
'contents' => $contents,
|
172 |
+
],
|
173 |
+
];
|
174 |
+
|
175 |
+
$event = new Event( $event_data );
|
176 |
+
|
177 |
+
$this->send_api_event( $event );
|
178 |
+
|
179 |
+
$event_data['event_id'] = $event->get_id();
|
180 |
+
|
181 |
+
$this->pixel->inject_event( $event_name, $event_data, 'trackCustom' );
|
182 |
}
|
183 |
|
184 |
/**
|
185 |
* Triggers Search for result pages (deduped)
|
186 |
+
*
|
187 |
+
* @internal
|
188 |
*/
|
189 |
public function inject_search_event() {
|
190 |
+
|
191 |
if ( ! self::$isEnabled ) {
|
192 |
return;
|
193 |
}
|
194 |
|
195 |
+
if ( ! is_admin() && is_search() && '' !== get_search_query() && 'product' === get_query_var( 'post_type' ) ) {
|
196 |
+
|
197 |
if ( $this->pixel->is_last_event( 'Search' ) ) {
|
198 |
return;
|
199 |
}
|
200 |
|
201 |
+
// needs to run before wc_template_redirect, normally hooked with priority 10
|
202 |
+
add_action( 'template_redirect', [ $this, 'send_search_event' ], 5 );
|
203 |
+
add_action( 'woocommerce_before_shop_loop', [ $this, 'actually_inject_search_event' ] );
|
204 |
+
}
|
205 |
+
}
|
206 |
+
|
207 |
+
|
208 |
+
/**
|
209 |
+
* Sends a server-side Search event.
|
210 |
+
*
|
211 |
+
* @internal
|
212 |
+
*
|
213 |
+
* @since 2.0.0
|
214 |
+
*/
|
215 |
+
public function send_search_event() {
|
216 |
+
|
217 |
+
$this->send_api_event( $this->get_search_event() );
|
218 |
+
}
|
219 |
+
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Creates an Event instance to track a search request.
|
223 |
+
*
|
224 |
+
* The event instance is stored in memory to return a single instance per request.
|
225 |
+
*
|
226 |
+
* @since 2.0.0
|
227 |
+
*
|
228 |
+
* @return Event
|
229 |
+
*/
|
230 |
+
private function get_search_event() {
|
231 |
+
global $wp_query;
|
232 |
+
|
233 |
+
if ( null === $this->search_event ) {
|
234 |
+
|
235 |
+
// if any product is a variant, fire the pixel with content_type: product_group
|
236 |
+
$content_type = 'product';
|
237 |
+
$product_ids = [];
|
238 |
+
$contents = [];
|
239 |
+
$total_value = 0.00;
|
240 |
+
|
241 |
+
foreach ( $wp_query->posts as $post ) {
|
242 |
+
|
243 |
+
$product = wc_get_product( $post );
|
244 |
+
|
245 |
+
if ( ! $product instanceof \WC_Product ) {
|
246 |
+
continue;
|
247 |
+
}
|
248 |
+
|
249 |
+
$product_ids = array_merge( $product_ids, WC_Facebookcommerce_Utils::get_fb_content_ids( $product ) );
|
250 |
+
|
251 |
+
$contents[] = [
|
252 |
+
'id' => \WC_Facebookcommerce_Utils::get_fb_retailer_id( $product ),
|
253 |
+
'quantity' => 1, // consider the search results a quantity of 1
|
254 |
+
];
|
255 |
+
|
256 |
+
$total_value += (float) $product->get_price();
|
257 |
+
|
258 |
+
if ( WC_Facebookcommerce_Utils::is_variable_type( $product->get_type() ) ) {
|
259 |
+
$content_type = 'product_group';
|
260 |
+
}
|
261 |
}
|
262 |
+
|
263 |
+
$event_data = [
|
264 |
+
'event_name' => 'Search',
|
265 |
+
'custom_data' => [
|
266 |
+
'content_type' => $content_type,
|
267 |
+
'content_ids' => json_encode( array_slice( $product_ids, 0, 10 ) ),
|
268 |
+
'contents' => $contents,
|
269 |
+
'search_string' => get_search_query(),
|
270 |
+
'value' => Framework\SV_WC_Helper::number_format( $total_value ),
|
271 |
+
'currency' => get_woocommerce_currency(),
|
272 |
+
],
|
273 |
+
];
|
274 |
+
|
275 |
+
$this->search_event = new Event( $event_data );
|
276 |
}
|
277 |
+
|
278 |
+
return $this->search_event;
|
279 |
}
|
280 |
|
281 |
+
|
282 |
/**
|
283 |
+
* Injects a Search event on result pages.
|
284 |
+
*
|
285 |
+
* @internal
|
286 |
*/
|
287 |
public function actually_inject_search_event() {
|
|
|
|
|
|
|
288 |
|
289 |
+
$event = $this->get_search_event();
|
290 |
+
|
291 |
+
$this->pixel->inject_event( $event->get_name(), [
|
292 |
+
'event_id' => $event->get_id(),
|
293 |
+
'event_name' => $event->get_name(),
|
294 |
+
'custom_data' => $event->get_custom_data(),
|
295 |
+
] );
|
296 |
}
|
297 |
|
298 |
|
321 |
$content_type = 'product';
|
322 |
}
|
323 |
|
324 |
+
$categories = \WC_Facebookcommerce_Utils::get_product_categories( $product->get_id() );
|
325 |
+
|
326 |
+
$event_data = [
|
327 |
+
'event_name' => 'ViewContent',
|
328 |
+
'custom_data' => [
|
329 |
+
'content_name' => $product->get_title(),
|
330 |
+
'content_ids' => wp_json_encode( \WC_Facebookcommerce_Utils::get_fb_content_ids( $product ) ),
|
331 |
+
'content_type' => $content_type,
|
332 |
+
'contents' => [
|
333 |
+
[
|
334 |
+
'id' => \WC_Facebookcommerce_Utils::get_fb_retailer_id( $product ),
|
335 |
+
'quantity' => 1,
|
336 |
+
]
|
337 |
+
],
|
338 |
+
'content_category' => $categories['name'],
|
339 |
+
'value' => $product->get_price(),
|
340 |
+
'currency' => get_woocommerce_currency(),
|
341 |
+
],
|
342 |
+
];
|
343 |
+
|
344 |
+
$event = new \SkyVerge\WooCommerce\Facebook\Events\Event( $event_data );
|
345 |
+
|
346 |
+
$this->send_api_event( $event );
|
347 |
+
|
348 |
+
$event_data['event_id'] = $event->get_id();
|
349 |
+
|
350 |
+
$this->pixel->inject_event( 'ViewContent', $event_data );
|
351 |
}
|
352 |
|
353 |
|
375 |
return;
|
376 |
}
|
377 |
|
378 |
+
$event_data = [
|
379 |
+
'event_name' => 'AddToCart',
|
380 |
+
'custom_data' => [
|
381 |
+
'content_ids' => $this->get_cart_content_ids(),
|
382 |
+
'content_name' => $this->get_cart_content_names(),
|
383 |
+
'content_type' => 'product',
|
384 |
+
'contents' => $this->get_cart_contents(),
|
385 |
+
'value' => $this->get_cart_total(),
|
386 |
+
'currency' => get_woocommerce_currency(),
|
387 |
+
],
|
388 |
+
];
|
389 |
+
|
390 |
+
$event = new SkyVerge\WooCommerce\Facebook\Events\Event( $event_data );
|
391 |
+
|
392 |
+
$this->send_api_event( $event );
|
393 |
+
|
394 |
+
// send the event ID to prevent duplication
|
395 |
+
$event_data['event_id'] = $event->get_id();
|
396 |
+
|
397 |
+
// store the ID in the session to be sent in AJAX JS event tracking as well
|
398 |
+
WC()->session->set( 'facebook_for_woocommerce_add_to_cart_event_id', $event->get_id() );
|
399 |
+
|
400 |
+
$this->pixel->inject_event( 'AddToCart', $event_data );
|
401 |
}
|
402 |
|
403 |
|
432 |
|
433 |
if ( self::$isEnabled ) {
|
434 |
|
435 |
+
$params = [
|
436 |
'content_ids' => $this->get_cart_content_ids(),
|
437 |
+
'content_name' => $this->get_cart_content_names(),
|
438 |
'content_type' => 'product',
|
439 |
'contents' => $this->get_cart_contents(),
|
440 |
'value' => $this->get_cart_total(),
|
441 |
'currency' => get_woocommerce_currency(),
|
442 |
+
];
|
443 |
+
|
444 |
+
// send the event ID to prevent duplication
|
445 |
+
if ( ! empty ( $event_id = WC()->session->get( 'facebook_for_woocommerce_add_to_cart_event_id' ) ) ) {
|
446 |
+
|
447 |
+
$params['event_id'] = $event_id;
|
448 |
+
}
|
449 |
+
|
450 |
+
$script = $this->pixel->get_event_script( 'AddToCart', $params );
|
451 |
|
452 |
$fragments['div.wc-facebook-pixel-event-placeholder'] = '<div class="wc-facebook-pixel-event-placeholder">' . $script . '</div>';
|
453 |
}
|
491 |
|
492 |
$params = [
|
493 |
'content_ids' => $this->get_cart_content_ids(),
|
494 |
+
'content_name' => $this->get_cart_content_names(),
|
495 |
'content_type' => 'product',
|
496 |
'contents' => $this->get_cart_contents(),
|
497 |
'value' => $this->get_cart_total(),
|
498 |
'currency' => get_woocommerce_currency(),
|
499 |
];
|
500 |
|
501 |
+
// send the event ID to prevent duplication
|
502 |
+
if ( ! empty ( $event_id = WC()->session->get( 'facebook_for_woocommerce_add_to_cart_event_id' ) ) ) {
|
503 |
+
|
504 |
+
$params['event_id'] = $event_id;
|
505 |
+
}
|
506 |
+
|
507 |
$script = $this->pixel->get_conditional_one_time_event_script( 'AddToCart', $params, 'added_to_cart' );
|
508 |
|
509 |
$fragments['div.wc-facebook-pixel-event-placeholder'] = '<div class="wc-facebook-pixel-event-placeholder">' . $script . '</div>';
|
605 |
return;
|
606 |
}
|
607 |
|
608 |
+
$event_name = 'InitiateCheckout';
|
609 |
+
$event_data = [
|
610 |
+
'event_name' => $event_name,
|
611 |
+
'custom_data' => [
|
612 |
+
'num_items' => $this->get_cart_num_items(),
|
613 |
+
'content_ids' => $this->get_cart_content_ids(),
|
614 |
+
'content_name' => $this->get_cart_content_names(),
|
615 |
+
'content_type' => 'product',
|
616 |
+
'contents' => $this->get_cart_contents(),
|
617 |
+
'value' => $this->get_cart_total(),
|
618 |
+
'currency' => get_woocommerce_currency(),
|
619 |
+
],
|
620 |
+
];
|
621 |
+
|
622 |
+
// if there is only one item in the cart, send its first category
|
623 |
+
if ( ( $cart = WC()->cart ) && count( $cart->get_cart() ) === 1 ) {
|
624 |
+
|
625 |
+
$item = current( $cart->get_cart() );
|
626 |
+
|
627 |
+
if ( isset( $item['data'] ) && $item['data'] instanceof \WC_Product ) {
|
628 |
+
|
629 |
+
$categories = \WC_Facebookcommerce_Utils::get_product_categories( $item['data']->get_id() );
|
630 |
+
|
631 |
+
if ( ! empty( $categories['name'] ) ) {
|
632 |
+
$event_data['custom_data']['content_category'] = $categories['name'];
|
633 |
+
}
|
634 |
+
}
|
635 |
+
}
|
636 |
+
|
637 |
+
$event = new Event( $event_data );
|
638 |
+
|
639 |
+
$this->send_api_event( $event );
|
640 |
+
|
641 |
+
$event_data['event_id'] = $event->get_id();
|
642 |
+
|
643 |
+
$this->pixel->inject_event( $event_name, $event_data );
|
644 |
}
|
645 |
|
646 |
|
660 |
*/
|
661 |
public function inject_purchase_event( $order_id ) {
|
662 |
|
663 |
+
$event_name = 'Purchase';
|
664 |
+
|
665 |
+
if ( ! self::$isEnabled || $this->pixel->is_last_event( $event_name ) ) {
|
666 |
return;
|
667 |
}
|
668 |
|
690 |
return;
|
691 |
}
|
692 |
|
693 |
+
$content_type = 'product';
|
694 |
+
$contents = [];
|
695 |
+
$product_ids = [ [] ];
|
696 |
+
$product_names = [];
|
697 |
|
698 |
foreach ( $order->get_items() as $item ) {
|
699 |
|
700 |
if ( $product = isset( $item['product_id'] ) ? wc_get_product( $item['product_id'] ) : null ) {
|
701 |
|
702 |
+
$product_ids[] = \WC_Facebookcommerce_Utils::get_fb_content_ids( $product );
|
703 |
+
$product_names[] = $product->get_name();
|
704 |
|
705 |
if ( 'product_group' !== $content_type && $product->is_type( 'variable' ) ) {
|
706 |
$content_type = 'product_group';
|
713 |
$content->quantity = $quantity;
|
714 |
|
715 |
$contents[] = $content;
|
|
|
716 |
}
|
717 |
}
|
718 |
|
719 |
+
$event_data = [
|
720 |
+
'event_name' => $event_name,
|
721 |
+
'custom_data' => [
|
722 |
+
'content_ids' => wp_json_encode( array_merge( ... $product_ids ) ),
|
723 |
+
'content_name' => wp_json_encode( $product_names ),
|
724 |
+
'contents' => wp_json_encode( $contents ),
|
725 |
+
'content_type' => $content_type,
|
726 |
+
'value' => $order->get_total(),
|
727 |
+
'currency' => get_woocommerce_currency(),
|
728 |
+
],
|
729 |
+
];
|
730 |
+
|
731 |
+
$event = new Event( $event_data );
|
732 |
+
|
733 |
+
$this->send_api_event( $event );
|
734 |
+
|
735 |
+
$event_data['event_id'] = $event->get_id();
|
736 |
+
|
737 |
+
$this->pixel->inject_event( $event_name, $event_data );
|
738 |
|
739 |
$this->inject_subscribe_event( $order_id );
|
740 |
|
762 |
foreach ( wcs_get_subscriptions_for_order( $order_id ) as $subscription ) {
|
763 |
|
764 |
// TODO consider 'StartTrial' event for free trial Subscriptions, which is the same as here (minus sign_up_fee) and tracks "when a person starts a free trial of a product or service" {FN 2020-03-20}
|
765 |
+
$event_name = 'Subscribe';
|
766 |
|
767 |
// TODO consider including (int|float) 'predicted_ltv': "Predicted lifetime value of a subscriber as defined by the advertiser and expressed as an exact value." {FN 2020-03-20}
|
768 |
+
$event_data = [
|
769 |
+
'event_name' => $event_name,
|
770 |
+
'custom_data' => [
|
771 |
+
'sign_up_fee' => $subscription->get_sign_up_fee(),
|
772 |
+
'value' => $subscription->get_total(),
|
773 |
+
'currency' => get_woocommerce_currency(),
|
774 |
+
],
|
775 |
+
];
|
776 |
+
|
777 |
+
$event = new Event( $event_data );
|
778 |
+
|
779 |
+
$this->send_api_event( $event );
|
780 |
+
|
781 |
+
$event_data['event_id'] = $event->get_id();
|
782 |
+
|
783 |
+
$this->pixel->inject_event( $event_name, $event_data );
|
784 |
}
|
785 |
}
|
786 |
|
822 |
}
|
823 |
|
824 |
|
825 |
+
/**
|
826 |
+
* Sends an API event.
|
827 |
+
*
|
828 |
+
* @since 2.0.0
|
829 |
+
*
|
830 |
+
* @param Event $event event object
|
831 |
+
* @return bool
|
832 |
+
*/
|
833 |
+
protected function send_api_event( Event $event ) {
|
834 |
+
|
835 |
+
try {
|
836 |
+
|
837 |
+
facebook_for_woocommerce()->get_api()->send_pixel_events( facebook_for_woocommerce()->get_integration()->get_facebook_pixel_id(), [ $event ] );
|
838 |
+
|
839 |
+
$success = true;
|
840 |
+
|
841 |
+
} catch ( Framework\SV_WC_API_Exception $exception ) {
|
842 |
+
|
843 |
+
$success = false;
|
844 |
+
|
845 |
+
if ( facebook_for_woocommerce()->get_integration()->is_debug_mode_enabled() ) {
|
846 |
+
facebook_for_woocommerce()->log( 'Could not send Pixel event: ' . $exception->getMessage() );
|
847 |
+
}
|
848 |
+
}
|
849 |
+
|
850 |
+
return $success;
|
851 |
+
}
|
852 |
+
|
853 |
+
|
854 |
/**
|
855 |
* Gets the cart content items count.
|
856 |
*
|
890 |
}
|
891 |
|
892 |
|
893 |
+
/**
|
894 |
+
* Gets all content names from cart.
|
895 |
+
*
|
896 |
+
* @since 2.0.0
|
897 |
+
*
|
898 |
+
* @return string JSON data
|
899 |
+
*/
|
900 |
+
private function get_cart_content_names() {
|
901 |
+
|
902 |
+
$product_names = [];
|
903 |
+
|
904 |
+
if ( $cart = WC()->cart ) {
|
905 |
+
|
906 |
+
foreach ( $cart->get_cart() as $item ) {
|
907 |
+
|
908 |
+
if ( isset( $item['data'] ) && $item['data'] instanceof \WC_Product ) {
|
909 |
+
|
910 |
+
$product_names[] = $item['data']->get_name();
|
911 |
+
}
|
912 |
+
}
|
913 |
+
}
|
914 |
+
|
915 |
+
return wp_json_encode( array_unique( $product_names ) );
|
916 |
+
}
|
917 |
+
|
918 |
+
|
919 |
/**
|
920 |
* Gets the cart content data.
|
921 |
*
|
facebook-commerce-messenger-chat.php
CHANGED
@@ -125,9 +125,6 @@ if ( ! class_exists( 'WC_Facebookcommerce_MessengerChat' ) ) :
|
|
125 |
|
126 |
|
127 |
public function __construct( $settings ) {
|
128 |
-
$this->enabled = isset( $settings['is_messenger_chat_plugin_enabled'] )
|
129 |
-
? $settings['is_messenger_chat_plugin_enabled']
|
130 |
-
: 'no';
|
131 |
|
132 |
$this->page_id = isset( $settings['fb_page_id'] )
|
133 |
? $settings['fb_page_id']
|
@@ -137,18 +134,6 @@ if ( ! class_exists( 'WC_Facebookcommerce_MessengerChat' ) ) :
|
|
137 |
? $settings['facebook_jssdk_version']
|
138 |
: '';
|
139 |
|
140 |
-
$this->greeting_text_code = isset( $settings['msger_chat_customization_greeting_text_code'] )
|
141 |
-
? $settings['msger_chat_customization_greeting_text_code']
|
142 |
-
: null;
|
143 |
-
|
144 |
-
$this->locale = isset( $settings['msger_chat_customization_locale'] )
|
145 |
-
? $settings['msger_chat_customization_locale']
|
146 |
-
: null;
|
147 |
-
|
148 |
-
$this->theme_color_code = isset( $settings['msger_chat_customization_theme_color_code'] )
|
149 |
-
? $settings['msger_chat_customization_theme_color_code']
|
150 |
-
: null;
|
151 |
-
|
152 |
add_action( 'wp_footer', array( $this, 'inject_messenger_chat_plugin' ) );
|
153 |
}
|
154 |
|
@@ -160,16 +145,13 @@ if ( ! class_exists( 'WC_Facebookcommerce_MessengerChat' ) ) :
|
|
160 |
*/
|
161 |
public function inject_messenger_chat_plugin() {
|
162 |
|
163 |
-
if (
|
164 |
|
165 |
printf( "
|
166 |
<div
|
167 |
attribution=\"fbe_woocommerce\"
|
168 |
class=\"fb-customerchat\"
|
169 |
page_id=\"%s\"
|
170 |
-
%s
|
171 |
-
%s
|
172 |
-
%s
|
173 |
></div>
|
174 |
<!-- Facebook JSSDK -->
|
175 |
<script>
|
@@ -193,14 +175,8 @@ if ( ! class_exists( 'WC_Facebookcommerce_MessengerChat' ) ) :
|
|
193 |
<div></div>
|
194 |
",
|
195 |
esc_attr( $this->page_id ),
|
196 |
-
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
197 |
-
$this->theme_color_code ? 'theme_color="' . esc_attr( $this->theme_color_code ) . '"' : '',
|
198 |
-
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
199 |
-
$this->greeting_text_code ? 'logged_in_greeting="' . esc_attr( $this->greeting_text_code ) . '"' : '',
|
200 |
-
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
201 |
-
$this->greeting_text_code ? 'logged_out_greeting="' . esc_attr( $this->greeting_text_code ) . '"' : '',
|
202 |
esc_js( $this->jssdk_version ?: 'v5.0' ),
|
203 |
-
esc_js(
|
204 |
);
|
205 |
|
206 |
endif;
|
125 |
|
126 |
|
127 |
public function __construct( $settings ) {
|
|
|
|
|
|
|
128 |
|
129 |
$this->page_id = isset( $settings['fb_page_id'] )
|
130 |
? $settings['fb_page_id']
|
134 |
? $settings['facebook_jssdk_version']
|
135 |
: '';
|
136 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
add_action( 'wp_footer', array( $this, 'inject_messenger_chat_plugin' ) );
|
138 |
}
|
139 |
|
145 |
*/
|
146 |
public function inject_messenger_chat_plugin() {
|
147 |
|
148 |
+
if ( facebook_for_woocommerce()->get_integration()->is_messenger_enabled() ) :
|
149 |
|
150 |
printf( "
|
151 |
<div
|
152 |
attribution=\"fbe_woocommerce\"
|
153 |
class=\"fb-customerchat\"
|
154 |
page_id=\"%s\"
|
|
|
|
|
|
|
155 |
></div>
|
156 |
<!-- Facebook JSSDK -->
|
157 |
<script>
|
175 |
<div></div>
|
176 |
",
|
177 |
esc_attr( $this->page_id ),
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
esc_js( $this->jssdk_version ?: 'v5.0' ),
|
179 |
+
esc_js( facebook_for_woocommerce()->get_integration()->get_messenger_locale() ?: 'en_US' )
|
180 |
);
|
181 |
|
182 |
endif;
|
facebook-commerce-pixel-event.php
CHANGED
@@ -8,6 +8,8 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
|
|
|
|
11 |
if ( ! class_exists( 'WC_Facebookcommerce_Pixel' ) ) :
|
12 |
|
13 |
|
@@ -17,6 +19,8 @@ if ( ! class_exists( 'WC_Facebookcommerce_Pixel' ) ) :
|
|
17 |
const SETTINGS_KEY = 'facebook_config';
|
18 |
const PIXEL_ID_KEY = 'pixel_id';
|
19 |
const USE_PII_KEY = 'use_pii';
|
|
|
|
|
20 |
|
21 |
/** @var string cache key for pixel script block output */
|
22 |
const PIXEL_RENDER = 'pixel_render';
|
@@ -78,13 +82,7 @@ if ( ! class_exists( 'WC_Facebookcommerce_Pixel' ) ) :
|
|
78 |
*/
|
79 |
private function get_pixel_init_code() {
|
80 |
|
81 |
-
$
|
82 |
-
$agent_string = sprintf(
|
83 |
-
'%s-%s-%s',
|
84 |
-
$version_info['source'],
|
85 |
-
$version_info['version'],
|
86 |
-
$version_info['pluginVersion']
|
87 |
-
);
|
88 |
|
89 |
/**
|
90 |
* Filters Facebook Pixel init code.
|
@@ -396,14 +394,51 @@ if ( ! class_exists( 'WC_Facebookcommerce_Pixel' ) ) :
|
|
396 |
*/
|
397 |
public static function build_event( $event_name, $params, $method = 'track' ) {
|
398 |
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
407 |
}
|
408 |
|
409 |
|
@@ -420,7 +455,7 @@ if ( ! class_exists( 'WC_Facebookcommerce_Pixel' ) ) :
|
|
420 |
*/
|
421 |
private static function build_params( $params = [], $event = '' ) {
|
422 |
|
423 |
-
$params = array_replace(
|
424 |
|
425 |
/**
|
426 |
* Filters the parameters for the pixel code.
|
@@ -504,6 +539,48 @@ if ( ! class_exists( 'WC_Facebookcommerce_Pixel' ) ) :
|
|
504 |
update_option( self::SETTINGS_KEY, $fb_options );
|
505 |
}
|
506 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
507 |
private static function get_version_info() {
|
508 |
global $wp_version;
|
509 |
|
@@ -528,6 +605,8 @@ if ( ! class_exists( 'WC_Facebookcommerce_Pixel' ) ) :
|
|
528 |
array(
|
529 |
self::PIXEL_ID_KEY => '0',
|
530 |
self::USE_PII_KEY => 0,
|
|
|
|
|
531 |
)
|
532 |
);
|
533 |
}
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
use SkyVerge\WooCommerce\Facebook\Events\Event;
|
12 |
+
|
13 |
if ( ! class_exists( 'WC_Facebookcommerce_Pixel' ) ) :
|
14 |
|
15 |
|
19 |
const SETTINGS_KEY = 'facebook_config';
|
20 |
const PIXEL_ID_KEY = 'pixel_id';
|
21 |
const USE_PII_KEY = 'use_pii';
|
22 |
+
const USE_S2S_KEY= 'use_s2s';
|
23 |
+
const ACCESS_TOKEN_KEY = 'access_token';
|
24 |
|
25 |
/** @var string cache key for pixel script block output */
|
26 |
const PIXEL_RENDER = 'pixel_render';
|
82 |
*/
|
83 |
private function get_pixel_init_code() {
|
84 |
|
85 |
+
$agent_string = Event::get_platform_identifier();
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
|
87 |
/**
|
88 |
* Filters Facebook Pixel init code.
|
394 |
*/
|
395 |
public static function build_event( $event_name, $params, $method = 'track' ) {
|
396 |
|
397 |
+
// do not send the event name in the params
|
398 |
+
if ( isset( $params['event_name'] ) ) {
|
399 |
+
|
400 |
+
unset( $params['event_name'] );
|
401 |
+
}
|
402 |
+
|
403 |
+
// if possible, send the event ID to avoid duplication
|
404 |
+
// @see https://developers.facebook.com/docs/marketing-api/server-side-api/deduplicate-pixel-and-server-side-events#deduplication-best-practices
|
405 |
+
if ( isset( $params['event_id'] ) ) {
|
406 |
+
|
407 |
+
$event_id = $params['event_id'];
|
408 |
+
unset( $params['event_id'] );
|
409 |
+
}
|
410 |
+
|
411 |
+
// if custom data is set, send only the custom data
|
412 |
+
if ( isset( $params['custom_data'] ) ) {
|
413 |
+
|
414 |
+
$params = $params['custom_data'];
|
415 |
+
}
|
416 |
+
|
417 |
+
if ( ! empty( $event_id ) ) {
|
418 |
+
|
419 |
+
$event = sprintf(
|
420 |
+
"/* %s Facebook Integration Event Tracking */\n" .
|
421 |
+
"fbq('%s', '%s', %s, %s);",
|
422 |
+
WC_Facebookcommerce_Utils::getIntegrationName(),
|
423 |
+
esc_js( $method ),
|
424 |
+
esc_js( $event_name ),
|
425 |
+
json_encode( self::build_params( $params, $event_name ), JSON_PRETTY_PRINT | JSON_FORCE_OBJECT ),
|
426 |
+
json_encode( [ 'eventID' => $event_id ], JSON_PRETTY_PRINT | JSON_FORCE_OBJECT )
|
427 |
+
);
|
428 |
+
|
429 |
+
} else {
|
430 |
+
|
431 |
+
$event = sprintf(
|
432 |
+
"/* %s Facebook Integration Event Tracking */\n" .
|
433 |
+
"fbq('%s', '%s', %s);",
|
434 |
+
WC_Facebookcommerce_Utils::getIntegrationName(),
|
435 |
+
esc_js( $method ),
|
436 |
+
esc_js( $event_name ),
|
437 |
+
json_encode( self::build_params( $params, $event_name ), JSON_PRETTY_PRINT | JSON_FORCE_OBJECT )
|
438 |
+
);
|
439 |
+
}
|
440 |
+
|
441 |
+
return $event;
|
442 |
}
|
443 |
|
444 |
|
455 |
*/
|
456 |
private static function build_params( $params = [], $event = '' ) {
|
457 |
|
458 |
+
$params = array_replace( Event::get_version_info(), $params );
|
459 |
|
460 |
/**
|
461 |
* Filters the parameters for the pixel code.
|
539 |
update_option( self::SETTINGS_KEY, $fb_options );
|
540 |
}
|
541 |
|
542 |
+
public static function get_use_s2s() {
|
543 |
+
$fb_options = self::get_options();
|
544 |
+
if ( ! $fb_options ) {
|
545 |
+
return false;
|
546 |
+
}
|
547 |
+
return isset( $fb_options[ self::USE_S2S_KEY ] ) ?
|
548 |
+
$fb_options[ self::USE_S2S_KEY ] : false;
|
549 |
+
}
|
550 |
+
|
551 |
+
public static function set_use_s2s( $use_s2s ) {
|
552 |
+
$fb_options = self::get_options();
|
553 |
+
|
554 |
+
if ( isset( $fb_options[ self::USE_S2S_KEY ] )
|
555 |
+
&& $fb_options[ self::USE_S2S_KEY ] == $use_s2s ) {
|
556 |
+
return;
|
557 |
+
}
|
558 |
+
|
559 |
+
$fb_options[ self::USE_S2S_KEY ] = $use_s2s;
|
560 |
+
update_option( self::SETTINGS_KEY, $fb_options );
|
561 |
+
}
|
562 |
+
|
563 |
+
public static function get_access_token() {
|
564 |
+
$fb_options = self::get_options();
|
565 |
+
if ( ! $fb_options ) {
|
566 |
+
return '';
|
567 |
+
}
|
568 |
+
return isset( $fb_options[ self::ACCESS_TOKEN_KEY ] ) ?
|
569 |
+
$fb_options[ self::ACCESS_TOKEN_KEY ] : '';
|
570 |
+
}
|
571 |
+
|
572 |
+
public static function set_access_token( $access_token ) {
|
573 |
+
$fb_options = self::get_options();
|
574 |
+
|
575 |
+
if ( isset( $fb_options[ self::ACCESS_TOKEN_KEY ] )
|
576 |
+
&& $fb_options[ self::ACCESS_TOKEN_KEY ] == $access_token ) {
|
577 |
+
return;
|
578 |
+
}
|
579 |
+
|
580 |
+
$fb_options[ self::ACCESS_TOKEN_KEY ] = $access_token;
|
581 |
+
update_option( self::SETTINGS_KEY, $fb_options );
|
582 |
+
}
|
583 |
+
|
584 |
private static function get_version_info() {
|
585 |
global $wp_version;
|
586 |
|
605 |
array(
|
606 |
self::PIXEL_ID_KEY => '0',
|
607 |
self::USE_PII_KEY => 0,
|
608 |
+
self::USE_S2S_KEY => false,
|
609 |
+
self::ACCESS_TOKEN_KEY => '',
|
610 |
)
|
611 |
);
|
612 |
}
|
facebook-commerce.php
CHANGED
@@ -8,6 +8,7 @@
|
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
|
|
11 |
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
12 |
use SkyVerge\WooCommerce\Facebook\Products;
|
13 |
use SkyVerge\WooCommerce\Facebook\Products\Feed;
|
@@ -45,43 +46,49 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
45 |
const OPTION_PIXEL_INSTALL_TIME = 'wc_facebook_pixel_install_time';
|
46 |
|
47 |
/** @var string the facebook page ID setting ID */
|
48 |
-
const SETTING_FACEBOOK_PAGE_ID = '
|
49 |
|
50 |
/** @var string the facebook pixel ID setting ID */
|
51 |
-
const SETTING_FACEBOOK_PIXEL_ID = '
|
52 |
|
53 |
/** @var string the "enable advanced matching" setting ID */
|
54 |
const SETTING_ENABLE_ADVANCED_MATCHING = 'enable_advanced_matching';
|
55 |
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
/** @var string the "enable product sync" setting ID */
|
57 |
-
const SETTING_ENABLE_PRODUCT_SYNC = '
|
58 |
|
59 |
/** @var string the excluded product category IDs setting ID */
|
60 |
-
const SETTING_EXCLUDED_PRODUCT_CATEGORY_IDS = '
|
61 |
|
62 |
/** @var string the excluded product tag IDs setting ID */
|
63 |
-
const SETTING_EXCLUDED_PRODUCT_TAG_IDS = '
|
64 |
|
65 |
/** @var string the product description mode setting ID */
|
66 |
-
const SETTING_PRODUCT_DESCRIPTION_MODE = '
|
67 |
|
68 |
/** @var string the scheduled resync offset setting ID */
|
69 |
const SETTING_SCHEDULED_RESYNC_OFFSET = 'scheduled_resync_offset';
|
70 |
|
71 |
/** @var string the "enable messenger" setting ID */
|
72 |
-
const SETTING_ENABLE_MESSENGER = '
|
73 |
|
74 |
/** @var string the messenger locale setting ID */
|
75 |
-
const SETTING_MESSENGER_LOCALE = '
|
76 |
|
77 |
/** @var string the messenger greeting setting ID */
|
78 |
-
const SETTING_MESSENGER_GREETING = '
|
79 |
|
80 |
/** @var string the messenger color HEX setting ID */
|
81 |
-
const SETTING_MESSENGER_COLOR_HEX = '
|
82 |
|
83 |
/** @var string the "debug mode" setting ID */
|
84 |
-
const SETTING_ENABLE_DEBUG_MODE = '
|
85 |
|
86 |
/** @var string the standard product description mode name */
|
87 |
const PRODUCT_DESCRIPTION_MODE_STANDARD = 'standard';
|
@@ -117,6 +124,9 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
117 |
/** @var bool|null whether the feed has been migrated from FBE 1 to FBE 1.5 */
|
118 |
private $feed_migrated;
|
119 |
|
|
|
|
|
|
|
120 |
|
121 |
/** Legacy properties *********************************************************************************************/
|
122 |
|
@@ -132,6 +142,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
132 |
/** @var string the API flag to set a product as not visible in the Facebook shop */
|
133 |
const FB_SHOP_PRODUCT_HIDDEN = 'staging';
|
134 |
|
|
|
135 |
const FB_CART_URL = 'fb_cart_url';
|
136 |
|
137 |
const FB_MESSAGE_DISPLAY_TIME = 180;
|
@@ -176,6 +187,12 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
176 |
// so that it works the same way the pixel ID does
|
177 |
$settings_advanced_matching_enabled = $this->is_advanced_matching_enabled();
|
178 |
WC_Facebookcommerce_Pixel::set_use_pii_key( $settings_advanced_matching_enabled );
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
}
|
180 |
}
|
181 |
|
@@ -218,6 +235,13 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
218 |
$this->settings[ self::SETTING_ENABLE_ADVANCED_MATCHING ] = $advanced_matching_enabled;
|
219 |
}
|
220 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
221 |
if ( ! class_exists( 'WC_Facebookcommerce_Utils' ) ) {
|
222 |
include_once 'includes/fbutils.php';
|
223 |
}
|
@@ -226,7 +250,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
226 |
|
227 |
if ( ! class_exists( 'WC_Facebookcommerce_Graph_API' ) ) {
|
228 |
include_once 'includes/fbgraph.php';
|
229 |
-
$this->fbgraph = new WC_Facebookcommerce_Graph_API(
|
230 |
}
|
231 |
|
232 |
WC_Facebookcommerce_Utils::$fbgraph = $this->fbgraph;
|
@@ -236,8 +260,6 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
236 |
|
237 |
$this->init_pixel();
|
238 |
|
239 |
-
$this->init_form_fields();
|
240 |
-
|
241 |
if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) {
|
242 |
include_once 'includes/fbutils.php';
|
243 |
}
|
@@ -276,23 +298,8 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
276 |
}
|
277 |
|
278 |
add_action( 'admin_notices', array( $this, 'checks' ) );
|
279 |
-
add_action(
|
280 |
-
'woocommerce_update_options_integration_facebookcommerce',
|
281 |
-
array( $this, 'process_admin_options' )
|
282 |
-
);
|
283 |
-
add_action( 'admin_enqueue_scripts', array( $this, 'load_assets' ) );
|
284 |
-
|
285 |
-
add_action(
|
286 |
-
'wp_ajax_ajax_save_fb_settings',
|
287 |
-
array( $this, 'ajax_save_fb_settings' ),
|
288 |
-
self::FB_PRIORITY_MID
|
289 |
-
);
|
290 |
|
291 |
-
add_action(
|
292 |
-
'wp_ajax_ajax_delete_fb_settings',
|
293 |
-
array( $this, 'ajax_delete_fb_settings' ),
|
294 |
-
self::FB_PRIORITY_MID
|
295 |
-
);
|
296 |
|
297 |
add_action(
|
298 |
'wp_ajax_ajax_sync_all_fb_products',
|
@@ -328,20 +335,14 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
328 |
self::FB_PRIORITY_MID
|
329 |
);
|
330 |
|
331 |
-
add_action(
|
332 |
-
'wp_ajax_ajax_update_fb_option',
|
333 |
-
array( $this, 'ajax_update_fb_option' ),
|
334 |
-
self::FB_PRIORITY_MID
|
335 |
-
);
|
336 |
-
|
337 |
-
// on_product_save() must run with priority larger than 20 to make sure WooCommerce has a chance to save the submitted product information
|
338 |
-
add_action( 'woocommerce_process_product_meta', [ $this, 'on_product_save' ], 40 );
|
339 |
-
|
340 |
// don't duplicate product FBID meta
|
341 |
add_filter( 'woocommerce_duplicate_product_exclude_meta', [ $this, 'fb_duplicate_product_reset_meta' ] );
|
342 |
|
343 |
-
//
|
344 |
-
if ( $this->
|
|
|
|
|
|
|
345 |
|
346 |
add_action(
|
347 |
'woocommerce_product_quick_edit_save',
|
@@ -357,16 +358,9 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
357 |
1 // Args passed to on_quick_and_bulk_edit_save ('product')
|
358 |
);
|
359 |
|
360 |
-
add_action( '
|
361 |
-
|
362 |
-
add_action(
|
363 |
-
'before_delete_post',
|
364 |
-
array( $this, 'on_product_delete' ),
|
365 |
-
10,
|
366 |
-
1
|
367 |
-
);
|
368 |
|
369 |
-
|
370 |
|
371 |
add_action(
|
372 |
'transition_post_status',
|
@@ -422,17 +416,11 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
422 |
$this->events_tracker = new WC_Facebookcommerce_EventsTracker( $user_info );
|
423 |
}
|
424 |
|
425 |
-
|
426 |
-
|
427 |
-
$this->
|
428 |
-
|
429 |
-
|
430 |
-
'msger_chat_customization_greeting_text_code' => $this->get_messenger_greeting(),
|
431 |
-
'msger_chat_customization_locale' => $this->get_messenger_locale(),
|
432 |
-
'msger_chat_customization_theme_color_code' => $this->get_messenger_color_hex(),
|
433 |
-
'facebook_jssdk_version' => $this->get_js_sdk_version(),
|
434 |
-
] );
|
435 |
-
}
|
436 |
}
|
437 |
|
438 |
public function load_background_sync_process() {
|
@@ -457,7 +445,9 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
457 |
if ( isset( $_POST['request_time'] ) ) {
|
458 |
$request_time = esc_js( sanitize_text_field( wp_unslash( $_POST['request_time'] ) ) );
|
459 |
}
|
460 |
-
|
|
|
|
|
461 |
if ( isset( $this->background_processor ) ) {
|
462 |
$is_processing = $this->background_processor->handle_cron_healthcheck();
|
463 |
$remaining = $this->background_processor->get_item_count();
|
@@ -480,6 +470,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
480 |
'background' => false,
|
481 |
);
|
482 |
}
|
|
|
483 |
printf( json_encode( $response ) );
|
484 |
wp_die();
|
485 |
}
|
@@ -552,9 +543,11 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
552 |
wp_enqueue_script(
|
553 |
'wc_facebook_metabox_jsx',
|
554 |
plugins_url(
|
555 |
-
'/assets/js/facebook-metabox.min.js
|
556 |
__FILE__
|
557 |
-
)
|
|
|
|
|
558 |
);
|
559 |
wp_localize_script(
|
560 |
'wc_facebook_metabox_jsx',
|
@@ -592,53 +585,29 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
592 |
if ( $fb_product_group_id ) {
|
593 |
|
594 |
?>
|
595 |
-
<?php echo esc_html__( 'Facebook ID:', 'facebook-for-woocommerce' ); ?>
|
596 |
-
<a href="https://facebook.com/<?php echo esc_attr( $fb_product_group_id ); ?>"
|
597 |
-
target="_blank">
|
598 |
-
<?php echo esc_html( $fb_product_group_id ); ?>
|
599 |
-
</a>
|
600 |
-
<p/>
|
601 |
-
<?php
|
602 |
|
603 |
-
|
|
|
604 |
|
605 |
-
|
606 |
-
<p><?php echo esc_html__( 'Variant IDs:', 'facebook-for-woocommerce' ); ?><br/>
|
607 |
-
<?php
|
608 |
|
609 |
-
$
|
610 |
|
611 |
-
|
|
|
612 |
|
613 |
-
|
614 |
-
self::FB_PRODUCT_ITEM_ID,
|
615 |
-
$child_id
|
616 |
-
);
|
617 |
|
618 |
-
|
619 |
-
|
620 |
-
<a href="https://facebook.com/<?php echo esc_attr( $fb_product_item_id ); ?>"
|
621 |
-
target="_blank">
|
622 |
-
<?php echo esc_html( $fb_product_item_id ); ?>
|
623 |
-
</a><br/>
|
624 |
-
<?php
|
625 |
-
}
|
626 |
|
627 |
-
|
628 |
</p>
|
629 |
-
<?php
|
630 |
-
}
|
631 |
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
<input name="<?php echo esc_attr( Products::VISIBILITY_META_KEY ); ?>"
|
636 |
-
type="checkbox"
|
637 |
-
value="1"
|
638 |
-
<?php echo checked( ! $woo_product->woo_product instanceof \WC_Product || Products::is_product_visible( $woo_product->woo_product ) ); ?>/>
|
639 |
|
640 |
-
<p/>
|
641 |
-
<?php */ ?>
|
642 |
<input name="is_product_page" type="hidden" value="1"/>
|
643 |
|
644 |
<p/>
|
@@ -666,12 +635,100 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
666 |
}
|
667 |
|
668 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
669 |
/**
|
670 |
* Gets the total of published products.
|
671 |
*
|
672 |
* @return int
|
673 |
*/
|
674 |
-
|
675 |
|
676 |
$args = [
|
677 |
'post_type' => 'product',
|
@@ -700,9 +757,11 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
700 |
wp_enqueue_script(
|
701 |
'wc_facebook_infobanner_jsx',
|
702 |
plugins_url(
|
703 |
-
'/assets/js/facebook-infobanner.min.js
|
704 |
__FILE__
|
705 |
-
)
|
|
|
|
|
706 |
);
|
707 |
wp_localize_script(
|
708 |
'wc_facebook_infobanner_jsx',
|
@@ -715,7 +774,9 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
715 |
plugins_url(
|
716 |
'/assets/css/facebook-infobanner.css',
|
717 |
__FILE__
|
718 |
-
)
|
|
|
|
|
719 |
);
|
720 |
|
721 |
if ( ! facebook_for_woocommerce()->is_plugin_settings() ) {
|
@@ -758,9 +819,6 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
758 |
feedMigrated: <?php echo $this->is_feed_migrated() ? 'true' : 'false'; ?>,
|
759 |
samples: <?php echo $this->get_sample_product_feed(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
760 |
},
|
761 |
-
excludedCategoryIDs: <?php echo json_encode( $this->get_excluded_product_category_ids() ); ?>,
|
762 |
-
excludedTagIDs: <?php echo json_encode( $this->get_excluded_product_tag_ids() ); ?>,
|
763 |
-
messengerGreetingMaxCharacters: <?php echo esc_js( $this->get_messenger_greeting_max_characters() ); ?>
|
764 |
};
|
765 |
|
766 |
</script>
|
@@ -769,13 +827,6 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
769 |
$ajax_data = [
|
770 |
'nonce' => wp_create_nonce( 'wc_facebook_settings_jsx' ),
|
771 |
];
|
772 |
-
wp_enqueue_script(
|
773 |
-
'wc_facebook_settings_jsx',
|
774 |
-
plugins_url(
|
775 |
-
'/assets/js/facebook-settings.min.js?ts=' . time(),
|
776 |
-
__FILE__
|
777 |
-
)
|
778 |
-
);
|
779 |
wp_localize_script(
|
780 |
'wc_facebook_settings_jsx',
|
781 |
'wc_facebook_settings_jsx',
|
@@ -786,7 +837,9 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
786 |
plugins_url(
|
787 |
'/assets/css/facebook.css',
|
788 |
__FILE__
|
789 |
-
)
|
|
|
|
|
790 |
);
|
791 |
}
|
792 |
|
@@ -794,7 +847,6 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
794 |
/**
|
795 |
* Checks the product type and calls the corresponding on publish method.
|
796 |
*
|
797 |
-
*
|
798 |
* @internal
|
799 |
*
|
800 |
* @since 1.10.0
|
@@ -809,28 +861,35 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
809 |
return;
|
810 |
}
|
811 |
|
812 |
-
|
813 |
-
$sync_enabled =
|
814 |
-
|
|
|
|
|
|
|
|
|
815 |
|
816 |
if ( ! $product->is_type( 'variable' ) ) {
|
817 |
|
818 |
if ( $sync_enabled ) {
|
819 |
|
820 |
Products::enable_sync_for_products( [ $product ] );
|
|
|
821 |
|
822 |
$this->save_product_settings( $product );
|
823 |
|
824 |
} else {
|
825 |
|
|
|
|
|
|
|
|
|
|
|
826 |
Products::disable_sync_for_products( [ $product ] );
|
827 |
}
|
828 |
}
|
829 |
|
830 |
-
|
831 |
-
// $this->update_fb_visibility( $product->get_id(), $is_visible ? self::FB_SHOP_PRODUCT_VISIBLE : self::FB_SHOP_PRODUCT_HIDDEN );
|
832 |
-
|
833 |
-
if ( $sync_enabled && $this->get_page_access_token() && $this->get_product_catalog_id() ) {
|
834 |
|
835 |
switch ( $product->get_type() ) {
|
836 |
|
@@ -851,8 +910,6 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
851 |
break;
|
852 |
}
|
853 |
}
|
854 |
-
|
855 |
-
$this->enable_product_sync_delay_admin_notice();
|
856 |
}
|
857 |
|
858 |
|
@@ -888,72 +945,60 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
888 |
}
|
889 |
|
890 |
|
891 |
-
/**
|
892 |
-
* Enables product sync delay notice when a post is moved to the trash.
|
893 |
-
*
|
894 |
-
* @internal
|
895 |
-
*
|
896 |
-
* @since 1.11.0
|
897 |
-
*
|
898 |
-
* @param int $post_id the post ID
|
899 |
-
*/
|
900 |
-
public function on_product_trash( $post_id ) {
|
901 |
-
|
902 |
-
$product = wc_get_product( $post_id );
|
903 |
-
|
904 |
-
if ( $product instanceof \WC_Product ) {
|
905 |
-
$this->enable_product_sync_delay_admin_notice();
|
906 |
-
}
|
907 |
-
}
|
908 |
-
|
909 |
-
|
910 |
/**
|
911 |
* Deletes a product from Facebook.
|
912 |
*
|
913 |
-
* @param int $
|
914 |
*/
|
915 |
-
public function on_product_delete( $
|
916 |
|
917 |
-
$
|
918 |
|
919 |
-
if
|
920 |
-
|
921 |
-
// been deleted.
|
922 |
return;
|
923 |
}
|
924 |
|
925 |
-
|
926 |
-
|
|
|
|
|
|
|
|
|
|
|
927 |
return;
|
928 |
}
|
929 |
|
930 |
-
|
931 |
-
|
932 |
-
$
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
-
self::FB_PRODUCT_ITEM_ID,
|
937 |
-
$wp_id,
|
938 |
-
$woo_product
|
939 |
-
);
|
940 |
-
if ( ! ( $fb_product_group_id || $fb_product_item_id ) ) {
|
941 |
-
return; // No synced product, no-op.
|
942 |
-
}
|
943 |
-
$products = array( $wp_id );
|
944 |
-
if ( WC_Facebookcommerce_Utils::is_variable_type( $woo_product->get_type() ) ) {
|
945 |
-
$children = $woo_product->get_children();
|
946 |
-
$products = array_merge( $products, $children );
|
947 |
-
}
|
948 |
-
foreach ( $products as $item_id ) {
|
949 |
-
$this->delete_product_item( $item_id );
|
950 |
-
}
|
951 |
-
if ( $fb_product_group_id ) {
|
952 |
-
$pg_result = $this->fbgraph->delete_product_group( $fb_product_group_id );
|
953 |
-
WC_Facebookcommerce_Utils::log( $pg_result );
|
954 |
-
}
|
955 |
|
956 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
957 |
}
|
958 |
|
959 |
|
@@ -967,7 +1012,6 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
967 |
* @param \WP_post $post
|
968 |
*/
|
969 |
public function fb_change_product_published_status( $new_status, $old_status, $post ) {
|
970 |
-
global $post;
|
971 |
|
972 |
if ( ! $post ) {
|
973 |
return;
|
@@ -977,7 +1021,12 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
977 |
|
978 |
$product = wc_get_product( $post->ID );
|
979 |
|
980 |
-
// bail if
|
|
|
|
|
|
|
|
|
|
|
981 |
if ( ! $product instanceof \WC_Product || ! Products::product_should_be_synced( $product ) ) {
|
982 |
return;
|
983 |
}
|
@@ -986,7 +1035,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
986 |
// change from trash status -> publish status
|
987 |
// no need to update for change from trash <-> unpublish status
|
988 |
if ( ( $old_status === 'publish' && $new_status !== 'publish' ) || ( $old_status === 'trash' && $new_status === 'publish' ) ) {
|
989 |
-
$this->update_fb_visibility( $
|
990 |
}
|
991 |
}
|
992 |
|
@@ -997,30 +1046,25 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
997 |
* Will determine product type (simple or variable) and delegate to
|
998 |
* appropriate handler.
|
999 |
*
|
1000 |
-
* @param int $
|
1001 |
*/
|
1002 |
-
public function on_product_publish( $
|
1003 |
-
|
1004 |
-
// bail if we don't have a page access token or a catalog ID configured
|
1005 |
-
if ( ! $this->get_page_access_token() || ! $this->get_product_catalog_id() ) {
|
1006 |
-
return;
|
1007 |
-
}
|
1008 |
|
1009 |
-
|
|
|
1010 |
return;
|
1011 |
}
|
1012 |
|
1013 |
-
$
|
1014 |
|
1015 |
-
|
1016 |
-
if ( ! $woo_product->woo_product instanceof \WC_Product || ! Products::product_should_be_synced( $woo_product->woo_product ) ) {
|
1017 |
return;
|
1018 |
}
|
1019 |
|
1020 |
-
if ( $
|
1021 |
-
$this->on_variable_product_publish( $
|
1022 |
} else {
|
1023 |
-
$this->on_simple_product_publish( $
|
1024 |
}
|
1025 |
}
|
1026 |
|
@@ -1030,11 +1074,13 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1030 |
* this function will delete the product from FB Page as well.
|
1031 |
*/
|
1032 |
function delete_on_out_of_stock( $wp_id, $woo_product ) {
|
1033 |
-
|
1034 |
-
|
|
|
1035 |
$this->delete_product_item( $wp_id );
|
1036 |
return true;
|
1037 |
}
|
|
|
1038 |
return false;
|
1039 |
}
|
1040 |
|
@@ -1047,29 +1093,21 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1047 |
*/
|
1048 |
function on_variable_product_publish( $wp_id, $woo_product = null ) {
|
1049 |
|
1050 |
-
if ( ! $
|
1051 |
-
|
1052 |
}
|
1053 |
|
1054 |
-
if (
|
1055 |
return;
|
1056 |
}
|
1057 |
|
1058 |
-
|
1059 |
-
// If yes, loop through variants and see if product items are published.
|
1060 |
-
if ( ! $woo_product ) {
|
1061 |
-
$woo_product = new WC_Facebook_Product( $wp_id );
|
1062 |
-
}
|
1063 |
-
|
1064 |
-
if ( $this->delete_on_out_of_stock( $wp_id, $woo_product ) ) {
|
1065 |
return;
|
1066 |
}
|
1067 |
|
1068 |
-
|
1069 |
-
|
1070 |
-
|
1071 |
-
$woo_product
|
1072 |
-
);
|
1073 |
|
1074 |
if ( $fb_product_group_id ) {
|
1075 |
|
@@ -1077,25 +1115,26 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1077 |
|
1078 |
$this->update_product_group( $woo_product );
|
1079 |
|
1080 |
-
|
1081 |
-
$variation_id = $woo_product->find_matching_product_variation();
|
1082 |
|
1083 |
-
|
1084 |
-
// If default variation value is to update, delete old fb_product_item_id
|
1085 |
-
// and create new one in order to make it order correctly.
|
1086 |
-
foreach ( $child_products as $item_id ) {
|
1087 |
|
1088 |
-
|
|
|
1089 |
|
1090 |
-
|
1091 |
-
$this->set_default_variant( $fb_product_group_id, $fb_product_item_id );
|
1092 |
-
}
|
1093 |
-
}
|
1094 |
|
1095 |
-
|
|
|
1096 |
|
1097 |
-
$
|
|
|
|
|
|
|
|
|
1098 |
}
|
|
|
|
|
1099 |
}
|
1100 |
|
1101 |
|
@@ -1109,24 +1148,15 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1109 |
*/
|
1110 |
function on_simple_product_publish( $wp_id, $woo_product = null, &$parent_product = null ) {
|
1111 |
|
1112 |
-
if ( ! $
|
1113 |
-
|
1114 |
-
}
|
1115 |
-
|
1116 |
-
if ( get_post_status( $wp_id ) != 'publish' ) {
|
1117 |
-
return;
|
1118 |
-
}
|
1119 |
-
|
1120 |
-
if ( ! $woo_product ) {
|
1121 |
-
$woo_product = new WC_Facebook_Product( $wp_id, $parent_product );
|
1122 |
}
|
1123 |
|
1124 |
-
|
1125 |
-
if ( ! $woo_product->woo_product instanceof \WC_Product || ! Products::product_should_be_synced( $woo_product->woo_product ) ) {
|
1126 |
return;
|
1127 |
}
|
1128 |
|
1129 |
-
if ( $this->delete_on_out_of_stock( $wp_id, $woo_product ) ) {
|
1130 |
return;
|
1131 |
}
|
1132 |
|
@@ -1175,34 +1205,43 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1175 |
}
|
1176 |
}
|
1177 |
|
1178 |
-
function create_product_variable( $woo_product ) {
|
1179 |
-
$retailer_id = WC_Facebookcommerce_Utils::get_fb_retailer_id( $woo_product );
|
1180 |
|
1181 |
-
|
1182 |
-
|
1183 |
-
|
1184 |
-
|
1185 |
-
|
|
|
|
|
|
|
|
|
|
|
1186 |
|
1187 |
-
|
1188 |
-
|
1189 |
-
|
1190 |
-
|
1191 |
-
|
1192 |
-
|
1193 |
-
|
1194 |
-
|
1195 |
-
|
1196 |
-
|
1197 |
-
|
1198 |
-
|
1199 |
-
|
1200 |
-
|
1201 |
-
|
1202 |
-
|
|
|
|
|
|
|
1203 |
}
|
|
|
|
|
1204 |
}
|
1205 |
|
|
|
1206 |
/**
|
1207 |
* Create product group and product, store fb-specific info
|
1208 |
**/
|
@@ -1232,10 +1271,6 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1232 |
'retailer_id' => $retailer_id,
|
1233 |
);
|
1234 |
|
1235 |
-
// Default visibility on create = published
|
1236 |
-
$woo_product->fb_visibility = true;
|
1237 |
-
update_post_meta( $woo_product->get_id(), Products::VISIBILITY_META_KEY, true );
|
1238 |
-
|
1239 |
if ( $variants ) {
|
1240 |
$product_group_data['variants'] =
|
1241 |
$woo_product->prepare_variants_for_group();
|
@@ -1254,7 +1289,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1254 |
if ( $create_product_group_result ) {
|
1255 |
$decode_result = WC_Facebookcommerce_Utils::decode_json( $create_product_group_result['body'] );
|
1256 |
$fb_product_group_id = $decode_result->id;
|
1257 |
-
|
1258 |
update_post_meta(
|
1259 |
$woo_product->get_id(),
|
1260 |
self::FB_PRODUCT_GROUP_ID,
|
@@ -1274,15 +1309,12 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1274 |
}
|
1275 |
|
1276 |
function create_product_item( $woo_product, $retailer_id, $product_group_id ) {
|
1277 |
-
|
1278 |
-
$woo_product->fb_visibility = true;
|
1279 |
$product_data = $woo_product->prepare_product( $retailer_id );
|
1280 |
if ( ! $product_data['price'] ) {
|
1281 |
return 0;
|
1282 |
}
|
1283 |
|
1284 |
-
update_post_meta( $woo_product->get_id(), Products::VISIBILITY_META_KEY, true );
|
1285 |
-
|
1286 |
$product_result = $this->check_api_result(
|
1287 |
$this->fbgraph->create_product_item(
|
1288 |
$product_group_id,
|
@@ -1398,205 +1430,23 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1398 |
* Saves settings via AJAX (to preserve window context for onboarding).
|
1399 |
*
|
1400 |
* @internal
|
|
|
|
|
1401 |
*/
|
1402 |
public function ajax_save_fb_settings() {
|
1403 |
|
1404 |
-
|
1405 |
-
|
1406 |
-
|
1407 |
-
if ( ! isset( $_REQUEST['facebook_for_woocommerce'] ) ) {
|
1408 |
-
// This is not a request from our plugin,
|
1409 |
-
// some other handler or plugin probably
|
1410 |
-
// wants to handle it and wp_die() after.
|
1411 |
-
return;
|
1412 |
-
}
|
1413 |
-
|
1414 |
-
\WC_Facebookcommerce_Utils::log( 'Saving settings via AJAX' );
|
1415 |
-
|
1416 |
-
// listen for a feed migrated event for FBE 1.5
|
1417 |
-
if ( isset( $_REQUEST['feed_migrated'] ) ) {
|
1418 |
-
|
1419 |
-
$this->set_feed_migrated( wc_string_to_bool( $_REQUEST['feed_migrated'] ) );
|
1420 |
-
|
1421 |
-
// don't save anything else if already connected
|
1422 |
-
if ( $this->get_external_merchant_settings_id() ) {
|
1423 |
-
wp_send_json_success();
|
1424 |
-
}
|
1425 |
-
}
|
1426 |
|
1427 |
-
|
|
|
|
|
|
|
|
|
|
|
1428 |
|
1429 |
-
|
1430 |
-
|
1431 |
-
if ( ctype_alnum( $api_key ) ) {
|
1432 |
-
$this->update_page_access_token( $api_key );
|
1433 |
-
}
|
1434 |
-
}
|
1435 |
-
|
1436 |
-
if ( isset( $_REQUEST['external_merchant_settings_id'] ) ) {
|
1437 |
-
|
1438 |
-
$external_merchant_settings_id = sanitize_text_field( wp_unslash( $_REQUEST['external_merchant_settings_id'] ) );
|
1439 |
-
|
1440 |
-
if ( is_numeric( $external_merchant_settings_id ) ) {
|
1441 |
-
$this->update_external_merchant_settings_id( $external_merchant_settings_id );
|
1442 |
-
}
|
1443 |
-
}
|
1444 |
-
|
1445 |
-
if ( isset( $_REQUEST['product_catalog_id'] ) ) {
|
1446 |
-
|
1447 |
-
$product_catalog_id = sanitize_text_field( wp_unslash( $_REQUEST['product_catalog_id'] ) );
|
1448 |
-
|
1449 |
-
if ( ctype_digit( $product_catalog_id ) ) {
|
1450 |
-
|
1451 |
-
if ( ! empty( $this->get_product_catalog_id() ) && $_REQUEST['product_catalog_id'] !== $this->get_product_catalog_id() ) {
|
1452 |
-
$this->reset_all_products();
|
1453 |
-
}
|
1454 |
-
|
1455 |
-
$this->update_product_catalog_id( sanitize_text_field( wp_unslash( $_REQUEST['product_catalog_id'] ) ) );
|
1456 |
-
}
|
1457 |
-
}
|
1458 |
-
|
1459 |
-
if ( isset( $_REQUEST['pixel_id'] ) ) {
|
1460 |
-
|
1461 |
-
$pixel_id = sanitize_text_field( wp_unslash( $_REQUEST['pixel_id'] ) );
|
1462 |
-
|
1463 |
-
if ( ctype_digit( $pixel_id ) ) {
|
1464 |
-
|
1465 |
-
// to prevent race conditions with pixel-only settings, only save a pixel if we already have an access token
|
1466 |
-
if ( $this->get_external_merchant_settings_id() ) {
|
1467 |
-
|
1468 |
-
if ( $this->get_facebook_pixel_id() !== $pixel_id ) {
|
1469 |
-
$this->update_pixel_install_time( time() );
|
1470 |
-
}
|
1471 |
-
|
1472 |
-
$this->settings[ self::SETTING_FACEBOOK_PIXEL_ID ] = $pixel_id;
|
1473 |
-
|
1474 |
-
} else {
|
1475 |
-
|
1476 |
-
WC_Facebookcommerce_Utils::log( 'Got pixel-only settings, doing nothing' );
|
1477 |
-
|
1478 |
-
wp_send_json_error();
|
1479 |
-
}
|
1480 |
-
}
|
1481 |
-
}
|
1482 |
-
|
1483 |
-
if ( isset( $_REQUEST['pixel_use_pii'] ) ) {
|
1484 |
-
$this->settings[ self::SETTING_ENABLE_ADVANCED_MATCHING ] = wc_bool_to_string( wc_clean( wp_unslash( $_REQUEST['pixel_use_pii'] ) ) );
|
1485 |
-
}
|
1486 |
-
|
1487 |
-
if ( isset( $_REQUEST['page_id'] ) ) {
|
1488 |
-
|
1489 |
-
$page_id = sanitize_text_field( wp_unslash( $_REQUEST['page_id'] ) );
|
1490 |
-
|
1491 |
-
if ( ctype_digit( $page_id ) ) {
|
1492 |
-
$this->settings[ self::SETTING_FACEBOOK_PAGE_ID ] = $page_id;
|
1493 |
-
}
|
1494 |
-
}
|
1495 |
-
|
1496 |
-
if ( isset( $_REQUEST['is_messenger_chat_plugin_enabled'] ) ) {
|
1497 |
-
$this->settings[ self::SETTING_ENABLE_MESSENGER ] = wc_bool_to_string( wc_clean( wp_unslash( $_REQUEST['is_messenger_chat_plugin_enabled'] ) ) );
|
1498 |
-
}
|
1499 |
-
|
1500 |
-
if ( isset( $_REQUEST['facebook_jssdk_version'] ) ) {
|
1501 |
-
$this->update_js_sdk_version( sanitize_text_field( wp_unslash( $_REQUEST['facebook_jssdk_version'] ) ) );
|
1502 |
-
}
|
1503 |
-
|
1504 |
-
if ( ! empty( $_REQUEST['msger_chat_customization_greeting_text_code'] ) ) {
|
1505 |
-
$this->settings[ self::SETTING_MESSENGER_GREETING ] = sanitize_text_field( wp_unslash( $_REQUEST['msger_chat_customization_greeting_text_code'] ) );
|
1506 |
-
}
|
1507 |
-
|
1508 |
-
if ( isset( $_REQUEST['msger_chat_customization_locale'] ) ) {
|
1509 |
-
$this->settings[ self::SETTING_MESSENGER_LOCALE ] = sanitize_text_field( wp_unslash( $_REQUEST['msger_chat_customization_locale'] ) );
|
1510 |
-
}
|
1511 |
-
|
1512 |
-
if ( ! empty( $_REQUEST['msger_chat_customization_theme_color_code'] ) ) {
|
1513 |
-
$this->settings[ self::SETTING_MESSENGER_COLOR_HEX ] = sanitize_hex_color( wp_unslash( $_REQUEST['msger_chat_customization_theme_color_code'] ) );
|
1514 |
-
}
|
1515 |
-
|
1516 |
-
/** This filter is defined by WooCommerce in includes/abstracts/abstract-wc-settings-api.php */
|
1517 |
-
update_option( $this->get_option_key(), apply_filters( 'woocommerce_settings_api_sanitized_fields_' . $this->id, $this->settings ) );
|
1518 |
-
|
1519 |
-
WC_Facebookcommerce_Utils::log( 'Settings saved!' );
|
1520 |
-
|
1521 |
-
wp_send_json_success();
|
1522 |
-
}
|
1523 |
-
|
1524 |
-
/**
|
1525 |
-
* Delete all settings via AJAX
|
1526 |
-
**/
|
1527 |
-
function ajax_delete_fb_settings() {
|
1528 |
-
check_ajax_referer( 'wc_facebook_settings_jsx' );
|
1529 |
-
if ( ! WC_Facebookcommerce_Utils::check_woo_ajax_permissions( 'delete settings', false ) ) {
|
1530 |
-
return;
|
1531 |
-
}
|
1532 |
-
|
1533 |
-
// Do not allow reset in the middle of product sync
|
1534 |
-
$currently_syncing = get_transient( self::FB_SYNC_IN_PROGRESS );
|
1535 |
-
if ( $currently_syncing ) {
|
1536 |
-
wp_send_json(
|
1537 |
-
'A Facebook product sync is currently in progress.
|
1538 |
-
Deleting settings during product sync may cause errors.'
|
1539 |
-
);
|
1540 |
-
return;
|
1541 |
-
}
|
1542 |
-
|
1543 |
-
if ( isset( $_REQUEST ) ) {
|
1544 |
-
$ems = $this->get_external_merchant_settings_id();
|
1545 |
-
if ( $ems ) {
|
1546 |
-
WC_Facebookcommerce_Utils::fblog(
|
1547 |
-
'Deleted all settings!',
|
1548 |
-
array(),
|
1549 |
-
false,
|
1550 |
-
$ems
|
1551 |
-
);
|
1552 |
-
}
|
1553 |
-
|
1554 |
-
$this->init_settings();
|
1555 |
-
$this->update_page_access_token( '' );
|
1556 |
-
$this->update_product_catalog_id( '' );
|
1557 |
-
$this->set_feed_migrated( false );
|
1558 |
-
|
1559 |
-
$this->settings[ self::SETTING_FACEBOOK_PIXEL_ID ] = '';
|
1560 |
-
$this->settings[ self::SETTING_ENABLE_ADVANCED_MATCHING ] = 'no';
|
1561 |
-
$this->settings[ self::SETTING_FACEBOOK_PAGE_ID ] = '';
|
1562 |
-
|
1563 |
-
unset( $this->settings[ self::SETTING_ENABLE_MESSENGER ] );
|
1564 |
-
unset( $this->settings[ self::SETTING_MESSENGER_GREETING ] );
|
1565 |
-
unset( $this->settings[ self::SETTING_MESSENGER_LOCALE ] );
|
1566 |
-
unset( $this->settings[ self::SETTING_MESSENGER_COLOR_HEX ] );
|
1567 |
-
|
1568 |
-
$this->update_external_merchant_settings_id( '' );
|
1569 |
-
$this->update_pixel_install_time( 0 );
|
1570 |
-
$this->update_feed_id( '' );
|
1571 |
-
$this->update_upload_id( '' );
|
1572 |
-
$this->settings['upload_end_time'] = '';
|
1573 |
-
|
1574 |
-
WC_Facebookcommerce_Pixel::set_pixel_id( 0 );
|
1575 |
-
|
1576 |
-
update_option(
|
1577 |
-
$this->get_option_key(),
|
1578 |
-
apply_filters(
|
1579 |
-
'woocommerce_settings_api_sanitized_fields_' . $this->id,
|
1580 |
-
$this->settings
|
1581 |
-
)
|
1582 |
-
);
|
1583 |
-
|
1584 |
-
// Clean up old messages
|
1585 |
-
delete_transient( 'facebook_plugin_api_error' );
|
1586 |
-
delete_transient( 'facebook_plugin_api_success' );
|
1587 |
-
delete_transient( 'facebook_plugin_api_warning' );
|
1588 |
-
delete_transient( 'facebook_plugin_api_info' );
|
1589 |
-
delete_transient( 'facebook_plugin_api_sticky' );
|
1590 |
-
|
1591 |
-
$this->reset_all_products();
|
1592 |
-
|
1593 |
-
WC_Facebookcommerce_Utils::log( 'Settings deleted' );
|
1594 |
-
echo 'Settings Deleted';
|
1595 |
-
|
1596 |
-
}
|
1597 |
-
|
1598 |
-
wp_die();
|
1599 |
-
}
|
1600 |
|
1601 |
/**
|
1602 |
* Checks the feed upload status (FBE v1.0).
|
@@ -1624,7 +1474,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1624 |
|
1625 |
check_ajax_referer( 'wc_facebook_settings_jsx' );
|
1626 |
|
1627 |
-
if ( $this->
|
1628 |
|
1629 |
$response = [
|
1630 |
'connected' => true,
|
@@ -1870,7 +1720,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1870 |
sprintf(
|
1871 |
'Products may be out of Sync with Facebook due to your recent ' . $action_name . '.' .
|
1872 |
' <a href="%s&fb_force_resync=true&remove_sticky=true">Re-Sync them with FB.</a>',
|
1873 |
-
|
1874 |
)
|
1875 |
);
|
1876 |
}
|
@@ -1907,45 +1757,10 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1907 |
public function checks() {
|
1908 |
|
1909 |
// TODO improve this by checking the settings page with Framework method and ensure error notices are displayed under the Integration sections {FN 2020-01-30}
|
1910 |
-
if ( isset( $_GET['page']
|
1911 |
$this->display_errors();
|
1912 |
}
|
1913 |
|
1914 |
-
// check required fields
|
1915 |
-
if ( ! $this->is_configured() ) {
|
1916 |
-
|
1917 |
-
$message = sprintf(
|
1918 |
-
/* translators: Placeholders %1$s - opening strong HTML tag, %2$s - closing strong HTML tag, %3$s - opening link HTML tag, %4$s - closing link HTML tag */
|
1919 |
-
esc_html__(
|
1920 |
-
'%1$sFacebook for WooCommerce is almost ready.%2$s To complete your configuration, %3$scomplete the setup steps%4$s.',
|
1921 |
-
'facebook-for-woocommerce'
|
1922 |
-
),
|
1923 |
-
'<strong>',
|
1924 |
-
'</strong>',
|
1925 |
-
'<a href="' . esc_url( WOOCOMMERCE_FACEBOOK_PLUGIN_SETTINGS_URL ) . '">',
|
1926 |
-
'</a>'
|
1927 |
-
);
|
1928 |
-
|
1929 |
-
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
1930 |
-
echo $this->get_message_html( $message, 'info' );
|
1931 |
-
}
|
1932 |
-
|
1933 |
-
// WooCommerce 2.x upgrade nag
|
1934 |
-
if ( $this->get_page_access_token() && ( ! isset( $this->background_processor ) ) ) {
|
1935 |
-
|
1936 |
-
$message = sprintf(
|
1937 |
-
/* translators: Placeholders %1$s - WooCommerce version */
|
1938 |
-
esc_html__(
|
1939 |
-
'Facebook product sync may not work correctly in WooCommerce version %1$s. Please upgrade to WooCommerce 3.',
|
1940 |
-
'facebook-for-woocommerce'
|
1941 |
-
),
|
1942 |
-
esc_html( WC()->version )
|
1943 |
-
);
|
1944 |
-
|
1945 |
-
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
1946 |
-
echo $this->get_message_html( $message, 'warning' );
|
1947 |
-
}
|
1948 |
-
|
1949 |
$this->maybe_display_facebook_api_messages();
|
1950 |
}
|
1951 |
|
@@ -1982,7 +1797,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1982 |
'description' => strip_tags( $product_data['description'] ),
|
1983 |
'id' => $product_data['retailer_id'],
|
1984 |
'image_link' => $product_data['image_url'],
|
1985 |
-
'brand' =>
|
1986 |
'link' => $product_data['url'],
|
1987 |
'price' => $product_data['price'] . ' ' . get_woocommerce_currency(),
|
1988 |
];
|
@@ -2187,11 +2002,11 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
2187 |
throw new Framework\SV_WC_Plugin_Exception( __( 'Product sync is disabled.', 'facebook-for-woocommerce' ) );
|
2188 |
}
|
2189 |
|
2190 |
-
if ( ! $this->
|
2191 |
|
2192 |
-
WC_Facebookcommerce_Utils::log( sprintf( '
|
2193 |
|
2194 |
-
throw new Framework\SV_WC_Plugin_Exception( __( 'The
|
2195 |
}
|
2196 |
|
2197 |
$this->remove_resync_message();
|
@@ -2229,12 +2044,6 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
2229 |
throw new Framework\SV_WC_Plugin_Exception( __( "We've detected that your Facebook Product Catalog is no longer valid. This may happen if it was deleted, but could also be a temporary error. If the error persists, please click Manage connection > Advanced Options > Remove and setup the plugin again.", 'facebook-for-woocommerce' ) );
|
2230 |
}
|
2231 |
|
2232 |
-
// Cache the cart URL to display a warning in case it changes later
|
2233 |
-
$cart_url = get_option( self::FB_CART_URL );
|
2234 |
-
if ( $cart_url != wc_get_cart_url() ) {
|
2235 |
-
update_option( self::FB_CART_URL, wc_get_cart_url() );
|
2236 |
-
}
|
2237 |
-
|
2238 |
// Get all published posts. First unsynced then already-synced.
|
2239 |
$post_ids_new = WC_Facebookcommerce_Utils::get_wp_posts(
|
2240 |
self::FB_PRODUCT_GROUP_ID,
|
@@ -2356,902 +2165,135 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
2356 |
* @since 1.10.2
|
2357 |
*
|
2358 |
* @throws Framework\SV_WC_Plugin_Exception
|
2359 |
-
* @return bool
|
2360 |
-
*/
|
2361 |
-
public function sync_facebook_products_using_feed() {
|
2362 |
-
|
2363 |
-
if ( ! $this->is_product_sync_enabled() ) {
|
2364 |
-
WC_Facebookcommerce_Utils::log( 'Sync to Facebook is disabled' );
|
2365 |
-
|
2366 |
-
throw new Framework\SV_WC_Plugin_Exception( __( 'Product sync is disabled.', 'facebook-for-woocommerce' ) );
|
2367 |
-
}
|
2368 |
-
|
2369 |
-
if ( ! $this->get_page_access_token() || ! $this->get_product_catalog_id() ) {
|
2370 |
-
|
2371 |
-
WC_Facebookcommerce_Utils::log( sprintf( 'No API key or Catalog ID: %s and %s', $this->get_page_access_token(), $this->get_product_catalog_id() ) );
|
2372 |
-
|
2373 |
-
throw new Framework\SV_WC_Plugin_Exception( __( 'The page access token or product catalog ID are missing.', 'facebook-for-woocommerce' ) );
|
2374 |
-
}
|
2375 |
-
|
2376 |
-
$this->remove_resync_message();
|
2377 |
-
|
2378 |
-
if ( ! $this->fbgraph->is_product_catalog_valid( $this->get_product_catalog_id() ) ) {
|
2379 |
-
|
2380 |
-
WC_Facebookcommerce_Utils::log( 'Not syncing, invalid product catalog!' );
|
2381 |
-
WC_Facebookcommerce_Utils::fblog(
|
2382 |
-
'Tried to sync with an invalid product catalog!',
|
2383 |
-
array(),
|
2384 |
-
true
|
2385 |
-
);
|
2386 |
-
|
2387 |
-
throw new Framework\SV_WC_Plugin_Exception( __( "We've detected that your Facebook Product Catalog is no longer valid. This may happen if it was deleted, but could also be a temporary error. If the error persists, please click Manage connection > Advanced Options > Remove and setup the plugin again.", 'facebook-for-woocommerce' ) );
|
2388 |
-
}
|
2389 |
-
|
2390 |
-
// Cache the cart URL to display a warning in case it changes later
|
2391 |
-
$cart_url = get_option( self::FB_CART_URL );
|
2392 |
-
if ( $cart_url != wc_get_cart_url() ) {
|
2393 |
-
update_option( self::FB_CART_URL, wc_get_cart_url() );
|
2394 |
-
}
|
2395 |
-
|
2396 |
-
if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) {
|
2397 |
-
include_once 'includes/fbproductfeed.php';
|
2398 |
-
}
|
2399 |
-
if ( $this->test_mode ) {
|
2400 |
-
$this->fbproductfeed = new WC_Facebook_Product_Feed_Test_Mock(
|
2401 |
-
$this->get_product_catalog_id(),
|
2402 |
-
$this->fbgraph,
|
2403 |
-
$this->get_feed_id()
|
2404 |
-
);
|
2405 |
-
} else {
|
2406 |
-
$this->fbproductfeed = new WC_Facebook_Product_Feed(
|
2407 |
-
$this->get_product_catalog_id(),
|
2408 |
-
$this->fbgraph,
|
2409 |
-
$this->get_feed_id()
|
2410 |
-
);
|
2411 |
-
}
|
2412 |
-
|
2413 |
-
if ( ! $this->fbproductfeed->sync_all_products_using_feed() ) {
|
2414 |
-
|
2415 |
-
WC_Facebookcommerce_Utils::fblog( 'Sync all products using feed, curl failed', [], true );
|
2416 |
-
|
2417 |
-
throw new Framework\SV_WC_Plugin_Exception( __( "We couldn't create the feed or upload the product information.", 'facebook-for-woocommerce' ) );
|
2418 |
-
}
|
2419 |
-
|
2420 |
-
$this->update_feed_id( $this->fbproductfeed->feed_id );
|
2421 |
-
$this->update_upload_id( $this->fbproductfeed->upload_id );
|
2422 |
-
|
2423 |
-
update_option(
|
2424 |
-
$this->get_option_key(),
|
2425 |
-
apply_filters( 'woocommerce_settings_api_sanitized_fields_' . $this->id, $this->settings )
|
2426 |
-
);
|
2427 |
-
|
2428 |
-
wp_reset_postdata();
|
2429 |
-
|
2430 |
-
return true;
|
2431 |
-
}
|
2432 |
-
|
2433 |
-
|
2434 |
-
/**
|
2435 |
-
* Syncs Facebook products using a Feed.
|
2436 |
-
*
|
2437 |
-
* TODO: deprecate this methid in 1.11.0 or newer {WV 2020-03-12}
|
2438 |
-
*
|
2439 |
-
* @see https://developers.facebook.com/docs/marketing-api/fbe/fbe1/guides/feed-approach
|
2440 |
-
*
|
2441 |
-
* @return bool
|
2442 |
-
*/
|
2443 |
-
public function sync_all_fb_products_using_feed() {
|
2444 |
-
|
2445 |
-
try {
|
2446 |
-
$sync_started = $this->sync_facebook_products_using_feed();
|
2447 |
-
} catch ( Framework\SV_WC_Plugin_Exception $e ) {
|
2448 |
-
$sync_started = false;
|
2449 |
-
}
|
2450 |
-
|
2451 |
-
return $sync_started;
|
2452 |
-
}
|
2453 |
-
|
2454 |
-
|
2455 |
-
/**
|
2456 |
-
* Toggles product visibility via AJAX.
|
2457 |
-
*
|
2458 |
-
* @internal
|
2459 |
-
* @deprecated since 1.10.0
|
2460 |
-
**/
|
2461 |
-
public function ajax_fb_toggle_visibility() {
|
2462 |
-
|
2463 |
-
wc_deprecated_function( __METHOD__, '1.10.0' );
|
2464 |
-
}
|
2465 |
-
|
2466 |
-
|
2467 |
-
/**
|
2468 |
-
* Initializes the settings form fields.
|
2469 |
-
*
|
2470 |
-
* @since 1.0.0
|
2471 |
-
*
|
2472 |
-
* @internal
|
2473 |
-
*/
|
2474 |
-
public function init_form_fields() {
|
2475 |
-
|
2476 |
-
$term_query = new \WP_Term_Query( [
|
2477 |
-
'taxonomy' => 'product_cat',
|
2478 |
-
'hide_empty' => false,
|
2479 |
-
'fields' => 'id=>name',
|
2480 |
-
] );
|
2481 |
-
|
2482 |
-
$product_categories = $term_query->get_terms();
|
2483 |
-
|
2484 |
-
$term_query = new \WP_Term_Query( [
|
2485 |
-
'taxonomy' => 'product_tag',
|
2486 |
-
'hide_empty' => false,
|
2487 |
-
'hierarchical' => false,
|
2488 |
-
'fields' => 'id=>name',
|
2489 |
-
] );
|
2490 |
-
|
2491 |
-
$product_tags = $term_query->get_terms();
|
2492 |
-
|
2493 |
-
$messenger_locales = \WC_Facebookcommerce_MessengerChat::get_supported_locales();
|
2494 |
-
|
2495 |
-
// tries matching with WordPress locale, otherwise English, otherwise first available language
|
2496 |
-
if ( isset( $messenger_locales[ get_locale() ] ) ) {
|
2497 |
-
$default_locale = get_locale();
|
2498 |
-
} elseif ( isset( $messenger_locales[ 'en_US' ] ) ) {
|
2499 |
-
$default_locale = 'en_US';
|
2500 |
-
} elseif ( ! empty( $messenger_locales ) && is_array( $messenger_locales ) ) {
|
2501 |
-
$default_locale = key( $messenger_locales );
|
2502 |
-
} else {
|
2503 |
-
// fallback to English in case of invalid/empty filtered list of languages
|
2504 |
-
$messenger_locales = [ 'en_US' => _x( 'English (United States)', 'language', 'facebook-for-woocommerce' ) ];
|
2505 |
-
$default_locale = 'en_US';
|
2506 |
-
}
|
2507 |
-
|
2508 |
-
$default_messenger_greeting = __( "Hi! We're here to answer any questions you may have.", 'facebook-for-woocommerce' );
|
2509 |
-
$default_messenger_color = '#0084ff';
|
2510 |
-
|
2511 |
-
$form_fields = [
|
2512 |
-
|
2513 |
-
/** @see \WC_Facebookcommerce_Integration::generate_manage_connection_title_html() */
|
2514 |
-
[
|
2515 |
-
'type' => 'manage_connection_title',
|
2516 |
-
],
|
2517 |
-
|
2518 |
-
/** @see \WC_Facebookcommerce_Integration::generate_facebook_page_name_html() */
|
2519 |
-
self::SETTING_FACEBOOK_PAGE_ID => [
|
2520 |
-
'type' => 'facebook_page_name',
|
2521 |
-
'default' => '',
|
2522 |
-
],
|
2523 |
-
|
2524 |
-
/** @see \WC_Facebookcommerce_Integration::generate_facebook_pixel_id_html() */
|
2525 |
-
self::SETTING_FACEBOOK_PIXEL_ID => [
|
2526 |
-
'type' => 'facebook_pixel_id',
|
2527 |
-
'default' => '',
|
2528 |
-
],
|
2529 |
-
|
2530 |
-
self::SETTING_ENABLE_ADVANCED_MATCHING => [
|
2531 |
-
'title' => __( 'Use Advanced Matching', 'facebook-for-woocommerce' ),
|
2532 |
-
'description' => sprintf(
|
2533 |
-
/* translators: Placeholders: %1$s - opening <a> HTML link tag, %2$s - closing </a> HTML link tag */
|
2534 |
-
__( 'Improve the ability to match site visitors to people on Facebook by passing additional site visitor information (such as email address or phone number). %1$sLearn more%2$s.', 'facebook-for-woocommerce' ),
|
2535 |
-
'<a href="https://developers.facebook.com/docs/facebook-pixel/advanced/advanced-matching" target="_blank">',
|
2536 |
-
'</a>'
|
2537 |
-
),
|
2538 |
-
'type' => 'checkbox',
|
2539 |
-
'label' => ' ',
|
2540 |
-
'default' => 'yes',
|
2541 |
-
],
|
2542 |
-
|
2543 |
-
/** @see \WC_Facebookcommerce_Integration::generate_create_ad_html() */
|
2544 |
-
[
|
2545 |
-
'type' => 'create_ad',
|
2546 |
-
],
|
2547 |
-
|
2548 |
-
/** @see \WC_Facebookcommerce_Integration::generate_product_sync_title_html() */
|
2549 |
-
[
|
2550 |
-
'type' => 'product_sync_title',
|
2551 |
-
'title' => __( 'Product sync', 'facebook-for-woocommerce' ),
|
2552 |
-
],
|
2553 |
-
|
2554 |
-
self::SETTING_ENABLE_PRODUCT_SYNC => [
|
2555 |
-
'title' => __( 'Enable product sync', 'facebook-for-woocommerce' ),
|
2556 |
-
'type' => 'checkbox',
|
2557 |
-
'class' => 'product-sync-field toggle-fields-group',
|
2558 |
-
'label' => ' ',
|
2559 |
-
'default' => 'yes',
|
2560 |
-
],
|
2561 |
-
|
2562 |
-
self::SETTING_EXCLUDED_PRODUCT_CATEGORY_IDS => [
|
2563 |
-
'title' => __( 'Exclude categories from sync', 'facebook-for-woocommerce' ),
|
2564 |
-
'type' => 'multiselect',
|
2565 |
-
'class' => 'wc-enhanced-select product-sync-field',
|
2566 |
-
'css' => 'min-width: 300px;',
|
2567 |
-
'desc_tip' => __( 'Products in one or more of these categories will not sync to Facebook.', 'facebook-for-woocommerce' ),
|
2568 |
-
'default' => [],
|
2569 |
-
'options' => is_array( $product_categories ) ? $product_categories : [],
|
2570 |
-
'custom_attributes' => [
|
2571 |
-
'data-placeholder' => __( 'Search for a product category…', 'facebook-for-woocommerce' ),
|
2572 |
-
],
|
2573 |
-
],
|
2574 |
-
|
2575 |
-
self::SETTING_EXCLUDED_PRODUCT_TAG_IDS => [
|
2576 |
-
'title' => __( 'Exclude tags from sync', 'facebook-for-woocommerce' ),
|
2577 |
-
'type' => 'multiselect',
|
2578 |
-
'class' => 'wc-enhanced-select product-sync-field',
|
2579 |
-
'css' => 'min-width: 300px;',
|
2580 |
-
'desc_tip' => __( 'Products with one or more of these tags will not sync to Facebook.', 'facebook-for-woocommerce' ),
|
2581 |
-
'default' => [],
|
2582 |
-
'options' => is_array( $product_tags ) ? $product_tags : [],
|
2583 |
-
'custom_attributes' => [
|
2584 |
-
'data-placeholder' => __( 'Search for a product tag…', 'facebook-for-woocommerce' ),
|
2585 |
-
],
|
2586 |
-
],
|
2587 |
-
|
2588 |
-
self::SETTING_PRODUCT_DESCRIPTION_MODE => [
|
2589 |
-
'title' => __( 'Product description sync', 'facebook-for-woocommerce' ),
|
2590 |
-
'type' => 'select',
|
2591 |
-
'class' => 'product-sync-field',
|
2592 |
-
'desc_tip' => __( 'Choose which product description to display in the Facebook catalog.', 'facebook-for-woocommerce' ),
|
2593 |
-
'default' => self::PRODUCT_DESCRIPTION_MODE_STANDARD,
|
2594 |
-
'options' => [
|
2595 |
-
self::PRODUCT_DESCRIPTION_MODE_STANDARD => __( 'Standard description', 'facebook-for-woocommerce' ),
|
2596 |
-
self::PRODUCT_DESCRIPTION_MODE_SHORT => __( 'Short description', 'facebook-for-woocommerce' ),
|
2597 |
-
],
|
2598 |
-
],
|
2599 |
-
|
2600 |
-
/** @see \WC_Facebookcommerce_Integration::generate_resync_schedule_html() */
|
2601 |
-
/** @see \WC_Facebookcommerce_Integration::validate_resync_schedule_field() */
|
2602 |
-
//self::SETTING_SCHEDULED_RESYNC_OFFSET => [
|
2603 |
-
// 'title' => __( 'Force daily resync at', 'facebook-for-woocommerce' ),
|
2604 |
-
// 'class' => 'product-sync-field resync-schedule-fieldset',
|
2605 |
-
// 'type' => 'resync_schedule',
|
2606 |
-
//],
|
2607 |
-
|
2608 |
-
[
|
2609 |
-
'title' => __( 'Messenger', 'facebook-for-woocommerce' ),
|
2610 |
-
'type' => 'title',
|
2611 |
-
],
|
2612 |
-
|
2613 |
-
self::SETTING_ENABLE_MESSENGER => [
|
2614 |
-
'title' => __( 'Enable Messenger', 'facebook-for-woocommerce' ),
|
2615 |
-
'type' => 'checkbox',
|
2616 |
-
'class' => 'messenger-field toggle-fields-group',
|
2617 |
-
'label' => ' ',
|
2618 |
-
'desc_tip' => __( 'Enable and customize Facebook Messenger on your store.', 'facebook-for-woocommerce' ),
|
2619 |
-
'default' => 'no',
|
2620 |
-
],
|
2621 |
-
|
2622 |
-
self::SETTING_MESSENGER_LOCALE => [
|
2623 |
-
'title' => __( 'Language', 'facebook-for-woocommerce' ),
|
2624 |
-
'type' => 'select',
|
2625 |
-
'class' => 'wc-enhanced-select messenger-field',
|
2626 |
-
'default' => $default_locale,
|
2627 |
-
'options' => $messenger_locales,
|
2628 |
-
'custom_attributes' => [
|
2629 |
-
'data-default' => $default_locale,
|
2630 |
-
],
|
2631 |
-
],
|
2632 |
-
|
2633 |
-
/** @see \WC_Facebookcommerce_Integration::generate_messenger_greeting_html() */
|
2634 |
-
/** @see \WC_Facebookcommerce_Integration::validate_messenger_greeting_field() */
|
2635 |
-
self::SETTING_MESSENGER_GREETING => [
|
2636 |
-
'title' => __( 'Greeting', 'facebook-for-woocommerce' ),
|
2637 |
-
'type' => 'messenger_greeting',
|
2638 |
-
'class' => 'messenger-field',
|
2639 |
-
'default' => $default_messenger_greeting,
|
2640 |
-
'css' => 'max-width: 400px; margin-bottom: 10px',
|
2641 |
-
'custom_attributes' => [
|
2642 |
-
'maxlength' => $this->get_messenger_greeting_max_characters(),
|
2643 |
-
'data-default' => $default_messenger_greeting,
|
2644 |
-
],
|
2645 |
-
],
|
2646 |
-
|
2647 |
-
self::SETTING_MESSENGER_COLOR_HEX => [
|
2648 |
-
'title' => __( 'Colors', 'facebook-for-woocommerce' ),
|
2649 |
-
'type' => 'color',
|
2650 |
-
'class' => 'messenger-field',
|
2651 |
-
'default' => $default_messenger_color,
|
2652 |
-
'css' => 'width: 6em;',
|
2653 |
-
'custom_attributes' => [
|
2654 |
-
'data-default' => $default_messenger_color,
|
2655 |
-
],
|
2656 |
-
],
|
2657 |
-
|
2658 |
-
[
|
2659 |
-
'title' => __( 'Debug', 'facebook-for-woocommerce' ),
|
2660 |
-
'type' => 'title',
|
2661 |
-
],
|
2662 |
-
|
2663 |
-
self::SETTING_ENABLE_DEBUG_MODE => [
|
2664 |
-
'title' => __( 'Enable debug mode', 'facebook-for-woocommerce' ),
|
2665 |
-
'type' => 'checkbox',
|
2666 |
-
'label' => __( 'Log plugin events for debugging', 'facebook-for-woocommerce' ),
|
2667 |
-
'desc_tip' => __( 'Only enable this if you are experiencing problems with the plugin.', 'facebook-for-woocommerce' ),
|
2668 |
-
'default' => 'no',
|
2669 |
-
],
|
2670 |
-
|
2671 |
-
];
|
2672 |
-
|
2673 |
-
$this->form_fields = $form_fields;
|
2674 |
-
}
|
2675 |
-
|
2676 |
-
|
2677 |
-
/**
|
2678 |
-
* Gets the "Manage connection" field HTML.
|
2679 |
-
*
|
2680 |
-
* @see \WC_Settings_API::generate_title_html()
|
2681 |
-
*
|
2682 |
-
* @since 1.10.0
|
2683 |
-
*
|
2684 |
-
* @param string|int $key field key or index
|
2685 |
-
* @param array $args associative array of field arguments
|
2686 |
-
* @return string HTML
|
2687 |
-
*/
|
2688 |
-
protected function generate_manage_connection_title_html( $key, array $args = [] ) {
|
2689 |
-
|
2690 |
-
$key = $this->get_field_key( $key );
|
2691 |
-
|
2692 |
-
ob_start();
|
2693 |
-
|
2694 |
-
?>
|
2695 |
-
</table>
|
2696 |
-
<h3 class="wc-settings-sub-title" id="<?php echo esc_attr( $key ); ?>">
|
2697 |
-
<?php esc_html_e( 'Connection', 'facebook-for-woocommerce' ); ?>
|
2698 |
-
<a
|
2699 |
-
id="woocommerce-facebook-settings-manage-connection"
|
2700 |
-
class="button"
|
2701 |
-
href="#"
|
2702 |
-
style="vertical-align: middle; margin-left: 20px;"
|
2703 |
-
onclick="facebookConfig();"
|
2704 |
-
><?php esc_html_e( 'Manage connection', 'facebook-for-woocommerce' ); ?></a>
|
2705 |
-
</h3>
|
2706 |
-
<?php // if ( empty( $this->get_page_name() ) ) : ?>
|
2707 |
-
<?php
|
2708 |
-
/**
|
2709 |
-
<div id="connection-message-invalid">
|
2710 |
-
<p style="color: #DC3232;">
|
2711 |
-
<?php esc_html_e( 'Your connection has expired.', 'facebook-for-woocommerce' ); ?>
|
2712 |
-
<strong>
|
2713 |
-
<?php esc_html_e( 'Please click Manage connection > Advanced Options > Update Token to refresh your connection to Facebook.', 'facebook-for-woocommerce' ); ?>
|
2714 |
-
</strong>
|
2715 |
-
</p>
|
2716 |
-
</div>
|
2717 |
-
<div id="connection-message-refresh" style="display: none;">
|
2718 |
-
<p>
|
2719 |
-
<?php esc_html_e( 'Your access token has been updated.', 'facebook-for-woocommerce' ); ?>
|
2720 |
-
<strong>
|
2721 |
-
<?php esc_html_e( 'Please refresh the page.', 'facebook-for-woocommerce' ); ?>
|
2722 |
-
</strong>
|
2723 |
-
</p>
|
2724 |
-
</div>
|
2725 |
-
*/
|
2726 |
-
?>
|
2727 |
-
<?php // endif; ?>
|
2728 |
-
<table class="form-table">
|
2729 |
-
<?php
|
2730 |
-
|
2731 |
-
return ob_get_clean();
|
2732 |
-
}
|
2733 |
-
|
2734 |
-
|
2735 |
-
/**
|
2736 |
-
* Gets the "Facebook page" field HTML.
|
2737 |
-
*
|
2738 |
-
* @see \WC_Settings_API::generate_settings_html()
|
2739 |
-
*
|
2740 |
-
* @since 1.10.0
|
2741 |
-
*
|
2742 |
-
* @param string|int $key field key or index
|
2743 |
-
* @param array $args associative array of field arguments
|
2744 |
-
* @return string HTML
|
2745 |
-
*/
|
2746 |
-
protected function generate_facebook_page_name_html( $key, array $args = [] ) {
|
2747 |
-
|
2748 |
-
$key = $this->get_field_key( $key );
|
2749 |
-
// $page_name = $this->get_page_name();
|
2750 |
-
// $page_url = $this->get_page_url();
|
2751 |
-
|
2752 |
-
ob_start();
|
2753 |
-
|
2754 |
-
/*?>
|
2755 |
-
<tr valign="top">
|
2756 |
-
<th scope="row" class="titledesc">
|
2757 |
-
<?php esc_html_e( 'Facebook page', 'facebook-for-woocommerce' ); ?>
|
2758 |
-
</th>
|
2759 |
-
<td class="forminp">
|
2760 |
-
<?php if ( $page_name ) : ?>
|
2761 |
-
|
2762 |
-
<?php if ( $page_url ) : ?>
|
2763 |
-
|
2764 |
-
<a
|
2765 |
-
href="<?php echo esc_url( $page_url ); ?>"
|
2766 |
-
target="_blank"
|
2767 |
-
style="text-decoration: none;">
|
2768 |
-
<?php echo esc_html( $page_name ); ?>
|
2769 |
-
<span
|
2770 |
-
class="dashicons dashicons-external"
|
2771 |
-
style="margin-right: 8px; vertical-align: bottom;"
|
2772 |
-
></span>
|
2773 |
-
</a>
|
2774 |
-
|
2775 |
-
<?php else : ?>
|
2776 |
-
|
2777 |
-
<?php echo esc_html( $page_name ); ?>
|
2778 |
-
|
2779 |
-
<?php endif; ?>
|
2780 |
-
|
2781 |
-
<?php else : ?>
|
2782 |
-
|
2783 |
-
—
|
2784 |
-
|
2785 |
-
<?php endif;*/ ?>
|
2786 |
-
<input
|
2787 |
-
type="hidden"
|
2788 |
-
name="<?php echo esc_attr( $key ); ?>"
|
2789 |
-
id="<?php echo esc_attr( $key ); ?>"
|
2790 |
-
value="<?php echo esc_attr( $this->get_facebook_page_id() ); ?>"
|
2791 |
-
/>
|
2792 |
-
<?php /*
|
2793 |
-
</td>
|
2794 |
-
</tr>
|
2795 |
-
<?php */
|
2796 |
-
|
2797 |
-
return ob_get_clean();
|
2798 |
-
}
|
2799 |
-
|
2800 |
-
|
2801 |
-
/**
|
2802 |
-
* Gets the "Facebook Pixel" field HTML.
|
2803 |
-
*
|
2804 |
-
* @see \WC_Settings_API::generate_settings_html()
|
2805 |
-
*
|
2806 |
-
* @since 1.10.0
|
2807 |
-
*
|
2808 |
-
* @param string|int $key field key or index
|
2809 |
-
* @param array $args associative array of field arguments
|
2810 |
-
* @return string HTML
|
2811 |
-
*/
|
2812 |
-
protected function generate_facebook_pixel_id_html( $key, array $args = [] ) {
|
2813 |
-
|
2814 |
-
$key = $this->get_field_key( $key );
|
2815 |
-
$pixel_id = $this->get_facebook_pixel_id();
|
2816 |
-
|
2817 |
-
ob_start();
|
2818 |
-
|
2819 |
-
?>
|
2820 |
-
<tr valign="top">
|
2821 |
-
<th scope="row" class="titledesc">
|
2822 |
-
<?php esc_html_e( 'Pixel', 'facebook-for-woocommerce' ); ?>
|
2823 |
-
</th>
|
2824 |
-
<td class="forminp">
|
2825 |
-
<?php if ( $pixel_id ) : ?>
|
2826 |
-
<code style="padding: 4px 8px; color: #333;"><?php echo esc_html( $pixel_id ); ?></code>
|
2827 |
-
<?php else : ?>
|
2828 |
-
—
|
2829 |
-
<?php endif; ?>
|
2830 |
-
<input
|
2831 |
-
type="hidden"
|
2832 |
-
name="<?php echo esc_attr( $key ); ?>"
|
2833 |
-
id="<?php echo esc_attr( $key ); ?>"
|
2834 |
-
value="<?php echo esc_attr( $pixel_id ); ?>"
|
2835 |
-
/>
|
2836 |
-
</td>
|
2837 |
-
</tr>
|
2838 |
-
<?php
|
2839 |
-
|
2840 |
-
return ob_get_clean();
|
2841 |
-
}
|
2842 |
-
|
2843 |
-
|
2844 |
-
/**
|
2845 |
-
* Gets the "Create ad" field HTML.
|
2846 |
-
*
|
2847 |
-
* @see \WC_Settings_API::generate_settings_html()
|
2848 |
-
*
|
2849 |
-
* @since 1.10.0
|
2850 |
-
*
|
2851 |
-
* @param string|int $key field key or index
|
2852 |
-
* @param array $args associative array of field arguments
|
2853 |
-
* @return string HTML
|
2854 |
-
*/
|
2855 |
-
protected function generate_create_ad_html( $key, array $args = [] ) {
|
2856 |
-
|
2857 |
-
$create_ad_url = sprintf( 'https://www.facebook.com/ads/dia/redirect/?settings_id=%s&version=2&entry_point=admin_panel', rawurlencode( $this->get_external_merchant_settings_id() ) );
|
2858 |
-
|
2859 |
-
ob_start();
|
2860 |
-
|
2861 |
-
?>
|
2862 |
-
<tr valign="top">
|
2863 |
-
<th class="forminp" colspan="2">
|
2864 |
-
<a
|
2865 |
-
class="button button-primary"
|
2866 |
-
target="_blank"
|
2867 |
-
href="<?php echo esc_url( $create_ad_url ); ?>"
|
2868 |
-
><?php esc_html_e( 'Create ad', 'facebook-for-woocommerce' ); ?></a>
|
2869 |
-
</th>
|
2870 |
-
</tr>
|
2871 |
-
<?php
|
2872 |
-
|
2873 |
-
return ob_get_clean();
|
2874 |
-
}
|
2875 |
-
|
2876 |
-
|
2877 |
-
/**
|
2878 |
-
* Gets the "Sync products" field HTML.
|
2879 |
-
*
|
2880 |
-
* @see \WC_Settings_API::generate_title_html()
|
2881 |
-
*
|
2882 |
-
* @since 1.10.0
|
2883 |
-
*
|
2884 |
-
* @param string|int $key field key or index
|
2885 |
-
* @param array $args associative array of field arguments
|
2886 |
-
* @return string HTML
|
2887 |
-
*/
|
2888 |
-
protected function generate_product_sync_title_html( $key, array $args = [] ) {
|
2889 |
-
|
2890 |
-
$key = $this->get_field_key( $key );
|
2891 |
-
|
2892 |
-
ob_start();
|
2893 |
-
|
2894 |
-
?>
|
2895 |
-
</table>
|
2896 |
-
<h3 class="wc-settings-sub-title" id="<?php echo esc_attr( $key ); ?>">
|
2897 |
-
|
2898 |
-
<?php esc_html_e( 'Product sync', 'facebook-for-woocommerce' ); ?>
|
2899 |
-
|
2900 |
-
<?php if ( $this->get_page_name() ) : ?>
|
2901 |
-
<a
|
2902 |
-
id="woocommerce-facebook-settings-sync-products"
|
2903 |
-
class="button product-sync-field"
|
2904 |
-
href="#"
|
2905 |
-
style="vertical-align: middle; margin-left: 20px;"
|
2906 |
-
><?php esc_html_e( 'Sync products', 'facebook-for-woocommerce' ); ?></a>
|
2907 |
-
<?php endif; ?>
|
2908 |
-
|
2909 |
-
</h3>
|
2910 |
-
<div><p id="sync_progress" style="display: none"></p></div>
|
2911 |
-
<table class="form-table">
|
2912 |
-
<?php
|
2913 |
-
|
2914 |
-
return ob_get_clean();
|
2915 |
-
}
|
2916 |
-
|
2917 |
-
|
2918 |
-
/**
|
2919 |
-
* Processes and saves options.
|
2920 |
-
*
|
2921 |
-
* @see \WC_Settings_API::process_admin_options()
|
2922 |
-
*
|
2923 |
-
* @internal
|
2924 |
-
*
|
2925 |
-
* @since 1.10.0
|
2926 |
-
*/
|
2927 |
-
public function process_admin_options() {
|
2928 |
-
|
2929 |
-
$current_resync_offset = $this->get_scheduled_resync_offset();
|
2930 |
-
|
2931 |
-
parent::process_admin_options();
|
2932 |
-
|
2933 |
-
$saved_resync_offset = $this->get_scheduled_resync_offset();
|
2934 |
-
|
2935 |
-
if ( null === $saved_resync_offset || ! $this->is_product_sync_enabled() ) {
|
2936 |
-
$this->unschedule_resync();
|
2937 |
-
} elseif ( $saved_resync_offset !== $current_resync_offset || false === $this->is_resync_scheduled() ) {
|
2938 |
-
$this->schedule_resync( $saved_resync_offset );
|
2939 |
-
}
|
2940 |
-
|
2941 |
-
// when settings are saved, if there are excluded categories/terms we can exclude corresponding products from sync
|
2942 |
-
$product_cats = $product_tags = [];
|
2943 |
-
$product_cat_ids = $this->get_excluded_product_category_ids();
|
2944 |
-
$product_tag_ids = $this->get_excluded_product_tag_ids();
|
2945 |
-
|
2946 |
-
$disable_sync_for_products = [];
|
2947 |
-
|
2948 |
-
// get all products belonging to excluded categories
|
2949 |
-
if ( ! empty( $product_cat_ids ) ) {
|
2950 |
-
|
2951 |
-
foreach ( $product_cat_ids as $tag_id ) {
|
2952 |
-
|
2953 |
-
$term = get_term_by( 'id', $tag_id, 'product_cat' );
|
2954 |
-
|
2955 |
-
if ( $term instanceof \WP_Term ) {
|
2956 |
-
$product_cats[] = $term->slug;
|
2957 |
-
}
|
2958 |
-
}
|
2959 |
-
|
2960 |
-
if ( ! empty( $product_cats ) ) {
|
2961 |
-
|
2962 |
-
$disable_sync_for_products = wc_get_products( [
|
2963 |
-
'category' => $product_cats,
|
2964 |
-
'limit' => -1,
|
2965 |
-
'return' => 'ids',
|
2966 |
-
] );
|
2967 |
-
}
|
2968 |
-
}
|
2969 |
-
|
2970 |
-
// get all products belonging to excluded tags
|
2971 |
-
if ( ! empty( $product_tag_ids ) ) {
|
2972 |
-
|
2973 |
-
foreach ( $product_tag_ids as $tag_id ) {
|
2974 |
-
|
2975 |
-
$term = get_term_by( 'id', $tag_id, 'product_tag' );
|
2976 |
-
|
2977 |
-
if ( $term instanceof \WP_Term ) {
|
2978 |
-
$product_tags[] = $term->slug;
|
2979 |
-
}
|
2980 |
-
}
|
2981 |
-
|
2982 |
-
if ( ! empty( $product_tags ) ) {
|
2983 |
-
|
2984 |
-
$disable_sync_for_products = array_merge( wc_get_products( [
|
2985 |
-
'tag' => $product_tags,
|
2986 |
-
'limit' => -1,
|
2987 |
-
'return' => 'ids',
|
2988 |
-
] ), $disable_sync_for_products );
|
2989 |
-
}
|
2990 |
-
}
|
2991 |
-
|
2992 |
-
if ( ! empty( $disable_sync_for_products ) ) {
|
2993 |
-
|
2994 |
-
// disable sync for found products that match any excluded term
|
2995 |
-
Products::disable_sync_for_products( wc_get_products( [
|
2996 |
-
'limit' => -1,
|
2997 |
-
'include' => array_unique( $disable_sync_for_products ),
|
2998 |
-
] ) );
|
2999 |
-
}
|
3000 |
-
}
|
3001 |
-
|
3002 |
-
|
3003 |
-
/**
|
3004 |
-
* Generates the force resync fieldset HTML.
|
3005 |
-
*
|
3006 |
-
* @see \WC_Settings_API::generate_settings_html()
|
3007 |
-
*
|
3008 |
-
* @since 1.10.0
|
3009 |
-
*
|
3010 |
-
* @param string $key field key
|
3011 |
-
* @param array $data field data
|
3012 |
-
* @return string HTML
|
3013 |
*/
|
3014 |
-
|
3015 |
-
|
3016 |
-
$fieldset_key = $this->get_field_key( $key );
|
3017 |
-
$enabled_field_key = $this->get_field_key( 'scheduled_resync_enabled' );
|
3018 |
-
$hours_field_key = $this->get_field_key( 'scheduled_resync_hours' );
|
3019 |
-
$minutes_field_key = $this->get_field_key( 'scheduled_resync_minutes' );
|
3020 |
-
$meridiem_field_key = $this->get_field_key( 'scheduled_resync_meridiem' );
|
3021 |
-
|
3022 |
-
// check if the sites uses 12-hours or 24-hours time format
|
3023 |
-
$time_format = wc_time_format();
|
3024 |
-
// TODO replace these string search functions with Framework string helpers {FN 2020-01-31}
|
3025 |
-
$is_12_hours = ( false !== strpos( $time_format, 'g' ) || false !== strpos( $time_format, 'h' ) );
|
3026 |
-
// default to 24-hours format if no hour specifier is found on the string
|
3027 |
-
$is_24_hours = ! $is_12_hours;
|
3028 |
-
|
3029 |
-
if ( $this->is_scheduled_resync_enabled() ) {
|
3030 |
-
try {
|
3031 |
-
$offset = $this->get_scheduled_resync_offset();
|
3032 |
-
$resync_time = ( new DateTime( 'today' ) )->add( new DateInterval( "PT${offset}S" ) );
|
3033 |
-
$resync_hours = $is_24_hours ? $resync_time->format( 'G' ) : $resync_time->format( 'g' );
|
3034 |
-
$resync_minutes = $resync_time->format( 'i' );
|
3035 |
-
} catch ( \Exception $e ) {}
|
3036 |
-
}
|
3037 |
|
3038 |
-
|
3039 |
-
|
3040 |
-
|
3041 |
-
|
3042 |
-
$resync_meridiem = $is_24_hours ? '' : 'pm';
|
3043 |
}
|
3044 |
|
3045 |
-
$
|
3046 |
-
'title' => '',
|
3047 |
-
'disabled' => false,
|
3048 |
-
'class' => '',
|
3049 |
-
'css' => '',
|
3050 |
-
'desc_tip' => false,
|
3051 |
-
];
|
3052 |
|
3053 |
-
|
3054 |
|
3055 |
-
|
3056 |
-
|
3057 |
-
<tr valign="top">
|
3058 |
-
<th scope="row" class="titledesc">
|
3059 |
-
<label for="<?php echo esc_attr( $fieldset_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?> <?php echo $this->get_tooltip_html( $data ); ?></label>
|
3060 |
-
</th>
|
3061 |
-
<td class="forminp">
|
3062 |
-
<fieldset class="<?php echo esc_attr( $data['class'] ); ?>">
|
3063 |
-
<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
|
3064 |
-
<input
|
3065 |
-
class="toggle-fields-group resync-schedule-field"
|
3066 |
-
<?php disabled( $data['disabled'], true ); ?>
|
3067 |
-
type="checkbox"
|
3068 |
-
name="<?php echo esc_attr( $enabled_field_key ); ?>"
|
3069 |
-
id="<?php echo esc_attr( $enabled_field_key ); ?>"
|
3070 |
-
style="<?php echo esc_attr( $data['css'] ); ?>"
|
3071 |
-
value="1"
|
3072 |
-
<?php checked( $this->is_scheduled_resync_enabled() ); ?>
|
3073 |
-
/>
|
3074 |
-
<input
|
3075 |
-
class="input-number regular-input resync-schedule-field"
|
3076 |
-
type="number"
|
3077 |
-
min="0"
|
3078 |
-
max="<?php echo $is_24_hours ? 24 : 12; ?>"
|
3079 |
-
name="<?php echo esc_attr( $hours_field_key ); ?>"
|
3080 |
-
id="<?php echo esc_attr( $hours_field_key ); ?>"
|
3081 |
-
style="<?php echo esc_attr( $data['css'] ); ?>"
|
3082 |
-
value="<?php echo ! empty( $resync_hours ) ? esc_attr( $resync_hours ) : ''; ?>"
|
3083 |
-
<?php disabled( $data['disabled'], true ); ?>
|
3084 |
-
/>
|
3085 |
-
<strong>:</strong>
|
3086 |
-
<input
|
3087 |
-
class="input-number regular-input resync-schedule-field"
|
3088 |
-
type="number"
|
3089 |
-
min="0"
|
3090 |
-
max="59"
|
3091 |
-
name="<?php echo esc_attr( $minutes_field_key ); ?>"
|
3092 |
-
id="<?php echo esc_attr( $minutes_field_key ); ?>"
|
3093 |
-
style="<?php echo esc_attr( $data['css'] ); ?>"
|
3094 |
-
value="<?php echo ! empty( $resync_minutes ) ? esc_attr( $resync_minutes ) : ''; ?>"
|
3095 |
-
<?php disabled( $data['disabled'], true ); ?>
|
3096 |
-
/>
|
3097 |
-
<?php if ( ! $is_24_hours ) : ?>
|
3098 |
-
|
3099 |
-
<select
|
3100 |
-
class="resync-schedule-field"
|
3101 |
-
name="<?php echo esc_attr( $meridiem_field_key ); ?>"
|
3102 |
-
id="<?php echo esc_attr( $meridiem_field_key ); ?>"
|
3103 |
-
style="<?php echo esc_attr( $data['css'] ); ?>"
|
3104 |
-
<?php disabled( $data['disabled'], true ); ?>>
|
3105 |
-
<option
|
3106 |
-
<?php selected( true, $this->get_scheduled_resync_offset() < 12 * HOUR_IN_SECONDS, true ); ?>
|
3107 |
-
value="am">
|
3108 |
-
<?php esc_html_e( 'am', 'facebook-for-woocommerce' ); ?>
|
3109 |
-
</option>
|
3110 |
-
<option
|
3111 |
-
<?php selected( true, $this->get_scheduled_resync_offset() >= 12 * HOUR_IN_SECONDS || ( ! empty( $resync_meridiem ) && 'pm' === $resync_meridiem ), true ); ?>
|
3112 |
-
value="pm">
|
3113 |
-
<?php esc_html_e( 'pm', 'facebook-for-woocommerce' ); ?>
|
3114 |
-
</option>
|
3115 |
-
</select>
|
3116 |
-
|
3117 |
-
<?php endif; ?>
|
3118 |
-
<br/>
|
3119 |
-
</fieldset>
|
3120 |
-
</td>
|
3121 |
-
</tr>
|
3122 |
-
<?php
|
3123 |
|
3124 |
-
|
3125 |
-
}
|
3126 |
|
|
|
3127 |
|
3128 |
-
|
3129 |
-
|
3130 |
-
|
3131 |
-
|
3132 |
-
|
3133 |
-
|
3134 |
-
*
|
3135 |
-
* @param string $key field key
|
3136 |
-
* @param string $value posted value
|
3137 |
-
* @return int|string timestamp or empty string
|
3138 |
-
* @throws \Exception
|
3139 |
-
*/
|
3140 |
-
public function validate_resync_schedule_field( $key, $value ) {
|
3141 |
|
3142 |
-
|
3143 |
-
|
3144 |
-
$minutes_field_key = $this->get_field_key( 'scheduled_resync_minutes' );
|
3145 |
-
$meridiem_field_key = $this->get_field_key( 'scheduled_resync_meridiem' );
|
3146 |
|
3147 |
-
|
3148 |
-
|
3149 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3150 |
}
|
3151 |
|
3152 |
-
|
3153 |
-
$posted_minutes = (int) sanitize_text_field( wp_unslash( $_POST[ $minutes_field_key ] ) );
|
3154 |
-
$posted_minutes = str_pad( $posted_minutes, 2, '0', STR_PAD_LEFT );
|
3155 |
-
$posted_meridiem = ! empty( $_POST[ $meridiem_field_key ] ) ? sanitize_text_field( wp_unslash( $_POST[ $meridiem_field_key ] ) ) : '';
|
3156 |
|
3157 |
-
|
3158 |
-
$parsed_time = strtotime( "$posted_hours:$posted_minutes $posted_meridiem" );
|
3159 |
|
3160 |
-
|
3161 |
-
throw new \Exception( "Invalid resync schedule time: $posted_hours:$posted_minutes $posted_meridiem" );
|
3162 |
}
|
3163 |
|
3164 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3165 |
|
3166 |
-
return
|
3167 |
}
|
3168 |
|
3169 |
|
3170 |
/**
|
3171 |
-
*
|
3172 |
*
|
3173 |
-
*
|
3174 |
*
|
3175 |
-
* @
|
3176 |
*
|
3177 |
-
* @
|
3178 |
-
* @param array $args associative array of field arguments
|
3179 |
-
* @return string HTML
|
3180 |
*/
|
3181 |
-
|
3182 |
-
|
3183 |
-
// TODO replace strlen() here with Framework helper method to account for multibyte characters {FN 2020-01-30}
|
3184 |
-
$chars = max( 0, strlen( $this->get_messenger_greeting() ) );
|
3185 |
-
$max_chars = max( 0, $this->get_messenger_greeting_max_characters() );
|
3186 |
-
$field_id = $this->get_field_key( $key );
|
3187 |
-
$counter_class = $field_id . '-characters-count';
|
3188 |
|
3189 |
-
|
3190 |
-
|
3191 |
-
|
3192 |
-
|
3193 |
-
|
3194 |
|
3195 |
-
|
|
|
3196 |
|
3197 |
-
?>
|
3198 |
-
<span
|
3199 |
-
style="display: none; font-family: monospace; font-size: 0.9em;"
|
3200 |
-
class="<?php echo sanitize_html_class( $counter_class ); ?> characters-counter"
|
3201 |
-
><?php echo esc_html( $chars . ' / ' . $max_chars ); ?> <span style="display:none;"><?php echo esc_html( $this->get_messenger_greeting_long_warning_text() ); ?></span></span>
|
3202 |
-
<?php
|
3203 |
|
3204 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
3205 |
|
3206 |
-
|
3207 |
}
|
3208 |
|
3209 |
|
3210 |
/**
|
3211 |
-
*
|
3212 |
-
*
|
3213 |
-
* @see \WC_Settings_API::validate_textarea_field()
|
3214 |
*
|
3215 |
-
* @since 1.
|
|
|
3216 |
*
|
3217 |
-
* @
|
3218 |
-
* @param string $value field submitted value
|
3219 |
-
* @throws \Exception on validation errors
|
3220 |
-
* @return string some HTML allowed
|
3221 |
*/
|
3222 |
-
|
3223 |
-
|
3224 |
-
$value = is_string( $value ) ? trim( sanitize_text_field( wp_unslash( $value ) ) ) : '';
|
3225 |
-
|
3226 |
-
$max_chars = $this->get_messenger_greeting_max_characters();
|
3227 |
-
$value_length = function_exists( 'mb_strlen' ) ? mb_strlen( $value, Framework\SV_WC_Helper::MB_ENCODING ) : strlen( $value );
|
3228 |
-
|
3229 |
-
if ( $value_length > $max_chars ) {
|
3230 |
-
|
3231 |
-
throw new Framework\SV_WC_Plugin_Exception( sprintf(
|
3232 |
-
$this->get_messenger_greeting_long_warning_text() . ' %s',
|
3233 |
-
__( "The greeting hasn't been updated.", 'facebook-for-woocommerce' )
|
3234 |
-
) );
|
3235 |
-
}
|
3236 |
|
3237 |
-
|
3238 |
}
|
3239 |
|
3240 |
|
3241 |
/**
|
3242 |
-
*
|
3243 |
*
|
3244 |
-
*
|
3245 |
*
|
3246 |
-
* @
|
|
|
|
|
|
|
3247 |
*/
|
3248 |
-
|
3249 |
|
3250 |
-
|
3251 |
-
/* translators: Placeholder: %d - maximum number of allowed characters */
|
3252 |
-
__( 'The Messenger greeting must be %d characters or less.', 'facebook-for-woocommerce' ),
|
3253 |
-
$this->get_messenger_greeting_max_characters()
|
3254 |
-
);
|
3255 |
}
|
3256 |
|
3257 |
|
@@ -3471,7 +2513,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3471 |
* @param string $page_id the configured Facebook page ID
|
3472 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
3473 |
*/
|
3474 |
-
return (string) apply_filters( 'wc_facebook_page_id',
|
3475 |
}
|
3476 |
|
3477 |
|
@@ -3492,7 +2534,25 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3492 |
* @param string $pixel_id the configured Facebook pixel ID
|
3493 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
3494 |
*/
|
3495 |
-
return (string) apply_filters( 'wc_facebook_pixel_id',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3496 |
}
|
3497 |
|
3498 |
|
@@ -3513,7 +2573,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3513 |
* @param int[] $category_ids the configured excluded product category IDs
|
3514 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
3515 |
*/
|
3516 |
-
return (array) apply_filters( 'wc_facebook_excluded_product_category_ids',
|
3517 |
}
|
3518 |
|
3519 |
|
@@ -3534,7 +2594,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3534 |
* @param int[] $tag_ids the configured excluded product tag IDs
|
3535 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
3536 |
*/
|
3537 |
-
return (array) apply_filters( 'wc_facebook_excluded_product_tag_ids',
|
3538 |
}
|
3539 |
|
3540 |
|
@@ -3555,7 +2615,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3555 |
* @param string $mode the configured product description mode
|
3556 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
3557 |
*/
|
3558 |
-
$mode = (string) apply_filters( 'wc_facebook_product_description_mode',
|
3559 |
|
3560 |
$valid_modes = [
|
3561 |
self::PRODUCT_DESCRIPTION_MODE_STANDARD,
|
@@ -3576,26 +2636,13 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3576 |
* Returns null if no offset is configured.
|
3577 |
*
|
3578 |
* @since 1.10.0
|
|
|
3579 |
*
|
3580 |
* @return int|null
|
3581 |
*/
|
3582 |
public function get_scheduled_resync_offset() {
|
3583 |
|
3584 |
-
|
3585 |
-
* Filters the configured scheduled re-sync offset.
|
3586 |
-
*
|
3587 |
-
* @since 1.10.0
|
3588 |
-
*
|
3589 |
-
* @param int|null $offset the configured scheduled re-sync offset in seconds
|
3590 |
-
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
3591 |
-
*/
|
3592 |
-
$offset = (int) apply_filters( 'wc_facebook_scheduled_resync_offset', $this->get_option( self::SETTING_SCHEDULED_RESYNC_OFFSET, null ), $this );
|
3593 |
-
|
3594 |
-
if ( ! $offset ) {
|
3595 |
-
$offset = null;
|
3596 |
-
}
|
3597 |
-
|
3598 |
-
return $offset;
|
3599 |
}
|
3600 |
|
3601 |
|
@@ -3616,7 +2663,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3616 |
* @param string $locale the configured Facebook messenger locale
|
3617 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
3618 |
*/
|
3619 |
-
return (string) apply_filters( 'wc_facebook_messenger_locale',
|
3620 |
}
|
3621 |
|
3622 |
|
@@ -3637,10 +2684,9 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3637 |
* @param string $greeting the configured Facebook messenger greeting
|
3638 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
3639 |
*/
|
3640 |
-
$greeting = (string) apply_filters( 'wc_facebook_messenger_greeting',
|
3641 |
|
3642 |
-
|
3643 |
-
return substr( $greeting, 0, $this->get_messenger_greeting_max_characters() );
|
3644 |
}
|
3645 |
|
3646 |
|
@@ -3688,7 +2734,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3688 |
* @param string $hex the configured Facebook messenger color hex
|
3689 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
3690 |
*/
|
3691 |
-
return (string) apply_filters( 'wc_facebook_messenger_color_hex',
|
3692 |
}
|
3693 |
|
3694 |
|
@@ -3816,21 +2862,6 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3816 |
}
|
3817 |
|
3818 |
|
3819 |
-
/**
|
3820 |
-
* Sets whether the feed has been migrated from FBE 1 to FBE 1.5.
|
3821 |
-
*
|
3822 |
-
* @since 1.11.0
|
3823 |
-
*
|
3824 |
-
* @param bool $is_migrated whether the feed has been migrated from FBE 1 to FBE 1.5
|
3825 |
-
*/
|
3826 |
-
private function set_feed_migrated( $is_migrated ) {
|
3827 |
-
|
3828 |
-
$this->feed_migrated = (bool) $is_migrated;
|
3829 |
-
|
3830 |
-
update_option( 'wc_facebook_feed_migrated', wc_bool_to_string( $this->feed_migrated ) );
|
3831 |
-
}
|
3832 |
-
|
3833 |
-
|
3834 |
/** Conditional methods *******************************************************************************************/
|
3835 |
|
3836 |
|
@@ -3843,7 +2874,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3843 |
*/
|
3844 |
public function is_configured() {
|
3845 |
|
3846 |
-
return (
|
3847 |
}
|
3848 |
|
3849 |
|
@@ -3864,7 +2895,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3864 |
* @param bool $is_enabled whether advanced matching is enabled
|
3865 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
3866 |
*/
|
3867 |
-
return (bool) apply_filters( 'wc_facebook_is_advanced_matching_enabled',
|
3868 |
}
|
3869 |
|
3870 |
|
@@ -3885,7 +2916,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3885 |
* @param bool $is_enabled whether product sync is enabled
|
3886 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
3887 |
*/
|
3888 |
-
return (bool) apply_filters( 'wc_facebook_is_product_sync_enabled', 'yes' ===
|
3889 |
}
|
3890 |
|
3891 |
|
@@ -3893,20 +2924,15 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3893 |
* Determines whether the scheduled re-sync is enabled.
|
3894 |
*
|
3895 |
* @since 1.10.0
|
|
|
3896 |
*
|
3897 |
* @return bool
|
3898 |
*/
|
3899 |
public function is_scheduled_resync_enabled() {
|
3900 |
|
3901 |
-
|
3902 |
-
|
3903 |
-
|
3904 |
-
* @since 1.10.0
|
3905 |
-
*
|
3906 |
-
* @param bool $is_enabled whether the scheduled re-sync is enabled
|
3907 |
-
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
3908 |
-
*/
|
3909 |
-
return (bool) apply_filters( 'wc_facebook_is_scheduled_resync_enabled', $this->get_scheduled_resync_offset(), $this );
|
3910 |
}
|
3911 |
|
3912 |
|
@@ -3927,7 +2953,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3927 |
* @param bool $is_enabled whether the Facebook messenger is enabled
|
3928 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
3929 |
*/
|
3930 |
-
return (bool) apply_filters( 'wc_facebook_is_messenger_enabled', 'yes' ===
|
3931 |
}
|
3932 |
|
3933 |
|
@@ -3948,7 +2974,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3948 |
* @param bool $is_enabled whether debug mode is enabled
|
3949 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
3950 |
*/
|
3951 |
-
return (bool) apply_filters( 'wc_facebook_is_debug_mode_enabled', 'yes' ===
|
3952 |
}
|
3953 |
|
3954 |
|
@@ -4058,6 +3084,42 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
4058 |
}
|
4059 |
|
4060 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4061 |
/**
|
4062 |
* Gets the name of the configured Facebook page.
|
4063 |
*
|
@@ -4065,14 +3127,9 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
4065 |
*/
|
4066 |
public function get_page_name() {
|
4067 |
|
4068 |
-
|
4069 |
-
if ( $this->get_facebook_page_id() && $this->get_page_access_token() ) {
|
4070 |
-
$page_name = $this->fbgraph->get_page_name( $this->get_facebook_page_id(), $this->get_page_access_token() );
|
4071 |
-
} else {
|
4072 |
-
$page_name = '';
|
4073 |
-
}
|
4074 |
|
4075 |
-
return
|
4076 |
}
|
4077 |
|
4078 |
|
@@ -4085,13 +3142,9 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
4085 |
*/
|
4086 |
public function get_page_url() {
|
4087 |
|
4088 |
-
|
4089 |
-
$page_url = $this->fbgraph->get_page_url( $this->get_facebook_page_id(), $this->get_page_access_token() );
|
4090 |
-
} else {
|
4091 |
-
$page_url = '';
|
4092 |
-
}
|
4093 |
|
4094 |
-
return
|
4095 |
}
|
4096 |
|
4097 |
|
@@ -4148,71 +3201,10 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
4148 |
*/
|
4149 |
function admin_options() {
|
4150 |
|
4151 |
-
|
4152 |
-
$can_manage = current_user_can( 'manage_woocommerce' );
|
4153 |
-
$pre_setup = empty( $this->get_facebook_page_id() ) || empty( $this->get_page_access_token() );
|
4154 |
-
$apikey_invalid = ! $pre_setup && $this->get_page_access_token() && ! $page_name;
|
4155 |
-
|
4156 |
-
$remove_http_active = is_plugin_active( 'remove-http/remove-http.php' );
|
4157 |
-
$https_will_be_stripped = $remove_http_active && ! get_option( 'factmaven_rhttp' )['external'];
|
4158 |
-
|
4159 |
-
if ( $https_will_be_stripped ) {
|
4160 |
-
|
4161 |
-
$this->display_sticky_message(
|
4162 |
-
__( 'You\'re using Remove HTTP which has incompatibilities with our extension. Please disable it, or select the "Ignore external links" option on the Remove HTTP settings page.' )
|
4163 |
-
);
|
4164 |
-
}
|
4165 |
|
4166 |
?>
|
4167 |
|
4168 |
-
<h2><?php esc_html_e( 'Facebook', 'facebook-for-woocommerce' ); ?></h2>
|
4169 |
-
|
4170 |
-
<p>
|
4171 |
-
<?php esc_html_e( 'Control how WooCommerce integrates with your Facebook store.', 'facebook-for-woocommerce' ); ?>
|
4172 |
-
</p>
|
4173 |
-
|
4174 |
-
<div><input type="hidden" name="section" value="<?php echo esc_attr( $this->id ); ?>" /></div>
|
4175 |
-
|
4176 |
-
<div id="fbsetup" <?php echo $this->is_configured() ? 'style="display: none"' : ''; ?>>
|
4177 |
-
<div class="wrapper">
|
4178 |
-
<header>
|
4179 |
-
<div class="help-center">
|
4180 |
-
<a href="https://www.facebook.com/business/help/900699293402826" target="_blank">Help Center <i class="help-center-icon"></i></a>
|
4181 |
-
</div>
|
4182 |
-
</header>
|
4183 |
-
|
4184 |
-
<div class="content">
|
4185 |
-
<h1 id="setup_h1"><?php esc_html_e( 'Grow your business on Facebook', 'facebook-for-woocommerce' ); ?></h1>
|
4186 |
-
|
4187 |
-
<h2>
|
4188 |
-
<?php esc_html_e( 'Use this WooCommerce and Facebook integration to:', 'facebook-for-woocommerce' ); ?>
|
4189 |
-
</h2>
|
4190 |
-
|
4191 |
-
<ul>
|
4192 |
-
<li id="setup_l1"><?php esc_html_e( 'Easily install a tracking pixel', 'facebook-for-woocommerce' ); ?></li>
|
4193 |
-
<li id="setup_l2"><?php esc_html_e( 'Upload your products and create a shop', 'facebook-for-woocommerce' ); ?></li>
|
4194 |
-
<li id="setup_l3"><?php esc_html_e( 'Create dynamic ads with your products and pixel', 'facebook-for-woocommerce' ); ?></li>
|
4195 |
-
</ul>
|
4196 |
-
|
4197 |
-
<span
|
4198 |
-
<?php $external_merchant_settings_id = $this->get_external_merchant_settings_id(); ?>
|
4199 |
-
<?php echo ( ! $can_manage || $apikey_invalid || ! isset( $external_merchant_settings_id ) ) ? ' style="pointer-events: none;"' : ''; ?>>
|
4200 |
-
|
4201 |
-
<a href="#" class="btn pre-setup" onclick="facebookConfig()" id="cta_button">
|
4202 |
-
<?php esc_html_e( 'Get Started', 'facebook-for-woocommerce' ); ?>
|
4203 |
-
</a>
|
4204 |
-
|
4205 |
-
</span>
|
4206 |
-
|
4207 |
-
<?php
|
4208 |
-
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
4209 |
-
echo $this->get_nux_message_ifexist();
|
4210 |
-
?>
|
4211 |
-
|
4212 |
-
</div>
|
4213 |
-
</div>
|
4214 |
-
</div>
|
4215 |
-
|
4216 |
<div id="integration-settings" <?php echo ! $this->is_configured() ? 'style="display: none"' : ''; ?>>
|
4217 |
<table class="form-table"><?php $this->generate_settings_html( $this->get_form_fields() ); ?></table>
|
4218 |
</div>
|
@@ -4233,56 +3225,103 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
4233 |
}
|
4234 |
}
|
4235 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4236 |
function fb_duplicate_product_reset_meta( $to_delete ) {
|
4237 |
array_push( $to_delete, self::FB_PRODUCT_ITEM_ID );
|
4238 |
array_push( $to_delete, self::FB_PRODUCT_GROUP_ID );
|
4239 |
return $to_delete;
|
4240 |
}
|
4241 |
|
|
|
4242 |
/**
|
4243 |
* Helper function to update FB visibility.
|
|
|
|
|
|
|
4244 |
*/
|
4245 |
-
function update_fb_visibility( $
|
4246 |
|
4247 |
-
// bail if
|
4248 |
-
if ( ! $this->
|
4249 |
return;
|
4250 |
}
|
4251 |
|
4252 |
-
$
|
4253 |
|
4254 |
-
|
4255 |
-
|
4256 |
return;
|
4257 |
}
|
4258 |
|
4259 |
-
$
|
4260 |
-
|
4261 |
-
|
4262 |
-
|
4263 |
-
|
4264 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4265 |
|
4266 |
if ( ! $fb_product_item_id ) {
|
4267 |
-
WC_Facebookcommerce_Utils::fblog(
|
4268 |
-
|
4269 |
-
array(),
|
4270 |
-
true
|
4271 |
-
);
|
4272 |
-
continue;
|
4273 |
}
|
4274 |
-
$result = $this->check_api_result(
|
4275 |
-
$this->fbgraph->update_product_item(
|
4276 |
-
$fb_product_item_id,
|
4277 |
-
array( 'visibility' => $visibility )
|
4278 |
-
)
|
4279 |
-
);
|
4280 |
-
if ( $result ) {
|
4281 |
|
4282 |
-
|
4283 |
|
4284 |
-
|
4285 |
-
|
4286 |
}
|
4287 |
}
|
4288 |
}
|
@@ -4311,7 +3350,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
4311 |
} else {
|
4312 |
// - product never published to Facebook, new status is not publish
|
4313 |
// - product new status is not publish but may have been published before
|
4314 |
-
$this->update_fb_visibility( $
|
4315 |
}
|
4316 |
}
|
4317 |
|
@@ -4335,15 +3374,13 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
4335 |
return $fb_id;
|
4336 |
}
|
4337 |
|
4338 |
-
if ( ! isset( $this->settings['upload_end_time'] ) ) {
|
4339 |
-
return null;
|
4340 |
-
}
|
4341 |
-
|
4342 |
if ( ! $woo_product ) {
|
4343 |
$woo_product = new WC_Facebook_Product( $wp_id );
|
4344 |
}
|
4345 |
|
4346 |
-
$products
|
|
|
|
|
4347 |
$woo_product = new WC_Facebook_Product( current( $products ) );
|
4348 |
|
4349 |
// This is a generalized function used elsewhere
|
@@ -4392,8 +3429,6 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
4392 |
$fb_id
|
4393 |
);
|
4394 |
|
4395 |
-
update_post_meta( $wp_id, Products::VISIBILITY_META_KEY, true );
|
4396 |
-
|
4397 |
return $fb_id;
|
4398 |
}
|
4399 |
}
|
@@ -4464,25 +3499,6 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
4464 |
}
|
4465 |
|
4466 |
|
4467 |
-
function ajax_update_fb_option() {
|
4468 |
-
|
4469 |
-
check_ajax_referer( 'wc_facebook_settings_jsx' );
|
4470 |
-
WC_Facebookcommerce_Utils::check_woo_ajax_permissions( 'update fb options', true );
|
4471 |
-
|
4472 |
-
if ( isset( $_POST ) && ! empty( $_POST['option'] ) && isset( $_POST['option_value'] ) ) {
|
4473 |
-
|
4474 |
-
$option_name = sanitize_text_field( wp_unslash( $_POST['option'] ) );
|
4475 |
-
$option_value = sanitize_text_field( wp_unslash( $_POST['option_value'] ) );
|
4476 |
-
|
4477 |
-
if ( stripos( $option_name, 'fb_' ) === 0 ) {
|
4478 |
-
update_option( $option_name, $option_value );
|
4479 |
-
}
|
4480 |
-
}
|
4481 |
-
|
4482 |
-
wp_die();
|
4483 |
-
}
|
4484 |
-
|
4485 |
-
|
4486 |
/**
|
4487 |
* Adds an recurring action to sync products.
|
4488 |
*
|
@@ -4589,14 +3605,23 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
4589 |
}
|
4590 |
}
|
4591 |
|
|
|
|
|
|
|
|
|
4592 |
/**
|
4593 |
-
* Enables product sync delay
|
|
|
|
|
4594 |
*
|
4595 |
* @since 1.11.0
|
|
|
|
|
|
|
4596 |
*/
|
4597 |
-
|
4598 |
|
4599 |
-
|
4600 |
}
|
4601 |
|
4602 |
|
8 |
* @package FacebookCommerce
|
9 |
*/
|
10 |
|
11 |
+
use SkyVerge\WooCommerce\Facebook\Admin;
|
12 |
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
13 |
use SkyVerge\WooCommerce\Facebook\Products;
|
14 |
use SkyVerge\WooCommerce\Facebook\Products\Feed;
|
46 |
const OPTION_PIXEL_INSTALL_TIME = 'wc_facebook_pixel_install_time';
|
47 |
|
48 |
/** @var string the facebook page ID setting ID */
|
49 |
+
const SETTING_FACEBOOK_PAGE_ID = 'wc_facebook_page_id';
|
50 |
|
51 |
/** @var string the facebook pixel ID setting ID */
|
52 |
+
const SETTING_FACEBOOK_PIXEL_ID = 'wc_facebook_pixel_id';
|
53 |
|
54 |
/** @var string the "enable advanced matching" setting ID */
|
55 |
const SETTING_ENABLE_ADVANCED_MATCHING = 'enable_advanced_matching';
|
56 |
|
57 |
+
/** @var string the "use s2s" setting ID */
|
58 |
+
const SETTING_USE_S2S = 'use_s2s';
|
59 |
+
|
60 |
+
/** @var string the "access token" setting ID */
|
61 |
+
const SETTING_ACCESS_TOKEN = 'access_token';
|
62 |
+
|
63 |
/** @var string the "enable product sync" setting ID */
|
64 |
+
const SETTING_ENABLE_PRODUCT_SYNC = 'wc_facebook_enable_product_sync';
|
65 |
|
66 |
/** @var string the excluded product category IDs setting ID */
|
67 |
+
const SETTING_EXCLUDED_PRODUCT_CATEGORY_IDS = 'wc_facebook_excluded_product_category_ids';
|
68 |
|
69 |
/** @var string the excluded product tag IDs setting ID */
|
70 |
+
const SETTING_EXCLUDED_PRODUCT_TAG_IDS = 'wc_facebook_excluded_product_tag_ids';
|
71 |
|
72 |
/** @var string the product description mode setting ID */
|
73 |
+
const SETTING_PRODUCT_DESCRIPTION_MODE = 'wc_facebook_product_description_mode';
|
74 |
|
75 |
/** @var string the scheduled resync offset setting ID */
|
76 |
const SETTING_SCHEDULED_RESYNC_OFFSET = 'scheduled_resync_offset';
|
77 |
|
78 |
/** @var string the "enable messenger" setting ID */
|
79 |
+
const SETTING_ENABLE_MESSENGER = 'wc_facebook_enable_messenger';
|
80 |
|
81 |
/** @var string the messenger locale setting ID */
|
82 |
+
const SETTING_MESSENGER_LOCALE = 'wc_facebook_messenger_locale';
|
83 |
|
84 |
/** @var string the messenger greeting setting ID */
|
85 |
+
const SETTING_MESSENGER_GREETING = 'wc_facebook_messenger_greeting';
|
86 |
|
87 |
/** @var string the messenger color HEX setting ID */
|
88 |
+
const SETTING_MESSENGER_COLOR_HEX = 'wc_facebook_messenger_color_hex';
|
89 |
|
90 |
/** @var string the "debug mode" setting ID */
|
91 |
+
const SETTING_ENABLE_DEBUG_MODE = 'wc_facebook_enable_debug_mode';
|
92 |
|
93 |
/** @var string the standard product description mode name */
|
94 |
const PRODUCT_DESCRIPTION_MODE_STANDARD = 'standard';
|
124 |
/** @var bool|null whether the feed has been migrated from FBE 1 to FBE 1.5 */
|
125 |
private $feed_migrated;
|
126 |
|
127 |
+
/** @var array the page name and url */
|
128 |
+
private $page;
|
129 |
+
|
130 |
|
131 |
/** Legacy properties *********************************************************************************************/
|
132 |
|
142 |
/** @var string the API flag to set a product as not visible in the Facebook shop */
|
143 |
const FB_SHOP_PRODUCT_HIDDEN = 'staging';
|
144 |
|
145 |
+
/** @var string @deprecated */
|
146 |
const FB_CART_URL = 'fb_cart_url';
|
147 |
|
148 |
const FB_MESSAGE_DISPLAY_TIME = 180;
|
187 |
// so that it works the same way the pixel ID does
|
188 |
$settings_advanced_matching_enabled = $this->is_advanced_matching_enabled();
|
189 |
WC_Facebookcommerce_Pixel::set_use_pii_key( $settings_advanced_matching_enabled );
|
190 |
+
|
191 |
+
$settings_use_s2s = $this->is_use_s2s_enabled();
|
192 |
+
WC_Facebookcommerce_Pixel::set_use_s2s( $settings_use_s2s );
|
193 |
+
|
194 |
+
$settings_access_token = $this->get_access_token();
|
195 |
+
WC_Facebookcommerce_Pixel::set_access_token($settings_access_token);
|
196 |
}
|
197 |
}
|
198 |
|
235 |
$this->settings[ self::SETTING_ENABLE_ADVANCED_MATCHING ] = $advanced_matching_enabled;
|
236 |
}
|
237 |
|
238 |
+
//For now, the values of use s2s and access token will be the ones returned from WC_Facebookcommerce_Pixel
|
239 |
+
$use_s2s = WC_Facebookcommerce_Pixel::get_use_s2s();
|
240 |
+
$this->settings[self::SETTING_USE_S2S] = $use_s2s;
|
241 |
+
|
242 |
+
$access_token = WC_Facebookcommerce_Pixel::get_access_token();
|
243 |
+
$this->settings[self::SETTING_ACCESS_TOKEN] = $access_token;
|
244 |
+
|
245 |
if ( ! class_exists( 'WC_Facebookcommerce_Utils' ) ) {
|
246 |
include_once 'includes/fbutils.php';
|
247 |
}
|
250 |
|
251 |
if ( ! class_exists( 'WC_Facebookcommerce_Graph_API' ) ) {
|
252 |
include_once 'includes/fbgraph.php';
|
253 |
+
$this->fbgraph = new WC_Facebookcommerce_Graph_API( facebook_for_woocommerce()->get_connection_handler()->get_access_token() );
|
254 |
}
|
255 |
|
256 |
WC_Facebookcommerce_Utils::$fbgraph = $this->fbgraph;
|
260 |
|
261 |
$this->init_pixel();
|
262 |
|
|
|
|
|
263 |
if ( ! class_exists( 'WC_Facebookcommerce_EventsTracker' ) ) {
|
264 |
include_once 'includes/fbutils.php';
|
265 |
}
|
298 |
}
|
299 |
|
300 |
add_action( 'admin_notices', array( $this, 'checks' ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
301 |
|
302 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'load_assets' ) );
|
|
|
|
|
|
|
|
|
303 |
|
304 |
add_action(
|
305 |
'wp_ajax_ajax_sync_all_fb_products',
|
335 |
self::FB_PRIORITY_MID
|
336 |
);
|
337 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
338 |
// don't duplicate product FBID meta
|
339 |
add_filter( 'woocommerce_duplicate_product_exclude_meta', [ $this, 'fb_duplicate_product_reset_meta' ] );
|
340 |
|
341 |
+
// add product processing hooks if the plugin is configured only
|
342 |
+
if ( $this->is_configured() && $this->get_product_catalog_id() ) {
|
343 |
+
|
344 |
+
// on_product_save() must run with priority larger than 20 to make sure WooCommerce has a chance to save the submitted product information
|
345 |
+
add_action( 'woocommerce_process_product_meta', [ $this, 'on_product_save' ], 40 );
|
346 |
|
347 |
add_action(
|
348 |
'woocommerce_product_quick_edit_save',
|
358 |
1 // Args passed to on_quick_and_bulk_edit_save ('product')
|
359 |
);
|
360 |
|
361 |
+
add_action( 'before_delete_post', [ $this, 'on_product_delete' ] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
362 |
|
363 |
+
add_action( 'add_meta_boxes', array( $this, 'fb_product_metabox' ), 10, 1 );
|
364 |
|
365 |
add_action(
|
366 |
'transition_post_status',
|
416 |
$this->events_tracker = new WC_Facebookcommerce_EventsTracker( $user_info );
|
417 |
}
|
418 |
|
419 |
+
// initialize the messenger chat features
|
420 |
+
$this->messenger_chat = new WC_Facebookcommerce_MessengerChat( [
|
421 |
+
'fb_page_id' => $this->get_facebook_page_id(),
|
422 |
+
'facebook_jssdk_version' => $this->get_js_sdk_version(),
|
423 |
+
] );
|
|
|
|
|
|
|
|
|
|
|
|
|
424 |
}
|
425 |
|
426 |
public function load_background_sync_process() {
|
445 |
if ( isset( $_POST['request_time'] ) ) {
|
446 |
$request_time = esc_js( sanitize_text_field( wp_unslash( $_POST['request_time'] ) ) );
|
447 |
}
|
448 |
+
|
449 |
+
if ( facebook_for_woocommerce()->get_connection_handler()->get_access_token() ) {
|
450 |
+
|
451 |
if ( isset( $this->background_processor ) ) {
|
452 |
$is_processing = $this->background_processor->handle_cron_healthcheck();
|
453 |
$remaining = $this->background_processor->get_item_count();
|
470 |
'background' => false,
|
471 |
);
|
472 |
}
|
473 |
+
|
474 |
printf( json_encode( $response ) );
|
475 |
wp_die();
|
476 |
}
|
543 |
wp_enqueue_script(
|
544 |
'wc_facebook_metabox_jsx',
|
545 |
plugins_url(
|
546 |
+
'/assets/js/facebook-metabox.min.js',
|
547 |
__FILE__
|
548 |
+
),
|
549 |
+
[],
|
550 |
+
\WC_Facebookcommerce::PLUGIN_VERSION
|
551 |
);
|
552 |
wp_localize_script(
|
553 |
'wc_facebook_metabox_jsx',
|
585 |
if ( $fb_product_group_id ) {
|
586 |
|
587 |
?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
588 |
|
589 |
+
<?php echo esc_html__( 'Facebook ID:', 'facebook-for-woocommerce' ); ?> <a href="https://facebook.com/<?php echo esc_attr( $fb_product_group_id ); ?>"
|
590 |
+
target="_blank"><?php echo esc_html( $fb_product_group_id ); ?></a>
|
591 |
|
592 |
+
<?php if ( WC_Facebookcommerce_Utils::is_variable_type( $woo_product->get_type() ) ) : ?>
|
|
|
|
|
593 |
|
594 |
+
<?php if ( $product_item_ids_by_variation_id = $this->get_variation_product_item_ids( $woo_product, $fb_product_group_id ) ) : ?>
|
595 |
|
596 |
+
<p>
|
597 |
+
<?php echo esc_html__( 'Variant IDs:', 'facebook-for-woocommerce' ); ?><br/>
|
598 |
|
599 |
+
<?php foreach ( $product_item_ids_by_variation_id as $variation_id => $product_item_id ) : ?>
|
|
|
|
|
|
|
600 |
|
601 |
+
<?php echo esc_html( $variation_id ); ?>: <a href="https://facebook.com/<?php echo esc_attr( $product_item_id ); ?>"
|
602 |
+
target="_blank"><?php echo esc_html( $product_item_id ); ?></a><br/>
|
|
|
|
|
|
|
|
|
|
|
|
|
603 |
|
604 |
+
<?php endforeach; ?>
|
605 |
</p>
|
|
|
|
|
606 |
|
607 |
+
<?php endif; ?>
|
608 |
+
|
609 |
+
<?php endif; ?>
|
|
|
|
|
|
|
|
|
610 |
|
|
|
|
|
611 |
<input name="is_product_page" type="hidden" value="1"/>
|
612 |
|
613 |
<p/>
|
635 |
}
|
636 |
|
637 |
|
638 |
+
/**
|
639 |
+
* Gets a list of Product Item IDs indexed by the ID of the variation.
|
640 |
+
*
|
641 |
+
* @since 2.0.0
|
642 |
+
*
|
643 |
+
* @param string $product_group_id product group ID
|
644 |
+
* @return array
|
645 |
+
*/
|
646 |
+
private function get_variation_product_item_ids( $product, $product_group_id ) {
|
647 |
+
|
648 |
+
$product_item_ids_by_variation_id = [];
|
649 |
+
$missing_product_item_ids = [];
|
650 |
+
|
651 |
+
// get the product item IDs from meta data and build a list of variations that don't have a product item ID stored
|
652 |
+
foreach ( $product->get_children() as $variation_id ) {
|
653 |
+
|
654 |
+
if ( $variation = wc_get_product( $variation_id ) ) {
|
655 |
+
|
656 |
+
if ( $product_item_id = $variation->get_meta( self::FB_PRODUCT_ITEM_ID ) ) {
|
657 |
+
|
658 |
+
$product_item_ids_by_variation_id[ $variation_id ] = $product_item_id;
|
659 |
+
|
660 |
+
} else {
|
661 |
+
|
662 |
+
$retailer_id = WC_Facebookcommerce_Utils::get_fb_retailer_id( $variation );
|
663 |
+
|
664 |
+
$missing_product_item_ids[ $retailer_id ] = $variation;
|
665 |
+
|
666 |
+
$product_item_ids_by_variation_id[ $variation_id ] = null;
|
667 |
+
}
|
668 |
+
}
|
669 |
+
}
|
670 |
+
|
671 |
+
// use the Graph API to try to find and store the product item IDs for variations that don't have a value yet
|
672 |
+
if ( $missing_product_item_ids ) {
|
673 |
+
|
674 |
+
$product_item_ids = $this->find_variation_product_item_ids( $product_group_id );
|
675 |
+
|
676 |
+
foreach ( $missing_product_item_ids as $retailer_id => $variation ) {
|
677 |
+
|
678 |
+
if ( isset( $product_item_ids[ $retailer_id ] ) ) {
|
679 |
+
|
680 |
+
$variation->update_meta_data( self::FB_PRODUCT_ITEM_ID, $product_item_ids[ $retailer_id ] );
|
681 |
+
$variation->save_meta_data();
|
682 |
+
|
683 |
+
$product_item_ids_by_variation_id[ $variation->get_id() ] = $product_item_ids[ $retailer_id ];
|
684 |
+
}
|
685 |
+
}
|
686 |
+
}
|
687 |
+
|
688 |
+
return $product_item_ids_by_variation_id;
|
689 |
+
}
|
690 |
+
|
691 |
+
|
692 |
+
/**
|
693 |
+
* Uses the Graph API to return a list of Product Item IDs indexed by the variation's retailer ID.
|
694 |
+
*
|
695 |
+
* @since 2.0.0
|
696 |
+
*
|
697 |
+
* @param string $product_group_id product group ID
|
698 |
+
* @return array
|
699 |
+
*/
|
700 |
+
private function find_variation_product_item_ids( $product_group_id ) {
|
701 |
+
|
702 |
+
$product_item_ids = [];
|
703 |
+
|
704 |
+
try {
|
705 |
+
|
706 |
+
$response = facebook_for_woocommerce()->get_api()->get_product_group_products( $product_group_id );
|
707 |
+
|
708 |
+
do {
|
709 |
+
|
710 |
+
$product_item_ids = array_merge( $product_item_ids, $response->get_ids() );
|
711 |
+
|
712 |
+
// get up to two additional pages of results
|
713 |
+
} while ( $response = facebook_for_woocommerce()->get_api()->next( $response, 2 ) );
|
714 |
+
|
715 |
+
} catch ( Framework\SV_WC_API_Exception $e ) {
|
716 |
+
|
717 |
+
$message = sprintf( 'There was an error trying to find the IDs for Product Items in the Product Group %s: %s', $product_group_id, $e->getMessage() );
|
718 |
+
|
719 |
+
facebook_for_woocommerce()->log( $message );
|
720 |
+
}
|
721 |
+
|
722 |
+
return $product_item_ids;
|
723 |
+
}
|
724 |
+
|
725 |
+
|
726 |
/**
|
727 |
* Gets the total of published products.
|
728 |
*
|
729 |
* @return int
|
730 |
*/
|
731 |
+
public function get_product_count() {
|
732 |
|
733 |
$args = [
|
734 |
'post_type' => 'product',
|
757 |
wp_enqueue_script(
|
758 |
'wc_facebook_infobanner_jsx',
|
759 |
plugins_url(
|
760 |
+
'/assets/js/facebook-infobanner.min.js',
|
761 |
__FILE__
|
762 |
+
),
|
763 |
+
[],
|
764 |
+
\WC_Facebookcommerce::PLUGIN_VERSION
|
765 |
);
|
766 |
wp_localize_script(
|
767 |
'wc_facebook_infobanner_jsx',
|
774 |
plugins_url(
|
775 |
'/assets/css/facebook-infobanner.css',
|
776 |
__FILE__
|
777 |
+
),
|
778 |
+
[],
|
779 |
+
\WC_Facebookcommerce::PLUGIN_VERSION
|
780 |
);
|
781 |
|
782 |
if ( ! facebook_for_woocommerce()->is_plugin_settings() ) {
|
819 |
feedMigrated: <?php echo $this->is_feed_migrated() ? 'true' : 'false'; ?>,
|
820 |
samples: <?php echo $this->get_sample_product_feed(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
821 |
},
|
|
|
|
|
|
|
822 |
};
|
823 |
|
824 |
</script>
|
827 |
$ajax_data = [
|
828 |
'nonce' => wp_create_nonce( 'wc_facebook_settings_jsx' ),
|
829 |
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
830 |
wp_localize_script(
|
831 |
'wc_facebook_settings_jsx',
|
832 |
'wc_facebook_settings_jsx',
|
837 |
plugins_url(
|
838 |
'/assets/css/facebook.css',
|
839 |
__FILE__
|
840 |
+
),
|
841 |
+
[],
|
842 |
+
\WC_Facebookcommerce::PLUGIN_VERSION
|
843 |
);
|
844 |
}
|
845 |
|
847 |
/**
|
848 |
* Checks the product type and calls the corresponding on publish method.
|
849 |
*
|
|
|
850 |
* @internal
|
851 |
*
|
852 |
* @since 1.10.0
|
861 |
return;
|
862 |
}
|
863 |
|
864 |
+
$sync_mode = isset( $_POST['wc_facebook_sync_mode'] ) ? $_POST['wc_facebook_sync_mode'] : Admin::SYNC_MODE_SYNC_DISABLED;
|
865 |
+
$sync_enabled = Admin::SYNC_MODE_SYNC_DISABLED !== $sync_mode;
|
866 |
+
|
867 |
+
if ( Admin::SYNC_MODE_SYNC_AND_SHOW === $sync_mode && $product->is_virtual() ) {
|
868 |
+
// force to Sync and hide
|
869 |
+
$sync_mode = Admin::SYNC_MODE_SYNC_AND_HIDE;
|
870 |
+
}
|
871 |
|
872 |
if ( ! $product->is_type( 'variable' ) ) {
|
873 |
|
874 |
if ( $sync_enabled ) {
|
875 |
|
876 |
Products::enable_sync_for_products( [ $product ] );
|
877 |
+
Products::set_product_visibility( $product, Admin::SYNC_MODE_SYNC_AND_HIDE !== $sync_mode );
|
878 |
|
879 |
$this->save_product_settings( $product );
|
880 |
|
881 |
} else {
|
882 |
|
883 |
+
// if previously enabled, add a notice on the next page load
|
884 |
+
if ( Products::is_sync_enabled_for_product( $product ) ) {
|
885 |
+
Admin::add_product_disabled_sync_notice();
|
886 |
+
}
|
887 |
+
|
888 |
Products::disable_sync_for_products( [ $product ] );
|
889 |
}
|
890 |
}
|
891 |
|
892 |
+
if ( $sync_enabled ) {
|
|
|
|
|
|
|
893 |
|
894 |
switch ( $product->get_type() ) {
|
895 |
|
910 |
break;
|
911 |
}
|
912 |
}
|
|
|
|
|
913 |
}
|
914 |
|
915 |
|
945 |
}
|
946 |
|
947 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
948 |
/**
|
949 |
* Deletes a product from Facebook.
|
950 |
*
|
951 |
+
* @param int $product_id product ID
|
952 |
*/
|
953 |
+
public function on_product_delete( $product_id ) {
|
954 |
|
955 |
+
$product = wc_get_product( $product_id );
|
956 |
|
957 |
+
// bail if product does not exist
|
958 |
+
if ( ! $product instanceof \WC_Product ) {
|
|
|
959 |
return;
|
960 |
}
|
961 |
|
962 |
+
/**
|
963 |
+
* bail if not enabled for sync, except if explicitly deleting from the metabox
|
964 |
+
* @see ajax_delete_fb_product()
|
965 |
+
*/
|
966 |
+
if ( ( ! is_ajax() || ! isset( $_POST['action'] ) || 'ajax_delete_fb_product' !== $_POST['action'] )
|
967 |
+
&& ! Products::product_should_be_synced( $product ) ) {
|
968 |
+
|
969 |
return;
|
970 |
}
|
971 |
|
972 |
+
if ( $product->is_type( 'variation' ) ) {
|
973 |
+
|
974 |
+
$retailer_id = \WC_Facebookcommerce_Utils::get_fb_retailer_id( $product );
|
975 |
+
|
976 |
+
// enqueue variation to be deleted in the background
|
977 |
+
facebook_for_woocommerce()->get_products_sync_handler()->delete_products( [ $retailer_id ] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
978 |
|
979 |
+
} elseif ( $product->is_type( 'variable' ) ) {
|
980 |
+
|
981 |
+
$retailer_ids = [];
|
982 |
+
|
983 |
+
foreach ( $product->get_children() as $variation_id ) {
|
984 |
+
|
985 |
+
$variation = wc_get_product( $variation_id );
|
986 |
+
|
987 |
+
if ( $variation instanceof \WC_Product ) {
|
988 |
+
$retailer_ids[] = \WC_Facebookcommerce_Utils::get_fb_retailer_id( $variation );
|
989 |
+
}
|
990 |
+
}
|
991 |
+
|
992 |
+
// enqueue variations to be deleted in the background
|
993 |
+
facebook_for_woocommerce()->get_products_sync_handler()->delete_products( $retailer_ids );
|
994 |
+
|
995 |
+
$this->delete_product_group( $product_id );
|
996 |
+
|
997 |
+
} else {
|
998 |
+
|
999 |
+
$this->delete_product_item( $product_id );
|
1000 |
+
$this->delete_product_group( $product_id );
|
1001 |
+
}
|
1002 |
}
|
1003 |
|
1004 |
|
1012 |
* @param \WP_post $post
|
1013 |
*/
|
1014 |
public function fb_change_product_published_status( $new_status, $old_status, $post ) {
|
|
|
1015 |
|
1016 |
if ( ! $post ) {
|
1017 |
return;
|
1021 |
|
1022 |
$product = wc_get_product( $post->ID );
|
1023 |
|
1024 |
+
// bail if we couldn't retrieve a valid product object or the product isn't enabled for sync
|
1025 |
+
//
|
1026 |
+
// Note that while moving a variable product to the trash, this method is called for each one of the
|
1027 |
+
// variations before it gets called with the variable product. As a result, Products::product_should_be_synced()
|
1028 |
+
// always returns false for the variable product (since all children are in the trash at that point).
|
1029 |
+
// This causes update_fb_visibility() to be called on simple products and product variations only.
|
1030 |
if ( ! $product instanceof \WC_Product || ! Products::product_should_be_synced( $product ) ) {
|
1031 |
return;
|
1032 |
}
|
1035 |
// change from trash status -> publish status
|
1036 |
// no need to update for change from trash <-> unpublish status
|
1037 |
if ( ( $old_status === 'publish' && $new_status !== 'publish' ) || ( $old_status === 'trash' && $new_status === 'publish' ) ) {
|
1038 |
+
$this->update_fb_visibility( $product, $visibility );
|
1039 |
}
|
1040 |
}
|
1041 |
|
1046 |
* Will determine product type (simple or variable) and delegate to
|
1047 |
* appropriate handler.
|
1048 |
*
|
1049 |
+
* @param int $product_id product ID
|
1050 |
*/
|
1051 |
+
public function on_product_publish( $product_id ) {
|
|
|
|
|
|
|
|
|
|
|
1052 |
|
1053 |
+
// bail if the plugin is not configured properly
|
1054 |
+
if ( ! $this->is_configured() || ! $this->get_product_catalog_id() ) {
|
1055 |
return;
|
1056 |
}
|
1057 |
|
1058 |
+
$product = wc_get_product( $product_id );
|
1059 |
|
1060 |
+
if ( ! $this->product_should_be_synced( $product ) ) {
|
|
|
1061 |
return;
|
1062 |
}
|
1063 |
|
1064 |
+
if ( $product->is_type( 'variable' ) ) {
|
1065 |
+
$this->on_variable_product_publish( $product_id );
|
1066 |
} else {
|
1067 |
+
$this->on_simple_product_publish( $product_id );
|
1068 |
}
|
1069 |
}
|
1070 |
|
1074 |
* this function will delete the product from FB Page as well.
|
1075 |
*/
|
1076 |
function delete_on_out_of_stock( $wp_id, $woo_product ) {
|
1077 |
+
|
1078 |
+
if ( Products::product_should_be_deleted( $woo_product ) ) {
|
1079 |
+
|
1080 |
$this->delete_product_item( $wp_id );
|
1081 |
return true;
|
1082 |
}
|
1083 |
+
|
1084 |
return false;
|
1085 |
}
|
1086 |
|
1093 |
*/
|
1094 |
function on_variable_product_publish( $wp_id, $woo_product = null ) {
|
1095 |
|
1096 |
+
if ( ! $woo_product instanceof \WC_Facebook_Product ) {
|
1097 |
+
$woo_product = new \WC_Facebook_Product( $wp_id );
|
1098 |
}
|
1099 |
|
1100 |
+
if ( ! $this->product_should_be_synced( $woo_product->woo_product ) ) {
|
1101 |
return;
|
1102 |
}
|
1103 |
|
1104 |
+
if ( $this->delete_on_out_of_stock( $wp_id, $woo_product->woo_product ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
1105 |
return;
|
1106 |
}
|
1107 |
|
1108 |
+
// Check if product group has been published to FB. If not, it's new.
|
1109 |
+
// If yes, loop through variants and see if product items are published.
|
1110 |
+
$fb_product_group_id = $this->get_product_fbid( self::FB_PRODUCT_GROUP_ID, $wp_id, $woo_product );
|
|
|
|
|
1111 |
|
1112 |
if ( $fb_product_group_id ) {
|
1113 |
|
1115 |
|
1116 |
$this->update_product_group( $woo_product );
|
1117 |
|
1118 |
+
} else {
|
|
|
1119 |
|
1120 |
+
$retailer_id = WC_Facebookcommerce_Utils::get_fb_retailer_id( $woo_product->woo_product );
|
|
|
|
|
|
|
1121 |
|
1122 |
+
$this->create_product_group( $woo_product, $retailer_id, true );
|
1123 |
+
}
|
1124 |
|
1125 |
+
$variation_ids = [];
|
|
|
|
|
|
|
1126 |
|
1127 |
+
// scheduled update for each variation that should be synced
|
1128 |
+
foreach ( $woo_product->get_children() as $variation_id ) {
|
1129 |
|
1130 |
+
$variation = wc_get_product( $variation_id );
|
1131 |
+
|
1132 |
+
if ( $variation instanceof \WC_Product && $this->product_should_be_synced( $variation ) && ! $this->delete_on_out_of_stock( $variation_id, $variation ) ) {
|
1133 |
+
$variation_ids[] = $variation_id;
|
1134 |
+
}
|
1135 |
}
|
1136 |
+
|
1137 |
+
facebook_for_woocommerce()->get_products_sync_handler()->create_or_update_products( $variation_ids );
|
1138 |
}
|
1139 |
|
1140 |
|
1148 |
*/
|
1149 |
function on_simple_product_publish( $wp_id, $woo_product = null, &$parent_product = null ) {
|
1150 |
|
1151 |
+
if ( ! $woo_product instanceof \WC_Facebook_Product ) {
|
1152 |
+
$woo_product = new \WC_Facebook_Product( $wp_id, $parent_product );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1153 |
}
|
1154 |
|
1155 |
+
if ( ! $this->product_should_be_synced( $woo_product->woo_product ) ) {
|
|
|
1156 |
return;
|
1157 |
}
|
1158 |
|
1159 |
+
if ( $this->delete_on_out_of_stock( $wp_id, $woo_product->woo_product ) ) {
|
1160 |
return;
|
1161 |
}
|
1162 |
|
1205 |
}
|
1206 |
}
|
1207 |
|
|
|
|
|
1208 |
|
1209 |
+
/**
|
1210 |
+
* Determines whether the product with the given ID should be synced.
|
1211 |
+
*
|
1212 |
+
* TODO: can we move this logic into Products::product_should_be_synced()? {WV 2020-05-22}
|
1213 |
+
*
|
1214 |
+
* @since 2.0.0
|
1215 |
+
*
|
1216 |
+
* @param \WC_Product|false $product product object
|
1217 |
+
*/
|
1218 |
+
public function product_should_be_synced( $product ) {
|
1219 |
|
1220 |
+
$should_be_synced = true;
|
1221 |
+
|
1222 |
+
if ( ! $this->is_product_sync_enabled() ) {
|
1223 |
+
$should_be_synced = false;
|
1224 |
+
}
|
1225 |
+
|
1226 |
+
// can't sync if we don't have a valid product object
|
1227 |
+
if ( $should_be_synced && ! $product instanceof \WC_Product ) {
|
1228 |
+
$should_be_synced = false;
|
1229 |
+
}
|
1230 |
+
|
1231 |
+
// only published product should be synced
|
1232 |
+
if ( $should_be_synced && 'publish' !== get_post_status( $product->get_id() ) ) {
|
1233 |
+
$should_be_synced = false;
|
1234 |
+
}
|
1235 |
+
|
1236 |
+
// make sure the given product is enabled for sync
|
1237 |
+
if ( $should_be_synced && ! Products::product_should_be_synced( $product ) ) {
|
1238 |
+
$should_be_synced = false;
|
1239 |
}
|
1240 |
+
|
1241 |
+
return $should_be_synced;
|
1242 |
}
|
1243 |
|
1244 |
+
|
1245 |
/**
|
1246 |
* Create product group and product, store fb-specific info
|
1247 |
**/
|
1271 |
'retailer_id' => $retailer_id,
|
1272 |
);
|
1273 |
|
|
|
|
|
|
|
|
|
1274 |
if ( $variants ) {
|
1275 |
$product_group_data['variants'] =
|
1276 |
$woo_product->prepare_variants_for_group();
|
1289 |
if ( $create_product_group_result ) {
|
1290 |
$decode_result = WC_Facebookcommerce_Utils::decode_json( $create_product_group_result['body'] );
|
1291 |
$fb_product_group_id = $decode_result->id;
|
1292 |
+
|
1293 |
update_post_meta(
|
1294 |
$woo_product->get_id(),
|
1295 |
self::FB_PRODUCT_GROUP_ID,
|
1309 |
}
|
1310 |
|
1311 |
function create_product_item( $woo_product, $retailer_id, $product_group_id ) {
|
1312 |
+
|
|
|
1313 |
$product_data = $woo_product->prepare_product( $retailer_id );
|
1314 |
if ( ! $product_data['price'] ) {
|
1315 |
return 0;
|
1316 |
}
|
1317 |
|
|
|
|
|
1318 |
$product_result = $this->check_api_result(
|
1319 |
$this->fbgraph->create_product_item(
|
1320 |
$product_group_id,
|
1430 |
* Saves settings via AJAX (to preserve window context for onboarding).
|
1431 |
*
|
1432 |
* @internal
|
1433 |
+
*
|
1434 |
+
* @deprecated 2.0.0
|
1435 |
*/
|
1436 |
public function ajax_save_fb_settings() {
|
1437 |
|
1438 |
+
wc_deprecated_function( __METHOD__, '2.0.0' );
|
1439 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1440 |
|
1441 |
+
/**
|
1442 |
+
* Delete all settings via AJAX
|
1443 |
+
*
|
1444 |
+
* @deprecated 2.0.0
|
1445 |
+
*/
|
1446 |
+
function ajax_delete_fb_settings() {
|
1447 |
|
1448 |
+
wc_deprecated_function( __METHOD__, '2.0.0' );
|
1449 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1450 |
|
1451 |
/**
|
1452 |
* Checks the feed upload status (FBE v1.0).
|
1474 |
|
1475 |
check_ajax_referer( 'wc_facebook_settings_jsx' );
|
1476 |
|
1477 |
+
if ( $this->is_configured() ) {
|
1478 |
|
1479 |
$response = [
|
1480 |
'connected' => true,
|
1720 |
sprintf(
|
1721 |
'Products may be out of Sync with Facebook due to your recent ' . $action_name . '.' .
|
1722 |
' <a href="%s&fb_force_resync=true&remove_sticky=true">Re-Sync them with FB.</a>',
|
1723 |
+
facebook_for_woocommerce()->get_settings_url()
|
1724 |
)
|
1725 |
);
|
1726 |
}
|
1757 |
public function checks() {
|
1758 |
|
1759 |
// TODO improve this by checking the settings page with Framework method and ensure error notices are displayed under the Integration sections {FN 2020-01-30}
|
1760 |
+
if ( isset( $_GET['page'] ) && 'wc-facebook' === $_GET['page'] ) {
|
1761 |
$this->display_errors();
|
1762 |
}
|
1763 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1764 |
$this->maybe_display_facebook_api_messages();
|
1765 |
}
|
1766 |
|
1797 |
'description' => strip_tags( $product_data['description'] ),
|
1798 |
'id' => $product_data['retailer_id'],
|
1799 |
'image_link' => $product_data['image_url'],
|
1800 |
+
'brand' => Framework\SV_WC_Helper::str_truncate( wp_strip_all_tags( WC_Facebookcommerce_Utils::get_store_name() ), 100 ),
|
1801 |
'link' => $product_data['url'],
|
1802 |
'price' => $product_data['price'] . ' ' . get_woocommerce_currency(),
|
1803 |
];
|
2002 |
throw new Framework\SV_WC_Plugin_Exception( __( 'Product sync is disabled.', 'facebook-for-woocommerce' ) );
|
2003 |
}
|
2004 |
|
2005 |
+
if ( ! $this->is_configured() || ! $this->get_product_catalog_id() ) {
|
2006 |
|
2007 |
+
WC_Facebookcommerce_Utils::log( sprintf( 'Not syncing, the plugin is not configured or the Catalog ID is missing' ) );
|
2008 |
|
2009 |
+
throw new Framework\SV_WC_Plugin_Exception( __( 'The plugin is not configured or the Catalog ID is missing.', 'facebook-for-woocommerce' ) );
|
2010 |
}
|
2011 |
|
2012 |
$this->remove_resync_message();
|
2044 |
throw new Framework\SV_WC_Plugin_Exception( __( "We've detected that your Facebook Product Catalog is no longer valid. This may happen if it was deleted, but could also be a temporary error. If the error persists, please click Manage connection > Advanced Options > Remove and setup the plugin again.", 'facebook-for-woocommerce' ) );
|
2045 |
}
|
2046 |
|
|
|
|
|
|
|
|
|
|
|
|
|
2047 |
// Get all published posts. First unsynced then already-synced.
|
2048 |
$post_ids_new = WC_Facebookcommerce_Utils::get_wp_posts(
|
2049 |
self::FB_PRODUCT_GROUP_ID,
|
2165 |
* @since 1.10.2
|
2166 |
*
|
2167 |
* @throws Framework\SV_WC_Plugin_Exception
|
2168 |
+
* @return bool
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2169 |
*/
|
2170 |
+
public function sync_facebook_products_using_feed() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2171 |
|
2172 |
+
if ( ! $this->is_product_sync_enabled() ) {
|
2173 |
+
WC_Facebookcommerce_Utils::log( 'Sync to Facebook is disabled' );
|
2174 |
+
|
2175 |
+
throw new Framework\SV_WC_Plugin_Exception( __( 'Product sync is disabled.', 'facebook-for-woocommerce' ) );
|
|
|
2176 |
}
|
2177 |
|
2178 |
+
if ( ! $this->is_configured() || ! $this->get_product_catalog_id() ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
2179 |
|
2180 |
+
WC_Facebookcommerce_Utils::log( sprintf( 'Not syncing, the plugin is not configured or the Catalog ID is missing' ) );
|
2181 |
|
2182 |
+
throw new Framework\SV_WC_Plugin_Exception( __( 'The plugin is not configured or the Catalog ID is missing.', 'facebook-for-woocommerce' ) );
|
2183 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2184 |
|
2185 |
+
$this->remove_resync_message();
|
|
|
2186 |
|
2187 |
+
if ( ! $this->fbgraph->is_product_catalog_valid( $this->get_product_catalog_id() ) ) {
|
2188 |
|
2189 |
+
WC_Facebookcommerce_Utils::log( 'Not syncing, invalid product catalog!' );
|
2190 |
+
WC_Facebookcommerce_Utils::fblog(
|
2191 |
+
'Tried to sync with an invalid product catalog!',
|
2192 |
+
array(),
|
2193 |
+
true
|
2194 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2195 |
|
2196 |
+
throw new Framework\SV_WC_Plugin_Exception( __( "We've detected that your Facebook Product Catalog is no longer valid. This may happen if it was deleted, but could also be a temporary error. If the error persists, please click Manage connection > Advanced Options > Remove and setup the plugin again.", 'facebook-for-woocommerce' ) );
|
2197 |
+
}
|
|
|
|
|
2198 |
|
2199 |
+
if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) {
|
2200 |
+
include_once 'includes/fbproductfeed.php';
|
2201 |
+
}
|
2202 |
+
if ( $this->test_mode ) {
|
2203 |
+
$this->fbproductfeed = new WC_Facebook_Product_Feed_Test_Mock(
|
2204 |
+
$this->get_product_catalog_id(),
|
2205 |
+
$this->fbgraph,
|
2206 |
+
$this->get_feed_id()
|
2207 |
+
);
|
2208 |
+
} else {
|
2209 |
+
$this->fbproductfeed = new WC_Facebook_Product_Feed(
|
2210 |
+
$this->get_product_catalog_id(),
|
2211 |
+
$this->fbgraph,
|
2212 |
+
$this->get_feed_id()
|
2213 |
+
);
|
2214 |
}
|
2215 |
|
2216 |
+
if ( ! $this->fbproductfeed->sync_all_products_using_feed() ) {
|
|
|
|
|
|
|
2217 |
|
2218 |
+
WC_Facebookcommerce_Utils::fblog( 'Sync all products using feed, curl failed', [], true );
|
|
|
2219 |
|
2220 |
+
throw new Framework\SV_WC_Plugin_Exception( __( "We couldn't create the feed or upload the product information.", 'facebook-for-woocommerce' ) );
|
|
|
2221 |
}
|
2222 |
|
2223 |
+
$this->update_feed_id( $this->fbproductfeed->feed_id );
|
2224 |
+
$this->update_upload_id( $this->fbproductfeed->upload_id );
|
2225 |
+
|
2226 |
+
update_option(
|
2227 |
+
$this->get_option_key(),
|
2228 |
+
apply_filters( 'woocommerce_settings_api_sanitized_fields_' . $this->id, $this->settings )
|
2229 |
+
);
|
2230 |
+
|
2231 |
+
wp_reset_postdata();
|
2232 |
|
2233 |
+
return true;
|
2234 |
}
|
2235 |
|
2236 |
|
2237 |
/**
|
2238 |
+
* Syncs Facebook products using a Feed.
|
2239 |
*
|
2240 |
+
* TODO: deprecate this methid in 1.11.0 or newer {WV 2020-03-12}
|
2241 |
*
|
2242 |
+
* @see https://developers.facebook.com/docs/marketing-api/fbe/fbe1/guides/feed-approach
|
2243 |
*
|
2244 |
+
* @return bool
|
|
|
|
|
2245 |
*/
|
2246 |
+
public function sync_all_fb_products_using_feed() {
|
|
|
|
|
|
|
|
|
|
|
|
|
2247 |
|
2248 |
+
try {
|
2249 |
+
$sync_started = $this->sync_facebook_products_using_feed();
|
2250 |
+
} catch ( Framework\SV_WC_Plugin_Exception $e ) {
|
2251 |
+
$sync_started = false;
|
2252 |
+
}
|
2253 |
|
2254 |
+
return $sync_started;
|
2255 |
+
}
|
2256 |
|
|
|
|
|
|
|
|
|
|
|
|
|
2257 |
|
2258 |
+
/**
|
2259 |
+
* Toggles product visibility via AJAX.
|
2260 |
+
*
|
2261 |
+
* @internal
|
2262 |
+
* @deprecated since 1.10.0
|
2263 |
+
**/
|
2264 |
+
public function ajax_fb_toggle_visibility() {
|
2265 |
|
2266 |
+
wc_deprecated_function( __METHOD__, '1.10.0' );
|
2267 |
}
|
2268 |
|
2269 |
|
2270 |
/**
|
2271 |
+
* Initializes the settings form fields.
|
|
|
|
|
2272 |
*
|
2273 |
+
* @since 1.0.0
|
2274 |
+
* @deprecated 2.0.0
|
2275 |
*
|
2276 |
+
* @internal
|
|
|
|
|
|
|
2277 |
*/
|
2278 |
+
public function init_form_fields() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2279 |
|
2280 |
+
wc_deprecated_function( __METHOD__, '2.0.0' );
|
2281 |
}
|
2282 |
|
2283 |
|
2284 |
/**
|
2285 |
+
* Processes and saves options.
|
2286 |
*
|
2287 |
+
* TODO: remove this or move it to the new settings processing
|
2288 |
*
|
2289 |
+
* @internal
|
2290 |
+
*
|
2291 |
+
* @since 1.10.0
|
2292 |
+
* @deprecated 2.0.0
|
2293 |
*/
|
2294 |
+
public function process_admin_options() {
|
2295 |
|
2296 |
+
wc_deprecated_function( __METHOD__, '2.0.0' );
|
|
|
|
|
|
|
|
|
2297 |
}
|
2298 |
|
2299 |
|
2513 |
* @param string $page_id the configured Facebook page ID
|
2514 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
2515 |
*/
|
2516 |
+
return (string) apply_filters( 'wc_facebook_page_id', get_option( self::SETTING_FACEBOOK_PAGE_ID, '' ), $this );
|
2517 |
}
|
2518 |
|
2519 |
|
2534 |
* @param string $pixel_id the configured Facebook pixel ID
|
2535 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
2536 |
*/
|
2537 |
+
return (string) apply_filters( 'wc_facebook_pixel_id', get_option( self::SETTING_FACEBOOK_PIXEL_ID, '' ), $this );
|
2538 |
+
}
|
2539 |
+
|
2540 |
+
/**
|
2541 |
+
* Gets the configured use s2s flag.
|
2542 |
+
*
|
2543 |
+
* @return bool
|
2544 |
+
*/
|
2545 |
+
public function is_use_s2s_enabled() {
|
2546 |
+
return WC_Facebookcommerce_Pixel::get_use_s2s();
|
2547 |
+
}
|
2548 |
+
|
2549 |
+
/**
|
2550 |
+
* Gets the configured access token
|
2551 |
+
*
|
2552 |
+
* @return string
|
2553 |
+
*/
|
2554 |
+
public function get_access_token() {
|
2555 |
+
return WC_Facebookcommerce_Pixel::get_access_token();
|
2556 |
}
|
2557 |
|
2558 |
|
2573 |
* @param int[] $category_ids the configured excluded product category IDs
|
2574 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
2575 |
*/
|
2576 |
+
return (array) apply_filters( 'wc_facebook_excluded_product_category_ids', get_option( self::SETTING_EXCLUDED_PRODUCT_CATEGORY_IDS, [] ), $this );
|
2577 |
}
|
2578 |
|
2579 |
|
2594 |
* @param int[] $tag_ids the configured excluded product tag IDs
|
2595 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
2596 |
*/
|
2597 |
+
return (array) apply_filters( 'wc_facebook_excluded_product_tag_ids', get_option( self::SETTING_EXCLUDED_PRODUCT_TAG_IDS, [] ), $this );
|
2598 |
}
|
2599 |
|
2600 |
|
2615 |
* @param string $mode the configured product description mode
|
2616 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
2617 |
*/
|
2618 |
+
$mode = (string) apply_filters( 'wc_facebook_product_description_mode', get_option( self::SETTING_PRODUCT_DESCRIPTION_MODE, self::PRODUCT_DESCRIPTION_MODE_STANDARD ), $this );
|
2619 |
|
2620 |
$valid_modes = [
|
2621 |
self::PRODUCT_DESCRIPTION_MODE_STANDARD,
|
2636 |
* Returns null if no offset is configured.
|
2637 |
*
|
2638 |
* @since 1.10.0
|
2639 |
+
* @deprecated 2.0.0
|
2640 |
*
|
2641 |
* @return int|null
|
2642 |
*/
|
2643 |
public function get_scheduled_resync_offset() {
|
2644 |
|
2645 |
+
wc_deprecated_function( __METHOD__, '2.0.0' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2646 |
}
|
2647 |
|
2648 |
|
2663 |
* @param string $locale the configured Facebook messenger locale
|
2664 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
2665 |
*/
|
2666 |
+
return (string) apply_filters( 'wc_facebook_messenger_locale', get_option( self::SETTING_MESSENGER_LOCALE, 'en_US' ), $this );
|
2667 |
}
|
2668 |
|
2669 |
|
2684 |
* @param string $greeting the configured Facebook messenger greeting
|
2685 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
2686 |
*/
|
2687 |
+
$greeting = (string) apply_filters( 'wc_facebook_messenger_greeting', get_option( self::SETTING_MESSENGER_GREETING, __( "Hi! We're here to answer any questions you may have.", 'facebook-for-woocommerce' ) ), $this );
|
2688 |
|
2689 |
+
return Framework\SV_WC_Helper::str_truncate( $greeting, $this->get_messenger_greeting_max_characters(), '' );
|
|
|
2690 |
}
|
2691 |
|
2692 |
|
2734 |
* @param string $hex the configured Facebook messenger color hex
|
2735 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
2736 |
*/
|
2737 |
+
return (string) apply_filters( 'wc_facebook_messenger_color_hex', get_option( self::SETTING_MESSENGER_COLOR_HEX, '#0084ff' ), $this );
|
2738 |
}
|
2739 |
|
2740 |
|
2862 |
}
|
2863 |
|
2864 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2865 |
/** Conditional methods *******************************************************************************************/
|
2866 |
|
2867 |
|
2874 |
*/
|
2875 |
public function is_configured() {
|
2876 |
|
2877 |
+
return $this->get_facebook_page_id() && facebook_for_woocommerce()->get_connection_handler()->is_connected();
|
2878 |
}
|
2879 |
|
2880 |
|
2895 |
* @param bool $is_enabled whether advanced matching is enabled
|
2896 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
2897 |
*/
|
2898 |
+
return (bool) apply_filters( 'wc_facebook_is_advanced_matching_enabled', true, $this );
|
2899 |
}
|
2900 |
|
2901 |
|
2916 |
* @param bool $is_enabled whether product sync is enabled
|
2917 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
2918 |
*/
|
2919 |
+
return (bool) apply_filters( 'wc_facebook_is_product_sync_enabled', 'yes' === get_option( self::SETTING_ENABLE_PRODUCT_SYNC, 'yes' ), $this );
|
2920 |
}
|
2921 |
|
2922 |
|
2924 |
* Determines whether the scheduled re-sync is enabled.
|
2925 |
*
|
2926 |
* @since 1.10.0
|
2927 |
+
* @deprecated 2.0.0
|
2928 |
*
|
2929 |
* @return bool
|
2930 |
*/
|
2931 |
public function is_scheduled_resync_enabled() {
|
2932 |
|
2933 |
+
wc_deprecated_function( __METHOD__, '2.0.0' );
|
2934 |
+
|
2935 |
+
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
2936 |
}
|
2937 |
|
2938 |
|
2953 |
* @param bool $is_enabled whether the Facebook messenger is enabled
|
2954 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
2955 |
*/
|
2956 |
+
return (bool) apply_filters( 'wc_facebook_is_messenger_enabled', 'yes' === get_option( self::SETTING_ENABLE_MESSENGER ), $this );
|
2957 |
}
|
2958 |
|
2959 |
|
2974 |
* @param bool $is_enabled whether debug mode is enabled
|
2975 |
* @param \WC_Facebookcommerce_Integration $integration the integration instance
|
2976 |
*/
|
2977 |
+
return (bool) apply_filters( 'wc_facebook_is_debug_mode_enabled', 'yes' === get_option( self::SETTING_ENABLE_DEBUG_MODE ), $this );
|
2978 |
}
|
2979 |
|
2980 |
|
3084 |
}
|
3085 |
|
3086 |
|
3087 |
+
/**
|
3088 |
+
* Gets the array that holds the name and url of the configured Facebook page.
|
3089 |
+
*
|
3090 |
+
* @since 2.0.0
|
3091 |
+
*
|
3092 |
+
* @return array
|
3093 |
+
*/
|
3094 |
+
private function get_page() {
|
3095 |
+
|
3096 |
+
if ( ! is_array( $this->page ) && $this->is_configured() ) {
|
3097 |
+
|
3098 |
+
try {
|
3099 |
+
|
3100 |
+
$response = facebook_for_woocommerce()->get_api()->get_page( $this->get_facebook_page_id() );
|
3101 |
+
|
3102 |
+
$this->page = [
|
3103 |
+
'name' => $response->get_name(),
|
3104 |
+
'url' => $response->get_url(),
|
3105 |
+
];
|
3106 |
+
|
3107 |
+
} catch ( Framework\SV_WC_API_Exception $e ) {
|
3108 |
+
|
3109 |
+
// we intentionally set $this->page to an empty array if an error occurs to avoid additional API requests
|
3110 |
+
// it's unlikely that we will get a different result if the exception was caused by an expired token, incorrect page ID, or rate limiting error
|
3111 |
+
$this->page = [];
|
3112 |
+
|
3113 |
+
$message = sprintf( __( 'There was an error trying to retrieve information about the Facebook page: %s' ), $e->getMessage() );
|
3114 |
+
|
3115 |
+
facebook_for_woocommerce()->log( $message );
|
3116 |
+
}
|
3117 |
+
}
|
3118 |
+
|
3119 |
+
return is_array( $this->page ) ? $this->page : [];
|
3120 |
+
}
|
3121 |
+
|
3122 |
+
|
3123 |
/**
|
3124 |
* Gets the name of the configured Facebook page.
|
3125 |
*
|
3127 |
*/
|
3128 |
public function get_page_name() {
|
3129 |
|
3130 |
+
$page = $this->get_page();
|
|
|
|
|
|
|
|
|
|
|
3131 |
|
3132 |
+
return isset( $page['name'] ) ? $page['name'] : '';
|
3133 |
}
|
3134 |
|
3135 |
|
3142 |
*/
|
3143 |
public function get_page_url() {
|
3144 |
|
3145 |
+
$page = $this->get_page();
|
|
|
|
|
|
|
|
|
3146 |
|
3147 |
+
return isset( $page['url'] ) ? $page['url'] : '';
|
3148 |
}
|
3149 |
|
3150 |
|
3201 |
*/
|
3202 |
function admin_options() {
|
3203 |
|
3204 |
+
facebook_for_woocommerce()->get_message_handler()->show_messages();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3205 |
|
3206 |
?>
|
3207 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3208 |
<div id="integration-settings" <?php echo ! $this->is_configured() ? 'style="display: none"' : ''; ?>>
|
3209 |
<table class="form-table"><?php $this->generate_settings_html( $this->get_form_fields() ); ?></table>
|
3210 |
</div>
|
3225 |
}
|
3226 |
}
|
3227 |
|
3228 |
+
|
3229 |
+
/**
|
3230 |
+
* Uses the Graph API to delete the Product Group associated with the given product.
|
3231 |
+
*
|
3232 |
+
* @since 2.0.0
|
3233 |
+
*
|
3234 |
+
* @param int $product_id product ID
|
3235 |
+
*/
|
3236 |
+
private function delete_product_group( $product_id ) {
|
3237 |
+
|
3238 |
+
$product_group_id = $this->get_product_fbid( self::FB_PRODUCT_GROUP_ID, $product_id );
|
3239 |
+
|
3240 |
+
if ( $product_group_id ) {
|
3241 |
+
|
3242 |
+
// TODO: replace with a call to API::delete_product_group() {WV 2020-05-26}
|
3243 |
+
$pg_result = $this->fbgraph->delete_product_group( $product_group_id );
|
3244 |
+
|
3245 |
+
\WC_Facebookcommerce_Utils::log( $pg_result );
|
3246 |
+
}
|
3247 |
+
}
|
3248 |
+
|
3249 |
+
|
3250 |
function fb_duplicate_product_reset_meta( $to_delete ) {
|
3251 |
array_push( $to_delete, self::FB_PRODUCT_ITEM_ID );
|
3252 |
array_push( $to_delete, self::FB_PRODUCT_GROUP_ID );
|
3253 |
return $to_delete;
|
3254 |
}
|
3255 |
|
3256 |
+
|
3257 |
/**
|
3258 |
* Helper function to update FB visibility.
|
3259 |
+
*
|
3260 |
+
* @param int|\WC_Product $product_id product ID or product object
|
3261 |
+
* @param string $visibility visibility
|
3262 |
*/
|
3263 |
+
function update_fb_visibility( $product_id, $visibility ) {
|
3264 |
|
3265 |
+
// bail if the plugin is not configured properly
|
3266 |
+
if ( ! $this->is_configured() || ! $this->get_product_catalog_id() ) {
|
3267 |
return;
|
3268 |
}
|
3269 |
|
3270 |
+
$product = $product_id instanceof \WC_Product ? $product_id : wc_get_product( $product_id );
|
3271 |
|
3272 |
+
// bail if product isn't found
|
3273 |
+
if ( ! $product instanceof \WC_Product ) {
|
3274 |
return;
|
3275 |
}
|
3276 |
|
3277 |
+
$should_set_visible = $visibility === self::FB_SHOP_PRODUCT_VISIBLE;
|
3278 |
+
|
3279 |
+
if ( $product->is_type( 'variation' ) ) {
|
3280 |
+
|
3281 |
+
Products::set_product_visibility( $product, $should_set_visible );
|
3282 |
+
|
3283 |
+
facebook_for_woocommerce()->get_products_sync_handler()->create_or_update_products( [ $product->get_id() ] );
|
3284 |
+
|
3285 |
+
} elseif ( $product->is_type( 'variable' ) ) {
|
3286 |
+
|
3287 |
+
// parent product
|
3288 |
+
Products::set_product_visibility( $product, $should_set_visible );
|
3289 |
+
|
3290 |
+
// we should not add the parent product ID to the array of product IDs to be
|
3291 |
+
// updated because product groups, which are used to represent the parent product
|
3292 |
+
// for variable products, don't have the visibility property on Facebook
|
3293 |
+
$product_ids = [];
|
3294 |
+
|
3295 |
+
// set visibility for all children
|
3296 |
+
foreach ( $product->get_children() as $index => $id ) {
|
3297 |
+
|
3298 |
+
$product = wc_get_product( $id );
|
3299 |
+
|
3300 |
+
if ( ! $product instanceof \WC_Product ) {
|
3301 |
+
continue;
|
3302 |
+
}
|
3303 |
+
|
3304 |
+
Products::set_product_visibility( $product, $should_set_visible );
|
3305 |
+
|
3306 |
+
$product_ids[] = $product->get_id();
|
3307 |
+
}
|
3308 |
+
|
3309 |
+
// sync product with all variations
|
3310 |
+
facebook_for_woocommerce()->get_products_sync_handler()->create_or_update_products( $product_ids );
|
3311 |
+
|
3312 |
+
} else {
|
3313 |
+
|
3314 |
+
$fb_product_item_id = $this->get_product_fbid( self::FB_PRODUCT_ITEM_ID, $product_id );
|
3315 |
|
3316 |
if ( ! $fb_product_item_id ) {
|
3317 |
+
\WC_Facebookcommerce_Utils::fblog( $fb_product_item_id . " doesn't exist but underwent a visibility transform.", [], true );
|
3318 |
+
return;
|
|
|
|
|
|
|
|
|
3319 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3320 |
|
3321 |
+
$set_visibility = $this->fbgraph->update_product_item( $fb_product_item_id, [ 'visibility' => $visibility ] );
|
3322 |
|
3323 |
+
if ( $this->check_api_result( $set_visibility ) ) {
|
3324 |
+
Products::set_product_visibility( $product, $should_set_visible );
|
3325 |
}
|
3326 |
}
|
3327 |
}
|
3350 |
} else {
|
3351 |
// - product never published to Facebook, new status is not publish
|
3352 |
// - product new status is not publish but may have been published before
|
3353 |
+
$this->update_fb_visibility( $product, $visibility );
|
3354 |
}
|
3355 |
}
|
3356 |
|
3374 |
return $fb_id;
|
3375 |
}
|
3376 |
|
|
|
|
|
|
|
|
|
3377 |
if ( ! $woo_product ) {
|
3378 |
$woo_product = new WC_Facebook_Product( $wp_id );
|
3379 |
}
|
3380 |
|
3381 |
+
$products = WC_Facebookcommerce_Utils::get_product_array( $woo_product );
|
3382 |
+
|
3383 |
+
// if the product with ID equal to $wp_id is variable, $woo_product will be the first child
|
3384 |
$woo_product = new WC_Facebook_Product( current( $products ) );
|
3385 |
|
3386 |
// This is a generalized function used elsewhere
|
3429 |
$fb_id
|
3430 |
);
|
3431 |
|
|
|
|
|
3432 |
return $fb_id;
|
3433 |
}
|
3434 |
}
|
3499 |
}
|
3500 |
|
3501 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3502 |
/**
|
3503 |
* Adds an recurring action to sync products.
|
3504 |
*
|
3605 |
}
|
3606 |
}
|
3607 |
|
3608 |
+
|
3609 |
+
/** Deprecated methods ********************************************************************************************/
|
3610 |
+
|
3611 |
+
|
3612 |
/**
|
3613 |
+
* Enables product sync delay notice when a post is moved to the trash.
|
3614 |
+
*
|
3615 |
+
* @internal
|
3616 |
*
|
3617 |
* @since 1.11.0
|
3618 |
+
* @deprecated 2.0.0
|
3619 |
+
*
|
3620 |
+
* @param int $post_id the post ID
|
3621 |
*/
|
3622 |
+
public function on_product_trash( $post_id ) {
|
3623 |
|
3624 |
+
wc_deprecated_function( __METHOD__, '2.0.0' );
|
3625 |
}
|
3626 |
|
3627 |
|
facebook-config-warmer.php
CHANGED
@@ -18,6 +18,8 @@ if ( ! class_exists( 'WC_Facebookcommerce_WarmConfig' ) ) :
|
|
18 |
class WC_Facebookcommerce_WarmConfig {
|
19 |
static $fb_warm_pixel_id = null;
|
20 |
static $fb_warm_is_advanced_matching_enabled = null;
|
|
|
|
|
21 |
}
|
22 |
|
23 |
endif;
|
18 |
class WC_Facebookcommerce_WarmConfig {
|
19 |
static $fb_warm_pixel_id = null;
|
20 |
static $fb_warm_is_advanced_matching_enabled = null;
|
21 |
+
static $fb_warm_use_s2s = null;
|
22 |
+
static $fb_warm_access_token = null;
|
23 |
}
|
24 |
|
25 |
endif;
|
facebook-for-woocommerce.php
CHANGED
@@ -10,10 +10,10 @@
|
|
10 |
* Description: Grow your business on Facebook! Use this official plugin to help sell more of your products using Facebook. After completing the setup, you'll be ready to create ads that promote your products and you can also create a shop section on your Page where customers can browse your products on Facebook.
|
11 |
* Author: Facebook
|
12 |
* Author URI: https://www.facebook.com/
|
13 |
-
* Version:
|
14 |
* Text Domain: facebook-for-woocommerce
|
15 |
* WC requires at least: 3.5.0
|
16 |
-
* WC tested up to: 4.
|
17 |
*
|
18 |
* @package FacebookCommerce
|
19 |
*/
|
10 |
* Description: Grow your business on Facebook! Use this official plugin to help sell more of your products using Facebook. After completing the setup, you'll be ready to create ads that promote your products and you can also create a shop section on your Page where customers can browse your products on Facebook.
|
11 |
* Author: Facebook
|
12 |
* Author URI: https://www.facebook.com/
|
13 |
+
* Version: 2.0.0
|
14 |
* Text Domain: facebook-for-woocommerce
|
15 |
* WC requires at least: 3.5.0
|
16 |
+
* WC tested up to: 4.3.1
|
17 |
*
|
18 |
* @package FacebookCommerce
|
19 |
*/
|
i18n/languages/facebook-for-woocommerce.pot
CHANGED
@@ -2,10 +2,10 @@
|
|
2 |
# This file is distributed under the same license as the Facebook for WooCommerce package.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
-
"Project-Id-Version: Facebook for WooCommerce
|
6 |
"Report-Msgid-Bugs-To: "
|
7 |
"https://woocommerce.com/my-account/marketplace-ticket-form/\n"
|
8 |
-
"POT-Creation-Date: 2020-
|
9 |
"MIME-Version: 1.0\n"
|
10 |
"Content-Type: text/plain; charset=utf-8\n"
|
11 |
"Content-Transfer-Encoding: 8bit\n"
|
@@ -13,108 +13,119 @@ msgstr ""
|
|
13 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
14 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
15 |
|
16 |
-
#: class-wc-facebookcommerce.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
#. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
|
18 |
-
#. <a> tag, %4$s - </a> tag
|
19 |
msgid ""
|
20 |
-
"%1$sHeads up!%2$s
|
21 |
-
"
|
22 |
-
"
|
23 |
-
"more%6$s."
|
24 |
msgstr ""
|
25 |
|
26 |
-
#: class-wc-facebookcommerce.php:
|
27 |
#. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
|
28 |
-
#. <a> tag, %4$s - </a> tag
|
29 |
msgid ""
|
30 |
-
"%1$sHeads up!%2$s
|
31 |
-
"
|
32 |
-
"
|
33 |
-
|
|
|
|
|
|
|
34 |
msgstr ""
|
35 |
|
36 |
#. Plugin Name of the plugin/theme
|
37 |
msgid "Facebook for WooCommerce"
|
38 |
msgstr ""
|
39 |
|
40 |
-
#: facebook-commerce.php:
|
41 |
msgid "Facebook Commerce and Dynamic Ads (Pixel) Extension"
|
42 |
msgstr ""
|
43 |
|
44 |
-
#: facebook-commerce.php:
|
45 |
msgid "Facebook ID:"
|
46 |
msgstr ""
|
47 |
|
48 |
-
#: facebook-commerce.php:
|
49 |
msgid "Variant IDs:"
|
50 |
msgstr ""
|
51 |
|
52 |
-
#: facebook-commerce.php:
|
53 |
msgid "Reset Facebook metadata"
|
54 |
msgstr ""
|
55 |
|
56 |
-
#: facebook-commerce.php:
|
57 |
msgid "Delete product(s) on Facebook"
|
58 |
msgstr ""
|
59 |
|
60 |
-
#: facebook-commerce.php:
|
61 |
msgid "This product is not yet synced to Facebook."
|
62 |
msgstr ""
|
63 |
|
64 |
-
#: facebook-commerce.php:
|
65 |
msgid "Nothing to update for product group for %1$s"
|
66 |
msgstr ""
|
67 |
|
68 |
-
#: facebook-commerce.php:
|
69 |
#. translators: Placeholders %1$s - original error message from Facebook API
|
70 |
msgid "There was an issue connecting to the Facebook API: %1$s"
|
71 |
msgstr ""
|
72 |
|
73 |
-
#: facebook-commerce.php:
|
74 |
-
#. translators: Placeholders %1$s - opening strong HTML tag, %2$s - closing
|
75 |
-
#. strong HTML tag, %3$s - opening link HTML tag, %4$s - closing link HTML tag
|
76 |
-
msgid ""
|
77 |
-
"%1$sFacebook for WooCommerce is almost ready.%2$s To complete your "
|
78 |
-
"configuration, %3$scomplete the setup steps%4$s."
|
79 |
-
msgstr ""
|
80 |
-
|
81 |
-
#: facebook-commerce.php:1938
|
82 |
-
#. translators: Placeholders %1$s - WooCommerce version
|
83 |
-
msgid ""
|
84 |
-
"Facebook product sync may not work correctly in WooCommerce version %1$s. "
|
85 |
-
"Please upgrade to WooCommerce 3."
|
86 |
-
msgstr ""
|
87 |
-
|
88 |
-
#: facebook-commerce.php:2157
|
89 |
msgid "Your connection has expired."
|
90 |
msgstr ""
|
91 |
|
92 |
-
#: facebook-commerce.php:
|
93 |
msgid ""
|
94 |
"Please click Manage connection > Advanced Options > Update Token to refresh "
|
95 |
"your connection to Facebook."
|
96 |
msgstr ""
|
97 |
|
98 |
-
#: facebook-commerce.php:
|
99 |
#. translators: Placeholders %s - error message
|
100 |
msgid "There was an error trying to sync the products to Facebook. %s"
|
101 |
msgstr ""
|
102 |
|
103 |
-
#: facebook-commerce.php:
|
104 |
msgid "Product sync is disabled."
|
105 |
msgstr ""
|
106 |
|
107 |
-
#: facebook-commerce.php:
|
108 |
-
msgid "The
|
109 |
msgstr ""
|
110 |
|
111 |
-
#: facebook-commerce.php:
|
112 |
msgid ""
|
113 |
"A product sync is in progress. Please wait until the sync finishes before "
|
114 |
"starting a new one."
|
115 |
msgstr ""
|
116 |
|
117 |
-
#: facebook-commerce.php:
|
118 |
msgid ""
|
119 |
"We've detected that your Facebook Product Catalog is no longer valid. This "
|
120 |
"may happen if it was deleted, but could also be a temporary error. If the "
|
@@ -122,296 +133,249 @@ msgid ""
|
|
122 |
"and setup the plugin again."
|
123 |
msgstr ""
|
124 |
|
125 |
-
#: facebook-commerce.php:
|
126 |
msgid "We couldn't create the feed or upload the product information."
|
127 |
msgstr ""
|
128 |
|
129 |
-
#: facebook-commerce.php:
|
130 |
msgid "Hi! We're here to answer any questions you may have."
|
131 |
msgstr ""
|
132 |
|
133 |
-
#: facebook-commerce.php:
|
134 |
-
msgid "
|
135 |
msgstr ""
|
136 |
|
137 |
-
#: facebook-commerce.php:
|
138 |
-
#. translators: Placeholders: %1$s - opening <a> HTML link tag, %2$s - closing
|
139 |
-
#. </a> HTML link tag
|
140 |
msgid ""
|
141 |
-
"
|
142 |
-
"
|
143 |
-
"number). %1$sLearn more%2$s."
|
144 |
-
msgstr ""
|
145 |
-
|
146 |
-
#: facebook-commerce.php:2551 facebook-commerce.php:2898
|
147 |
-
msgid "Product sync"
|
148 |
-
msgstr ""
|
149 |
-
|
150 |
-
#: facebook-commerce.php:2555
|
151 |
-
msgid "Enable product sync"
|
152 |
-
msgstr ""
|
153 |
-
|
154 |
-
#: facebook-commerce.php:2563
|
155 |
-
msgid "Exclude categories from sync"
|
156 |
-
msgstr ""
|
157 |
-
|
158 |
-
#: facebook-commerce.php:2567
|
159 |
-
msgid "Products in one or more of these categories will not sync to Facebook."
|
160 |
-
msgstr ""
|
161 |
-
|
162 |
-
#: facebook-commerce.php:2571
|
163 |
-
msgid "Search for a product category…"
|
164 |
-
msgstr ""
|
165 |
-
|
166 |
-
#: facebook-commerce.php:2576
|
167 |
-
msgid "Exclude tags from sync"
|
168 |
-
msgstr ""
|
169 |
-
|
170 |
-
#: facebook-commerce.php:2580
|
171 |
-
msgid "Products with one or more of these tags will not sync to Facebook."
|
172 |
-
msgstr ""
|
173 |
-
|
174 |
-
#: facebook-commerce.php:2584
|
175 |
-
msgid "Search for a product tag…"
|
176 |
msgstr ""
|
177 |
|
178 |
-
#: facebook-commerce.php:
|
179 |
-
msgid "
|
180 |
msgstr ""
|
181 |
|
182 |
-
#: facebook-commerce.php:
|
183 |
-
msgid "
|
184 |
msgstr ""
|
185 |
|
186 |
-
#: facebook-commerce.php:
|
187 |
-
|
|
|
188 |
msgstr ""
|
189 |
|
190 |
-
#:
|
191 |
-
msgid "
|
192 |
msgstr ""
|
193 |
|
194 |
-
#:
|
195 |
-
msgid "
|
196 |
msgstr ""
|
197 |
|
198 |
-
#:
|
199 |
-
|
|
|
|
|
|
|
|
|
|
|
200 |
msgstr ""
|
201 |
|
202 |
-
#:
|
203 |
-
msgid "
|
|
|
|
|
|
|
|
|
204 |
msgstr ""
|
205 |
|
206 |
-
#:
|
207 |
-
msgid "
|
208 |
msgstr ""
|
209 |
|
210 |
-
#:
|
211 |
-
|
|
|
|
|
|
|
|
|
|
|
212 |
msgstr ""
|
213 |
|
214 |
-
#:
|
215 |
-
msgid "
|
216 |
msgstr ""
|
217 |
|
218 |
-
|
219 |
-
msgid "
|
220 |
msgstr ""
|
221 |
|
222 |
-
#:
|
223 |
-
msgid "
|
224 |
msgstr ""
|
225 |
|
226 |
-
#:
|
227 |
-
msgid "
|
228 |
msgstr ""
|
229 |
|
230 |
-
#:
|
231 |
-
|
|
|
232 |
msgstr ""
|
233 |
|
234 |
-
#:
|
|
|
235 |
msgid "Connection"
|
236 |
msgstr ""
|
237 |
|
238 |
-
#:
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
#: facebook-commerce.php:2868
|
247 |
-
msgid "Create ad"
|
248 |
-
msgstr ""
|
249 |
-
|
250 |
-
#: facebook-commerce.php:2906
|
251 |
-
msgid "Sync products"
|
252 |
msgstr ""
|
253 |
|
254 |
-
#:
|
255 |
-
msgid "
|
256 |
msgstr ""
|
257 |
|
258 |
-
#:
|
259 |
-
msgid "
|
260 |
msgstr ""
|
261 |
|
262 |
-
#:
|
263 |
-
msgid "
|
264 |
msgstr ""
|
265 |
|
266 |
-
#:
|
267 |
-
|
268 |
-
msgid "The Messenger greeting must be %d characters or less."
|
269 |
msgstr ""
|
270 |
|
271 |
-
#:
|
272 |
-
msgid "
|
273 |
msgstr ""
|
274 |
|
275 |
-
#:
|
276 |
-
msgid "
|
277 |
msgstr ""
|
278 |
|
279 |
-
#:
|
280 |
-
msgid "
|
281 |
msgstr ""
|
282 |
|
283 |
-
#:
|
284 |
-
msgid ""
|
285 |
-
"You're using Remove HTTP which has incompatibilities with our extension. "
|
286 |
-
"Please disable it, or select the \"Ignore external links\" option on the "
|
287 |
-
"Remove HTTP settings page."
|
288 |
msgstr ""
|
289 |
|
290 |
-
|
291 |
-
msgid "
|
292 |
msgstr ""
|
293 |
|
294 |
-
#:
|
295 |
-
msgid "
|
296 |
msgstr ""
|
297 |
|
298 |
-
#:
|
299 |
-
msgid "
|
300 |
msgstr ""
|
301 |
|
302 |
-
#:
|
303 |
-
msgid "
|
304 |
msgstr ""
|
305 |
|
306 |
-
#:
|
307 |
-
msgid "
|
308 |
msgstr ""
|
309 |
|
310 |
-
#:
|
311 |
-
msgid "
|
312 |
msgstr ""
|
313 |
|
314 |
-
#:
|
315 |
-
msgid "
|
316 |
msgstr ""
|
317 |
|
318 |
-
#:
|
319 |
-
msgid "
|
320 |
msgstr ""
|
321 |
|
322 |
-
#:
|
323 |
-
|
324 |
-
msgid "There was an issue connecting to the Facebook API: %s"
|
325 |
msgstr ""
|
326 |
|
327 |
-
#: includes/
|
328 |
-
msgid "
|
329 |
msgstr ""
|
330 |
|
331 |
-
#: includes/
|
332 |
-
msgid "
|
333 |
msgstr ""
|
334 |
|
335 |
-
#: includes/
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
msgstr ""
|
340 |
|
341 |
-
#: includes/
|
342 |
-
|
|
|
343 |
msgstr ""
|
344 |
|
345 |
-
#: includes/
|
346 |
-
msgid "
|
347 |
msgstr ""
|
348 |
|
349 |
-
#: includes/
|
350 |
-
|
351 |
-
msgid ""
|
352 |
-
"This product belongs to a category or tag that is excluded from the "
|
353 |
-
"Facebook catalog sync. It will not sync to Facebook. %sTo sync this product "
|
354 |
-
"to Facebook, click Go to Settings and remove the category or tag exclusion "
|
355 |
-
"or click Cancel and update the product's category / tag assignments."
|
356 |
msgstr ""
|
357 |
|
358 |
-
#: includes/
|
359 |
-
msgid "
|
360 |
msgstr ""
|
361 |
|
362 |
-
#: includes/
|
363 |
-
msgid "
|
364 |
msgstr ""
|
365 |
|
366 |
-
#: includes/
|
367 |
-
|
368 |
-
"
|
369 |
-
"Would you like to hide these products from your Facebook shop?"
|
370 |
msgstr ""
|
371 |
|
372 |
-
#: includes/
|
|
|
373 |
msgid ""
|
374 |
-
"
|
375 |
-
"
|
376 |
-
"Facebook, please remove the category or tag exclusion from the plugin "
|
377 |
-
"settings."
|
378 |
-
msgstr ""
|
379 |
-
|
380 |
-
#: includes/AJAX.php:290
|
381 |
-
msgid "Exclude Products"
|
382 |
msgstr ""
|
383 |
|
384 |
-
#: includes/
|
385 |
-
msgid "
|
386 |
msgstr ""
|
387 |
|
388 |
-
#: includes/
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
"
|
393 |
-
"products from the Facebook sync, click Exclude Products. To review the "
|
394 |
-
"category / tag exclusion settings, click Cancel."
|
395 |
msgstr ""
|
396 |
|
397 |
-
#: includes/Admin.php:
|
398 |
-
#. translators: Placeholders
|
399 |
-
|
400 |
-
|
401 |
-
msgid_plural "%1$sProgress:%2$s {count} items remaining."
|
402 |
msgstr[0] ""
|
403 |
msgstr[1] ""
|
404 |
|
405 |
-
#: includes/Admin.php:
|
406 |
#. translators: Placeholders %s - html code for a spinner icon
|
407 |
msgid "Your products will now be resynced to Facebook, this may take some time."
|
408 |
msgstr ""
|
409 |
|
410 |
-
#: includes/Admin.php:
|
411 |
-
msgid "Launch Test?"
|
412 |
-
msgstr ""
|
413 |
-
|
414 |
-
#: includes/Admin.php:136
|
415 |
msgid ""
|
416 |
"Facebook for WooCommerce automatically syncs your products on "
|
417 |
"create/update. Are you sure you want to force product resync?\n"
|
@@ -421,219 +385,243 @@ msgid ""
|
|
421 |
"did not sync."
|
422 |
msgstr ""
|
423 |
|
424 |
-
#: includes/Admin.php:
|
425 |
-
msgid "
|
426 |
msgstr ""
|
427 |
|
428 |
-
#: includes/Admin.php:
|
429 |
-
|
430 |
-
#. </strong> html tag
|
431 |
-
msgid "%1$sStatus:%2$s Test Pass."
|
432 |
msgstr ""
|
433 |
|
434 |
-
#: includes/Admin.php:
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
msgstr ""
|
439 |
|
440 |
-
#: includes/Admin.php:
|
441 |
-
|
442 |
-
#. </strong> html tag
|
443 |
-
msgid "%1$sStatus:%2$s Test Fail."
|
444 |
msgstr ""
|
445 |
|
446 |
-
#: includes/Admin.php:
|
447 |
-
msgid "
|
448 |
msgstr ""
|
449 |
|
450 |
-
#: includes/Admin.php:
|
451 |
-
msgid ""
|
452 |
-
"Something went wrong while uploading the product information, please try "
|
453 |
-
"again."
|
454 |
msgstr ""
|
455 |
|
456 |
-
#: includes/Admin.php:
|
457 |
-
msgid "
|
458 |
msgstr ""
|
459 |
|
460 |
-
#: includes/Admin.php:
|
461 |
-
msgid "
|
462 |
msgstr ""
|
463 |
|
464 |
-
#: includes/Admin.php:
|
465 |
-
msgid "
|
466 |
msgstr ""
|
467 |
|
468 |
-
#: includes/Admin.php:
|
469 |
-
|
470 |
-
msgid "Never synced with Facebook."
|
471 |
msgstr ""
|
472 |
|
473 |
-
#: includes/Admin.php:
|
474 |
-
|
475 |
-
#. the Facebook catalog
|
476 |
-
msgid "Hide from Facebook catalog. Currently synced with Facebook."
|
477 |
msgstr ""
|
478 |
|
479 |
-
#: includes/Admin.php:
|
480 |
-
|
481 |
-
#. the Facebook catalog
|
482 |
-
msgid "Publish in Facebook catalog. Currently synced with Facebook."
|
483 |
msgstr ""
|
484 |
|
485 |
-
#: includes/Admin.php:
|
486 |
-
|
487 |
-
#. from the Facebook catalog
|
488 |
-
msgid "Hide from Facebook catalog. Not synced with Facebook."
|
489 |
msgstr ""
|
490 |
|
491 |
-
#: includes/Admin.php:
|
492 |
-
|
493 |
-
#. Facebook) in the Facebook catalog
|
494 |
-
msgid "Publish in Facebook catalog. Not synced with Facebook."
|
495 |
msgstr ""
|
496 |
|
497 |
-
#: includes/Admin.php:
|
498 |
-
msgid "
|
499 |
msgstr ""
|
500 |
|
501 |
-
#: includes/Admin.php:
|
502 |
-
|
|
|
503 |
msgstr ""
|
504 |
|
505 |
-
#: includes/Admin.php:
|
506 |
-
msgid "
|
507 |
msgstr ""
|
508 |
|
509 |
-
#: includes/Admin.php:
|
510 |
-
msgid "
|
511 |
msgstr ""
|
512 |
|
513 |
-
#: includes/Admin.php:
|
514 |
-
msgid "
|
515 |
msgstr ""
|
516 |
|
517 |
-
#: includes/Admin.php:
|
518 |
-
|
|
|
519 |
msgstr ""
|
520 |
|
521 |
-
#: includes/Admin.php:
|
522 |
-
msgid "
|
523 |
msgstr ""
|
524 |
|
525 |
-
#: includes/Admin.php:
|
526 |
-
|
527 |
-
#. HTML <a> link tag, %3$s - closing HTML </a> link tag
|
528 |
-
msgid ""
|
529 |
-
"%1$s: One or more of your products is using a checkout URL that may be "
|
530 |
-
"different than your shop checkout URL. %2$sRe-sync your products to update "
|
531 |
-
"checkout URLs on Facebook%3$s."
|
532 |
msgstr ""
|
533 |
|
534 |
-
#: includes/Admin.php:
|
535 |
-
|
536 |
-
#. HTML </strong> tag, %3$s - opening HTML <a> tag, %4$s - closing HTML </a>
|
537 |
-
#. tag
|
538 |
-
msgid ""
|
539 |
-
"%1$sHeads up!%2$s Product sync is temporarily changed as we migrate to a "
|
540 |
-
"more secure experience. An automated sync from Facebook will run every hour "
|
541 |
-
"to update the catalog with any changes you've made. %3$sLearn more%4$s"
|
542 |
msgstr ""
|
543 |
|
544 |
-
#: includes/Admin.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
545 |
msgid "Don't show this notice again"
|
546 |
msgstr ""
|
547 |
|
548 |
-
#: includes/Admin.php:
|
549 |
-
#. translators: Placeholders: %1$s -
|
550 |
-
#. HTML
|
551 |
-
#. tag
|
552 |
msgid ""
|
553 |
-
"%1$
|
554 |
-
"
|
555 |
-
"
|
556 |
-
"
|
557 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
558 |
|
559 |
-
#: includes/Admin.php:
|
560 |
#. translators: Placeholders: %1$s - opening HTML <strong> tag, %2$s - closing
|
561 |
#. HTML </strong> tag, %3$s - opening HTML <a> tag, %4$s - closing HTML </a>
|
562 |
#. tag
|
563 |
msgid ""
|
564 |
-
"%1$sHeads up!%2$s Facebook
|
565 |
-
"
|
566 |
-
"
|
567 |
msgstr ""
|
568 |
|
569 |
-
#: includes/Admin.php:
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
"
|
575 |
-
"have removed any previously synced virtual products from the catalog sync "
|
576 |
-
"going forward. %3$sClick here to read more about Facebook's policy%4$s."
|
577 |
msgstr ""
|
578 |
|
579 |
-
#: includes/Admin.php:
|
580 |
msgid "Facebook Description"
|
581 |
msgstr ""
|
582 |
|
583 |
-
#: includes/Admin.php:
|
584 |
msgid ""
|
585 |
"Custom (plain-text only) description for product on Facebook. If blank, "
|
586 |
"product description will be used. If product description is blank, "
|
587 |
"shortname will be used."
|
588 |
msgstr ""
|
589 |
|
590 |
-
#: includes/Admin.php:
|
591 |
msgid "Facebook Product Image"
|
592 |
msgstr ""
|
593 |
|
594 |
-
#: includes/Admin.php:
|
595 |
msgid ""
|
596 |
"Choose the product image that should be synced to the Facebook catalog for "
|
597 |
"this product. If using a custom image, please enter an absolute URL (e.g. "
|
598 |
"https://domain.com/image.jpg)."
|
599 |
msgstr ""
|
600 |
|
601 |
-
#: includes/Admin.php:
|
602 |
msgid "Use WooCommerce image"
|
603 |
msgstr ""
|
604 |
|
605 |
-
#: includes/Admin.php:
|
606 |
msgid "Use custom image"
|
607 |
msgstr ""
|
608 |
|
609 |
-
#: includes/Admin.php:
|
610 |
msgid "Custom Image URL"
|
611 |
msgstr ""
|
612 |
|
613 |
-
#: includes/Admin.php:
|
614 |
#. translators: Placeholders %1$s - WC currency symbol
|
615 |
msgid "Facebook Price (%1$s)"
|
616 |
msgstr ""
|
617 |
|
618 |
-
#: includes/Admin.php:
|
619 |
msgid ""
|
620 |
"Custom price for product on Facebook. Please enter in monetary decimal (.) "
|
621 |
"format without thousand separators and currency symbols. If blank, product "
|
622 |
"price will be used."
|
623 |
msgstr ""
|
624 |
|
625 |
-
#: includes/Admin.php:
|
626 |
msgid "Use variation image"
|
627 |
msgstr ""
|
628 |
|
629 |
-
#: includes/Admin.php:
|
630 |
msgid "Use parent image"
|
631 |
msgstr ""
|
632 |
|
633 |
-
#: includes/Admin.php:
|
634 |
msgid "Close modal panel"
|
635 |
msgstr ""
|
636 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
637 |
#: includes/fbgraph.php:104
|
638 |
msgid "HTTP %s: %s"
|
639 |
msgstr ""
|
@@ -703,7 +691,7 @@ msgstr ""
|
|
703 |
msgid "https://www.facebook.com/"
|
704 |
msgstr ""
|
705 |
|
706 |
-
#: facebook-commerce-messenger-chat.php:
|
707 |
msgctxt "language"
|
708 |
msgid "English (United States)"
|
709 |
msgstr ""
|
2 |
# This file is distributed under the same license as the Facebook for WooCommerce package.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
+
"Project-Id-Version: Facebook for WooCommerce 2.0.0\n"
|
6 |
"Report-Msgid-Bugs-To: "
|
7 |
"https://woocommerce.com/my-account/marketplace-ticket-form/\n"
|
8 |
+
"POT-Creation-Date: 2020-07-30 19:04:18+00:00\n"
|
9 |
"MIME-Version: 1.0\n"
|
10 |
"Content-Type: text/plain; charset=utf-8\n"
|
11 |
"Content-Transfer-Encoding: 8bit\n"
|
13 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
14 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
15 |
|
16 |
+
#: class-wc-facebookcommerce.php:187
|
17 |
+
#. translators: Placeholders %1$s - opening strong HTML tag, %2$s - closing
|
18 |
+
#. strong HTML tag, %3$s - opening link HTML tag, %4$s - closing link HTML tag
|
19 |
+
msgid ""
|
20 |
+
"%1$sHeads up!%2$s You're ready to migrate to a more secure, reliable "
|
21 |
+
"Facebook for WooCommerce connection. Please %3$sclick here%4$s to reconnect!"
|
22 |
+
msgstr ""
|
23 |
+
|
24 |
+
#: class-wc-facebookcommerce.php:202
|
25 |
+
#. translators: Placeholders %1$s - opening link HTML tag, %2$s - closing link
|
26 |
+
#. HTML tag
|
27 |
+
msgid ""
|
28 |
+
"For your convenience, the Facebook for WooCommerce settings are now located "
|
29 |
+
"under %1$sWooCommerce > Facebook%2$s."
|
30 |
+
msgstr ""
|
31 |
+
|
32 |
+
#: class-wc-facebookcommerce.php:217
|
33 |
+
#. translators: Placeholders %1$s - opening strong HTML tag, %2$s - closing
|
34 |
+
#. strong HTML tag, %3$s - opening link HTML tag, %4$s - closing link HTML tag
|
35 |
+
msgid ""
|
36 |
+
"%1$sFacebook for WooCommerce is almost ready.%2$s To complete your "
|
37 |
+
"configuration, %3$scomplete the setup steps%4$s."
|
38 |
+
msgstr ""
|
39 |
+
|
40 |
+
#: class-wc-facebookcommerce.php:245
|
41 |
#. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
|
42 |
+
#. <a> tag, %4$s - </a> tag
|
43 |
msgid ""
|
44 |
+
"%1$sHeads up!%2$s If you've customized your Facebook Messenger color or "
|
45 |
+
"greeting settings, please update those settings again from the %3$sManage "
|
46 |
+
"Connection%4$s area."
|
|
|
47 |
msgstr ""
|
48 |
|
49 |
+
#: class-wc-facebookcommerce.php:262
|
50 |
#. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
|
51 |
+
#. <a> tag, %4$s - </a> tag
|
52 |
msgid ""
|
53 |
+
"%1$sHeads up!%2$s Your connection to Facebook is no longer valid. Please "
|
54 |
+
"%3$sclick here%4$s to securely reconnect your account and continue syncing "
|
55 |
+
"products."
|
56 |
+
msgstr ""
|
57 |
+
|
58 |
+
#: class-wc-facebookcommerce.php:315
|
59 |
+
msgid "Cannot create the API instance because the access token is missing."
|
60 |
msgstr ""
|
61 |
|
62 |
#. Plugin Name of the plugin/theme
|
63 |
msgid "Facebook for WooCommerce"
|
64 |
msgstr ""
|
65 |
|
66 |
+
#: facebook-commerce.php:215
|
67 |
msgid "Facebook Commerce and Dynamic Ads (Pixel) Extension"
|
68 |
msgstr ""
|
69 |
|
70 |
+
#: facebook-commerce.php:589
|
71 |
msgid "Facebook ID:"
|
72 |
msgstr ""
|
73 |
|
74 |
+
#: facebook-commerce.php:597
|
75 |
msgid "Variant IDs:"
|
76 |
msgstr ""
|
77 |
|
78 |
+
#: facebook-commerce.php:615
|
79 |
msgid "Reset Facebook metadata"
|
80 |
msgstr ""
|
81 |
|
82 |
+
#: facebook-commerce.php:620
|
83 |
msgid "Delete product(s) on Facebook"
|
84 |
msgstr ""
|
85 |
|
86 |
+
#: facebook-commerce.php:628
|
87 |
msgid "This product is not yet synced to Facebook."
|
88 |
msgstr ""
|
89 |
|
90 |
+
#: facebook-commerce.php:1369
|
91 |
msgid "Nothing to update for product group for %1$s"
|
92 |
msgstr ""
|
93 |
|
94 |
+
#: facebook-commerce.php:1635
|
95 |
#. translators: Placeholders %1$s - original error message from Facebook API
|
96 |
msgid "There was an issue connecting to the Facebook API: %1$s"
|
97 |
msgstr ""
|
98 |
|
99 |
+
#: facebook-commerce.php:1972
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
msgid "Your connection has expired."
|
101 |
msgstr ""
|
102 |
|
103 |
+
#: facebook-commerce.php:1972
|
104 |
msgid ""
|
105 |
"Please click Manage connection > Advanced Options > Update Token to refresh "
|
106 |
"your connection to Facebook."
|
107 |
msgstr ""
|
108 |
|
109 |
+
#: facebook-commerce.php:1979
|
110 |
#. translators: Placeholders %s - error message
|
111 |
msgid "There was an error trying to sync the products to Facebook. %s"
|
112 |
msgstr ""
|
113 |
|
114 |
+
#: facebook-commerce.php:2002 facebook-commerce.php:2175
|
115 |
msgid "Product sync is disabled."
|
116 |
msgstr ""
|
117 |
|
118 |
+
#: facebook-commerce.php:2009 facebook-commerce.php:2182
|
119 |
+
msgid "The plugin is not configured or the Catalog ID is missing."
|
120 |
msgstr ""
|
121 |
|
122 |
+
#: facebook-commerce.php:2032
|
123 |
msgid ""
|
124 |
"A product sync is in progress. Please wait until the sync finishes before "
|
125 |
"starting a new one."
|
126 |
msgstr ""
|
127 |
|
128 |
+
#: facebook-commerce.php:2044 facebook-commerce.php:2196
|
129 |
msgid ""
|
130 |
"We've detected that your Facebook Product Catalog is no longer valid. This "
|
131 |
"may happen if it was deleted, but could also be a temporary error. If the "
|
133 |
"and setup the plugin again."
|
134 |
msgstr ""
|
135 |
|
136 |
+
#: facebook-commerce.php:2220
|
137 |
msgid "We couldn't create the feed or upload the product information."
|
138 |
msgstr ""
|
139 |
|
140 |
+
#: facebook-commerce.php:2687
|
141 |
msgid "Hi! We're here to answer any questions you may have."
|
142 |
msgstr ""
|
143 |
|
144 |
+
#: facebook-commerce.php:3031
|
145 |
+
msgid "Facebook for WooCommerce error:"
|
146 |
msgstr ""
|
147 |
|
148 |
+
#: facebook-commerce.php:3113
|
|
|
|
|
149 |
msgid ""
|
150 |
+
"There was an error trying to retrieve information about the Facebook page: "
|
151 |
+
"%s"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
msgstr ""
|
153 |
|
154 |
+
#: facebook-commerce.php:3164
|
155 |
+
msgid "Get started with Messenger Customer Chat"
|
156 |
msgstr ""
|
157 |
|
158 |
+
#: facebook-commerce.php:3165
|
159 |
+
msgid "Get started with Instagram Shopping"
|
160 |
msgstr ""
|
161 |
|
162 |
+
#: facebook-commerce.php:3406
|
163 |
+
#. translators: Placeholders %1$s - original error message from Facebook API
|
164 |
+
msgid "There was an issue connecting to the Facebook API: %s"
|
165 |
msgstr ""
|
166 |
|
167 |
+
#: includes/AJAX.php:174 includes/AJAX.php:243
|
168 |
+
msgid "Go to Settings"
|
169 |
msgstr ""
|
170 |
|
171 |
+
#: includes/AJAX.php:179 includes/AJAX.php:248 includes/AJAX.php:312
|
172 |
+
msgid "Cancel"
|
173 |
msgstr ""
|
174 |
|
175 |
+
#: includes/AJAX.php:187
|
176 |
+
#. translators: Placeholder %s - <br/> tag
|
177 |
+
msgid ""
|
178 |
+
"This product belongs to a category or tag that is excluded from the "
|
179 |
+
"Facebook catalog sync. It will not sync to Facebook. %sTo sync this product "
|
180 |
+
"to Facebook, click Go to Settings and remove the category or tag exclusion "
|
181 |
+
"or click Cancel and update the product's category / tag assignments."
|
182 |
msgstr ""
|
183 |
|
184 |
+
#: includes/AJAX.php:254
|
185 |
+
msgid ""
|
186 |
+
"One or more of the selected products belongs to a category or tag that is "
|
187 |
+
"excluded from the Facebook catalog sync. To sync these products to "
|
188 |
+
"Facebook, please remove the category or tag exclusion from the plugin "
|
189 |
+
"settings."
|
190 |
msgstr ""
|
191 |
|
192 |
+
#: includes/AJAX.php:306
|
193 |
+
msgid "Exclude Products"
|
194 |
msgstr ""
|
195 |
|
196 |
+
#: includes/AJAX.php:320
|
197 |
+
#. translators: Placeholder %s - <br/> tags
|
198 |
+
msgid ""
|
199 |
+
"The categories and/or tags that you have selected to exclude from sync "
|
200 |
+
"contain products that are currently synced to Facebook.%sTo exclude these "
|
201 |
+
"products from the Facebook sync, click Exclude Products. To review the "
|
202 |
+
"category / tag exclusion settings, click Cancel."
|
203 |
msgstr ""
|
204 |
|
205 |
+
#: includes/Admin/Abstract_Settings_Screen.php:72
|
206 |
+
msgid "Save changes"
|
207 |
msgstr ""
|
208 |
|
209 |
+
#. Author of the plugin/theme
|
210 |
+
msgid "Facebook"
|
211 |
msgstr ""
|
212 |
|
213 |
+
#: includes/Admin/Settings.php:131
|
214 |
+
msgid "You do not have permission to save these settings."
|
215 |
msgstr ""
|
216 |
|
217 |
+
#: includes/Admin/Settings.php:140
|
218 |
+
msgid "Your settings have been saved."
|
219 |
msgstr ""
|
220 |
|
221 |
+
#: includes/Admin/Settings.php:146
|
222 |
+
#. translators: Placeholders: %s - user-friendly error message
|
223 |
+
msgid "Your settings could not be saved. %s"
|
224 |
msgstr ""
|
225 |
|
226 |
+
#: includes/Admin/Settings_Screens/Connection.php:35
|
227 |
+
#: includes/Admin/Settings_Screens/Connection.php:36
|
228 |
msgid "Connection"
|
229 |
msgstr ""
|
230 |
|
231 |
+
#: includes/Admin/Settings_Screens/Connection.php:58
|
232 |
+
#. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
|
233 |
+
#. <a> tag, %4$s - </a> tag, %5$s - <a> tag, %6$s - </a> tag
|
234 |
+
msgid ""
|
235 |
+
"%1$sHeads up!%2$s It looks like there was a problem with reconnecting your "
|
236 |
+
"site to Facebook. Please %3$sclick here%4$s to try again, or %5$sget in "
|
237 |
+
"touch with our support team%6$s for assistance."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
238 |
msgstr ""
|
239 |
|
240 |
+
#: includes/Admin/Settings_Screens/Connection.php:126
|
241 |
+
msgid "Page"
|
242 |
msgstr ""
|
243 |
|
244 |
+
#: includes/Admin/Settings_Screens/Connection.php:130
|
245 |
+
msgid "Pixel"
|
246 |
msgstr ""
|
247 |
|
248 |
+
#: includes/Admin/Settings_Screens/Connection.php:134
|
249 |
+
msgid "Catalog"
|
250 |
msgstr ""
|
251 |
|
252 |
+
#: includes/Admin/Settings_Screens/Connection.php:139
|
253 |
+
msgid "Business Manager account"
|
|
|
254 |
msgstr ""
|
255 |
|
256 |
+
#: includes/Admin/Settings_Screens/Connection.php:143
|
257 |
+
msgid "Ad Manager account"
|
258 |
msgstr ""
|
259 |
|
260 |
+
#: includes/Admin/Settings_Screens/Connection.php:256
|
261 |
+
msgid "Reach the Right People and Sell More Online"
|
262 |
msgstr ""
|
263 |
|
264 |
+
#: includes/Admin/Settings_Screens/Connection.php:258
|
265 |
+
msgid "Grow your business on Facebook"
|
266 |
msgstr ""
|
267 |
|
268 |
+
#: includes/Admin/Settings_Screens/Connection.php:261
|
269 |
+
msgid "Use this WooCommerce and Facebook integration to:"
|
|
|
|
|
|
|
270 |
msgstr ""
|
271 |
|
272 |
+
#: includes/Admin/Settings_Screens/Connection.php:264
|
273 |
+
msgid "Create an ad in a few steps"
|
274 |
msgstr ""
|
275 |
|
276 |
+
#: includes/Admin/Settings_Screens/Connection.php:265
|
277 |
+
msgid "Use built-in best practices for online sales"
|
278 |
msgstr ""
|
279 |
|
280 |
+
#: includes/Admin/Settings_Screens/Connection.php:266
|
281 |
+
msgid "Get reporting on sales and revenue"
|
282 |
msgstr ""
|
283 |
|
284 |
+
#: includes/Admin/Settings_Screens/Connection.php:273
|
285 |
+
msgid "Create Ad"
|
286 |
msgstr ""
|
287 |
|
288 |
+
#: includes/Admin/Settings_Screens/Connection.php:278
|
289 |
+
msgid "Manage Connection"
|
290 |
msgstr ""
|
291 |
|
292 |
+
#: includes/Admin/Settings_Screens/Connection.php:288
|
293 |
+
msgid "Get Started"
|
294 |
msgstr ""
|
295 |
|
296 |
+
#: includes/Admin/Settings_Screens/Connection.php:327
|
297 |
+
msgid "Uninstall"
|
298 |
msgstr ""
|
299 |
|
300 |
+
#: includes/Admin/Settings_Screens/Connection.php:352
|
301 |
+
msgid "Debug"
|
302 |
msgstr ""
|
303 |
|
304 |
+
#: includes/Admin/Settings_Screens/Connection.php:358
|
305 |
+
msgid "Enable debug mode"
|
|
|
306 |
msgstr ""
|
307 |
|
308 |
+
#: includes/Admin/Settings_Screens/Connection.php:360
|
309 |
+
msgid "Log plugin events for debugging"
|
310 |
msgstr ""
|
311 |
|
312 |
+
#: includes/Admin/Settings_Screens/Connection.php:361
|
313 |
+
msgid "Only enable this if you are experiencing problems with the plugin."
|
314 |
msgstr ""
|
315 |
|
316 |
+
#: includes/Admin/Settings_Screens/Messenger.php:39
|
317 |
+
#: includes/Admin/Settings_Screens/Messenger.php:40
|
318 |
+
#: includes/Admin/Settings_Screens/Messenger.php:143
|
319 |
+
msgid "Messenger"
|
320 |
msgstr ""
|
321 |
|
322 |
+
#: includes/Admin/Settings_Screens/Messenger.php:119
|
323 |
+
#. translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag
|
324 |
+
msgid "%1$sClick here%2$s to manage your Messenger greeting and colors."
|
325 |
msgstr ""
|
326 |
|
327 |
+
#: includes/Admin/Settings_Screens/Messenger.php:149
|
328 |
+
msgid "Enable Messenger"
|
329 |
msgstr ""
|
330 |
|
331 |
+
#: includes/Admin/Settings_Screens/Messenger.php:151
|
332 |
+
msgid "Enable and customize Facebook Messenger on your store"
|
|
|
|
|
|
|
|
|
|
|
333 |
msgstr ""
|
334 |
|
335 |
+
#: includes/Admin/Settings_Screens/Messenger.php:161
|
336 |
+
msgid "Language"
|
337 |
msgstr ""
|
338 |
|
339 |
+
#: includes/Admin/Settings_Screens/Messenger.php:166
|
340 |
+
msgid "Greeting & Colors"
|
341 |
msgstr ""
|
342 |
|
343 |
+
#: includes/Admin/Settings_Screens/Messenger.php:188
|
344 |
+
#. translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag
|
345 |
+
msgid "Please %1$sconnect to Facebook%2$s to enable and manage Facebook Messenger."
|
|
|
346 |
msgstr ""
|
347 |
|
348 |
+
#: includes/Admin/Settings_Screens/Messenger.php:239
|
349 |
+
#. translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag
|
350 |
msgid ""
|
351 |
+
"There was an error communicating with the Facebook Business Extension. "
|
352 |
+
"%1$sClick here%2$s to manage your Messenger settings."
|
|
|
|
|
|
|
|
|
|
|
|
|
353 |
msgstr ""
|
354 |
|
355 |
+
#: includes/Admin/Settings_Screens/Messenger.php:309
|
356 |
+
msgid "Please try again."
|
357 |
msgstr ""
|
358 |
|
359 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:42
|
360 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:43
|
361 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:110
|
362 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:205
|
363 |
+
msgid "Product sync"
|
|
|
|
|
364 |
msgstr ""
|
365 |
|
366 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:71
|
367 |
+
#. translators: Placeholders: {count} number of remaining items
|
368 |
+
msgid "{count} item remaining."
|
369 |
+
msgid_plural "{count} items remaining."
|
|
|
370 |
msgstr[0] ""
|
371 |
msgstr[1] ""
|
372 |
|
373 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:83
|
374 |
#. translators: Placeholders %s - html code for a spinner icon
|
375 |
msgid "Your products will now be resynced to Facebook, this may take some time."
|
376 |
msgstr ""
|
377 |
|
378 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:84
|
|
|
|
|
|
|
|
|
379 |
msgid ""
|
380 |
"Facebook for WooCommerce automatically syncs your products on "
|
381 |
"create/update. Are you sure you want to force product resync?\n"
|
385 |
"did not sync."
|
386 |
msgstr ""
|
387 |
|
388 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:85
|
389 |
+
msgid "Your products are syncing - you may safely leave this page %s"
|
390 |
msgstr ""
|
391 |
|
392 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:88
|
393 |
+
msgid "There was an error trying to sync the products to Facebook."
|
|
|
|
|
394 |
msgstr ""
|
395 |
|
396 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:89
|
397 |
+
msgid ""
|
398 |
+
"Something went wrong while uploading the product information, please try "
|
399 |
+
"again."
|
400 |
msgstr ""
|
401 |
|
402 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:118
|
403 |
+
msgid "Sync products"
|
|
|
|
|
404 |
msgstr ""
|
405 |
|
406 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:210
|
407 |
+
msgid "Enable product sync"
|
408 |
msgstr ""
|
409 |
|
410 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:218
|
411 |
+
msgid "Exclude categories from sync"
|
|
|
|
|
412 |
msgstr ""
|
413 |
|
414 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:222
|
415 |
+
msgid "Products in one or more of these categories will not sync to Facebook."
|
416 |
msgstr ""
|
417 |
|
418 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:226
|
419 |
+
msgid "Search for a product category…"
|
420 |
msgstr ""
|
421 |
|
422 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:232
|
423 |
+
msgid "Exclude tags from sync"
|
424 |
msgstr ""
|
425 |
|
426 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:236
|
427 |
+
msgid "Products with one or more of these tags will not sync to Facebook."
|
|
|
428 |
msgstr ""
|
429 |
|
430 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:240
|
431 |
+
msgid "Search for a product tag…"
|
|
|
|
|
432 |
msgstr ""
|
433 |
|
434 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:246
|
435 |
+
msgid "Product description sync"
|
|
|
|
|
436 |
msgstr ""
|
437 |
|
438 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:249
|
439 |
+
msgid "Choose which product description to display in the Facebook catalog."
|
|
|
|
|
440 |
msgstr ""
|
441 |
|
442 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:252
|
443 |
+
msgid "Standard description"
|
|
|
|
|
444 |
msgstr ""
|
445 |
|
446 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:253
|
447 |
+
msgid "Short description"
|
448 |
msgstr ""
|
449 |
|
450 |
+
#: includes/Admin/Settings_Screens/Product_Sync.php:274
|
451 |
+
#. translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag
|
452 |
+
msgid "Please %1$sconnect to Facebook%2$s to enable and manage product sync."
|
453 |
msgstr ""
|
454 |
|
455 |
+
#: includes/Admin.php:147 includes/Admin.php:971 includes/Admin.php:1076
|
456 |
+
msgid "Facebook sync"
|
457 |
msgstr ""
|
458 |
|
459 |
+
#: includes/Admin.php:174 includes/Admin.php:206
|
460 |
+
msgid "Sync and show"
|
461 |
msgstr ""
|
462 |
|
463 |
+
#: includes/Admin.php:176 includes/Admin.php:207
|
464 |
+
msgid "Sync and hide"
|
465 |
msgstr ""
|
466 |
|
467 |
+
#: includes/Admin.php:181 includes/Admin.php:208 includes/Admin.php:975
|
468 |
+
#: includes/Admin.php:1080
|
469 |
+
msgid "Do not sync"
|
470 |
msgstr ""
|
471 |
|
472 |
+
#: includes/Admin.php:205
|
473 |
+
msgid "Filter by Facebook sync setting"
|
474 |
msgstr ""
|
475 |
|
476 |
+
#: includes/Admin.php:606
|
477 |
+
msgid "Include in Facebook sync"
|
|
|
|
|
|
|
|
|
|
|
478 |
msgstr ""
|
479 |
|
480 |
+
#: includes/Admin.php:607
|
481 |
+
msgid "Exclude from Facebook sync"
|
|
|
|
|
|
|
|
|
|
|
|
|
482 |
msgstr ""
|
483 |
|
484 |
+
#: includes/Admin.php:800
|
485 |
+
#. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
|
486 |
+
#. <a> tag, %4$s - <a> tag
|
487 |
+
msgid ""
|
488 |
+
"%1$sHeads up!%2$s If this product was previously visible in Facebook, you "
|
489 |
+
"may need to delete it from the %3$sFacebook catalog%4$s to completely hide "
|
490 |
+
"it from customer view."
|
491 |
+
msgid_plural ""
|
492 |
+
"%1$sHeads up!%2$s If these products were previously visible in Facebook, "
|
493 |
+
"you may need to delete them from the %3$sFacebook catalog%4$s to completely "
|
494 |
+
"hide them from customer view."
|
495 |
+
msgstr[0] ""
|
496 |
+
msgstr[1] ""
|
497 |
+
|
498 |
+
#: includes/Admin.php:805
|
499 |
msgid "Don't show this notice again"
|
500 |
msgstr ""
|
501 |
|
502 |
+
#: includes/Admin.php:837
|
503 |
+
#. translators: Placeholders: %1$s - number of affected products, %2$s opening
|
504 |
+
#. HTML <a> tag, %3$s - closing HTML </a> tag, %4$s - opening HTML <a> tag,
|
505 |
+
#. %5$s - closing HTML </a> tag
|
506 |
msgid ""
|
507 |
+
"%2$s%1$s product%3$s or some of its variations could not be updated to show "
|
508 |
+
"in the Facebook catalog — %4$sFacebook Commerce Policies%5$s prohibit "
|
509 |
+
"selling some product types (like virtual products). You may still advertise "
|
510 |
+
"Virtual products on Facebook."
|
511 |
+
msgid_plural ""
|
512 |
+
"%2$s%1$s products%3$s or some of their variations could not be updated to "
|
513 |
+
"show in the Facebook catalog — %4$sFacebook Commerce Policies%5$s prohibit "
|
514 |
+
"selling some product types (like virtual products). You may still advertise "
|
515 |
+
"Virtual products on Facebook."
|
516 |
+
msgstr[0] ""
|
517 |
+
msgstr[1] ""
|
518 |
|
519 |
+
#: includes/Admin.php:900
|
520 |
#. translators: Placeholders: %1$s - opening HTML <strong> tag, %2$s - closing
|
521 |
#. HTML </strong> tag, %3$s - opening HTML <a> tag, %4$s - closing HTML </a>
|
522 |
#. tag
|
523 |
msgid ""
|
524 |
+
"%1$sHeads up!%2$s Facebook's %3$sCommerce Policies%4$s do not support "
|
525 |
+
"selling virtual products, so we have hidden your synced Virtual products in "
|
526 |
+
"your Facebook catalog. You may still advertise Virtual products on Facebook."
|
527 |
msgstr ""
|
528 |
|
529 |
+
#: includes/Admin.php:973 includes/Admin.php:1078
|
530 |
+
msgid "Sync and show in catalog"
|
531 |
+
msgstr ""
|
532 |
+
|
533 |
+
#: includes/Admin.php:974 includes/Admin.php:1079
|
534 |
+
msgid "Sync and hide in catalog"
|
|
|
|
|
535 |
msgstr ""
|
536 |
|
537 |
+
#: includes/Admin.php:982 includes/Admin.php:1090
|
538 |
msgid "Facebook Description"
|
539 |
msgstr ""
|
540 |
|
541 |
+
#: includes/Admin.php:984 includes/Admin.php:1092
|
542 |
msgid ""
|
543 |
"Custom (plain-text only) description for product on Facebook. If blank, "
|
544 |
"product description will be used. If product description is blank, "
|
545 |
"shortname will be used."
|
546 |
msgstr ""
|
547 |
|
548 |
+
#: includes/Admin.php:993 includes/Admin.php:1103
|
549 |
msgid "Facebook Product Image"
|
550 |
msgstr ""
|
551 |
|
552 |
+
#: includes/Admin.php:995 includes/Admin.php:1105
|
553 |
msgid ""
|
554 |
"Choose the product image that should be synced to the Facebook catalog for "
|
555 |
"this product. If using a custom image, please enter an absolute URL (e.g. "
|
556 |
"https://domain.com/image.jpg)."
|
557 |
msgstr ""
|
558 |
|
559 |
+
#: includes/Admin.php:997
|
560 |
msgid "Use WooCommerce image"
|
561 |
msgstr ""
|
562 |
|
563 |
+
#: includes/Admin.php:998 includes/Admin.php:1109
|
564 |
msgid "Use custom image"
|
565 |
msgstr ""
|
566 |
|
567 |
+
#: includes/Admin.php:1007 includes/Admin.php:1119
|
568 |
msgid "Custom Image URL"
|
569 |
msgstr ""
|
570 |
|
571 |
+
#: includes/Admin.php:1016 includes/Admin.php:1130
|
572 |
#. translators: Placeholders %1$s - WC currency symbol
|
573 |
msgid "Facebook Price (%1$s)"
|
574 |
msgstr ""
|
575 |
|
576 |
+
#: includes/Admin.php:1020 includes/Admin.php:1134
|
577 |
msgid ""
|
578 |
"Custom price for product on Facebook. Please enter in monetary decimal (.) "
|
579 |
"format without thousand separators and currency symbols. If blank, product "
|
580 |
"price will be used."
|
581 |
msgstr ""
|
582 |
|
583 |
+
#: includes/Admin.php:1107
|
584 |
msgid "Use variation image"
|
585 |
msgstr ""
|
586 |
|
587 |
+
#: includes/Admin.php:1108
|
588 |
msgid "Use parent image"
|
589 |
msgstr ""
|
590 |
|
591 |
+
#: includes/Admin.php:1248
|
592 |
msgid "Close modal panel"
|
593 |
msgstr ""
|
594 |
|
595 |
+
#: includes/Handlers/Connection.php:249
|
596 |
+
msgid "Connection complete! Thanks for using Facebook for WooCommerce."
|
597 |
+
msgstr ""
|
598 |
+
|
599 |
+
#: includes/Handlers/Connection.php:275
|
600 |
+
msgid "You do not have permission to uninstall Facebook Business Extension."
|
601 |
+
msgstr ""
|
602 |
+
|
603 |
+
#: includes/Handlers/Connection.php:285
|
604 |
+
msgid "Uninstall successful"
|
605 |
+
msgstr ""
|
606 |
+
|
607 |
+
#: includes/Handlers/Connection.php:291
|
608 |
+
msgid "Uninstall unsuccessful. Please try again."
|
609 |
+
msgstr ""
|
610 |
+
|
611 |
+
#: includes/Products/Sync/Background.php:64
|
612 |
+
msgid "Job data key \"%s\" not set"
|
613 |
+
msgstr ""
|
614 |
+
|
615 |
+
#: includes/Products/Sync/Background.php:68
|
616 |
+
msgid "Job data key \"%s\" is not an array"
|
617 |
+
msgstr ""
|
618 |
+
|
619 |
+
#: includes/Products/Sync/Background.php:150
|
620 |
+
msgid ""
|
621 |
+
"There was an error trying sync products using the Catalog Batch API for job "
|
622 |
+
"%s: %s"
|
623 |
+
msgstr ""
|
624 |
+
|
625 |
#: includes/fbgraph.php:104
|
626 |
msgid "HTTP %s: %s"
|
627 |
msgstr ""
|
691 |
msgid "https://www.facebook.com/"
|
692 |
msgstr ""
|
693 |
|
694 |
+
#: facebook-commerce-messenger-chat.php:234
|
695 |
msgctxt "language"
|
696 |
msgid "English (United States)"
|
697 |
msgstr ""
|
includes/AJAX.php
CHANGED
@@ -10,6 +10,8 @@
|
|
10 |
|
11 |
namespace SkyVerge\WooCommerce\Facebook;
|
12 |
|
|
|
|
|
13 |
defined( 'ABSPATH' ) or exit;
|
14 |
|
15 |
/**
|
@@ -34,8 +36,62 @@ class AJAX {
|
|
34 |
// maybe output a modal prompt when setting excluded terms
|
35 |
add_action( 'wp_ajax_facebook_for_woocommerce_set_excluded_terms_prompt', [ $this, 'handle_set_excluded_terms_prompt' ] );
|
36 |
|
37 |
-
//
|
38 |
-
add_action( '
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
}
|
40 |
|
41 |
|
@@ -67,29 +123,7 @@ class AJAX {
|
|
67 |
|
68 |
if ( $product instanceof \WC_Product ) {
|
69 |
|
70 |
-
if ( '
|
71 |
-
|
72 |
-
ob_start();
|
73 |
-
|
74 |
-
?>
|
75 |
-
<button
|
76 |
-
id="facebook-for-woocommerce-hide-products"
|
77 |
-
class="button button-large button-primary facebook-for-woocommerce-toggle-product-visibility hide-products"
|
78 |
-
><?php esc_html_e( 'Hide Product', 'facebook-for-woocommerce' ); ?></button>
|
79 |
-
<button
|
80 |
-
id="facebook-for-woocommerce-do-not-hide-products"
|
81 |
-
class="button button-large button-primary facebook-for-woocommerce-toggle-product-visibility show-products"
|
82 |
-
><?php esc_html_e( 'Do Not Hide Product', 'facebook-for-woocommerce' ); ?></button>
|
83 |
-
<?php
|
84 |
-
|
85 |
-
$buttons = ob_get_clean();
|
86 |
-
|
87 |
-
wp_send_json_error( [
|
88 |
-
'message' => __( 'This product will no longer be updated in your Facebook catalog. Would you like to hide this product from your Facebook shop?', 'facebook-for-woocommerce' ),
|
89 |
-
'buttons' => $buttons,
|
90 |
-
] );
|
91 |
-
|
92 |
-
} elseif ( ( 'enabled' === $sync_enabled && ! $product->is_type( 'variable' ) ) || ( 'enabled' === $var_sync_enabled && $product->is_type( 'variable' ) ) ) {
|
93 |
|
94 |
$has_excluded_terms = false;
|
95 |
|
@@ -98,6 +132,9 @@ class AJAX {
|
|
98 |
// try with categories first, since we have already IDs
|
99 |
$has_excluded_terms = ! empty( $product_cats ) && array_intersect( $product_cats, $integration->get_excluded_product_category_ids() );
|
100 |
|
|
|
|
|
|
|
101 |
// try next with tags, but WordPress only gives us tag names
|
102 |
if ( ! $has_excluded_terms && ! empty( $product_tags ) ) {
|
103 |
|
@@ -105,13 +142,19 @@ class AJAX {
|
|
105 |
|
106 |
foreach ( $product_tags as $product_tag_name_or_id ) {
|
107 |
|
108 |
-
|
|
|
|
|
109 |
|
110 |
$product_tag_ids[] = $term->term_id;
|
111 |
|
112 |
-
}
|
113 |
|
114 |
-
$
|
|
|
|
|
|
|
|
|
115 |
}
|
116 |
}
|
117 |
|
@@ -127,7 +170,7 @@ class AJAX {
|
|
127 |
<a
|
128 |
id="facebook-for-woocommerce-go-to-settings"
|
129 |
class="button button-large"
|
130 |
-
href="<?php echo esc_url( add_query_arg( '
|
131 |
><?php esc_html_e( 'Go to Settings', 'facebook-for-woocommerce' ); ?></a>
|
132 |
<button
|
133 |
id="facebook-for-woocommerce-cancel-sync"
|
@@ -171,73 +214,46 @@ class AJAX {
|
|
171 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
172 |
$toggle = isset( $_POST['toggle'] ) ? (string) $_POST['toggle'] : '';
|
173 |
|
174 |
-
if ( ! empty( $product_ids ) && ! empty( $toggle ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
175 |
|
176 |
-
|
177 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
|
179 |
ob_start();
|
180 |
|
181 |
?>
|
|
|
|
|
|
|
|
|
|
|
182 |
<button
|
183 |
-
id="facebook-for-woocommerce-
|
184 |
-
class="button button-large button-primary
|
185 |
-
|
186 |
-
|
187 |
-
id="facebook-for-woocommerce-do-not-hide-products"
|
188 |
-
class="button button-large button-primary facebook-for-woocommerce-toggle-product-visibility show-products"
|
189 |
-
><?php esc_html_e( 'Do Not Hide Products', 'facebook-for-woocommerce' ); ?></button>
|
190 |
<?php
|
191 |
|
192 |
$buttons = ob_get_clean();
|
193 |
|
194 |
wp_send_json_error( [
|
195 |
-
'message' => __( '
|
196 |
'buttons' => $buttons,
|
197 |
] );
|
198 |
-
|
199 |
-
// merchant wants to enable sync in Facebook multiple products: we must check if they belong to excluded categories, and perhaps warn them
|
200 |
-
} elseif ( 'facebook_include' === $toggle && ( $integration = facebook_for_woocommerce()->get_integration() ) ) {
|
201 |
-
|
202 |
-
$has_excluded_term = false;
|
203 |
-
|
204 |
-
foreach ( $product_ids as $product_id ) {
|
205 |
-
|
206 |
-
$product = wc_get_product( $product_id );
|
207 |
-
|
208 |
-
// product belongs to at least one excluded term: break the loop
|
209 |
-
if ( $product instanceof \WC_Product && Products::is_sync_excluded_for_product_terms( $product ) ) {
|
210 |
-
|
211 |
-
$has_excluded_term = true;
|
212 |
-
break;
|
213 |
-
}
|
214 |
-
}
|
215 |
-
|
216 |
-
// show modal if there's at least one product that belongs to an excluded term
|
217 |
-
if ( $has_excluded_term ) {
|
218 |
-
|
219 |
-
ob_start();
|
220 |
-
|
221 |
-
?>
|
222 |
-
<a
|
223 |
-
id="facebook-for-woocommerce-go-to-settings"
|
224 |
-
class="button button-large"
|
225 |
-
href="<?php echo esc_url( add_query_arg( 'section', \WC_Facebookcommerce::INTEGRATION_ID, admin_url( 'admin.php?page=wc-settings&tab=integration' ) ) ); ?>"
|
226 |
-
><?php esc_html_e( 'Go to Settings', 'facebook-for-woocommerce' ); ?></a>
|
227 |
-
<button
|
228 |
-
id="facebook-for-woocommerce-cancel-sync"
|
229 |
-
class="button button-large button-primary"
|
230 |
-
onclick="jQuery( '.modal-close' ).trigger( 'click' )"
|
231 |
-
><?php esc_html_e( 'Cancel', 'facebook-for-woocommerce' ); ?></button>
|
232 |
-
<?php
|
233 |
-
|
234 |
-
$buttons = ob_get_clean();
|
235 |
-
|
236 |
-
wp_send_json_error( [
|
237 |
-
'message' => __( '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.', 'facebook-for-woocommerce' ),
|
238 |
-
'buttons' => $buttons,
|
239 |
-
] );
|
240 |
-
}
|
241 |
}
|
242 |
}
|
243 |
|
@@ -289,12 +305,6 @@ class AJAX {
|
|
289 |
class="button button-large button-primary facebook-for-woocommerce-confirm-settings-change"
|
290 |
><?php esc_html_e( 'Exclude Products', 'facebook-for-woocommerce' ); ?></button>
|
291 |
|
292 |
-
<!-- TODO: restore for FBE 2.0
|
293 |
-
<button
|
294 |
-
id="facebook-for-woocommerce-confirm-settings-change-hide-products"
|
295 |
-
class="button button-large button-primary facebook-for-woocommerce-confirm-settings-change hide-products"
|
296 |
-
><?php esc_html_e( 'Exclude Products and Hide in Facebook', 'facebook-for-woocommerce' ); ?></button> -->
|
297 |
-
|
298 |
<button
|
299 |
id="facebook-for-woocommerce-cancel-settings-change"
|
300 |
class="button button-large button-primary"
|
@@ -431,161 +441,4 @@ class AJAX {
|
|
431 |
}
|
432 |
|
433 |
|
434 |
-
/**
|
435 |
-
* Gets an array of product IDs data for handling visibility (helper method).
|
436 |
-
*
|
437 |
-
* @see \SkyVerge\WooCommerce\Facebook\AJAX::set_products_visibility()
|
438 |
-
*
|
439 |
-
* @since 1.10.2
|
440 |
-
*
|
441 |
-
* @param array $terms_data term data with product IDs and visibility
|
442 |
-
* @return array product IDs and visibility data
|
443 |
-
*/
|
444 |
-
private function get_product_ids_for_visibility_from_terms( $terms_data ) {
|
445 |
-
|
446 |
-
$products = [];
|
447 |
-
|
448 |
-
foreach ( $terms_data as $term_data ) {
|
449 |
-
|
450 |
-
if ( ! isset( $term_data['term_id'], $term_data['taxonomy'], $term_data['visibility'] ) ) {
|
451 |
-
continue;
|
452 |
-
}
|
453 |
-
|
454 |
-
if ( 'product_cat' === $term_data['taxonomy'] ) {
|
455 |
-
$tax_query_arg = 'category';
|
456 |
-
} elseif( 'product_tag' === $term_data['taxonomy'] ) {
|
457 |
-
$tax_query_arg = 'tag';
|
458 |
-
} else {
|
459 |
-
continue;
|
460 |
-
}
|
461 |
-
|
462 |
-
$term = get_term_by( 'id', $term_data['term_id'], $term_data['taxonomy'] );
|
463 |
-
|
464 |
-
if ( ! $term instanceof \WP_Term ) {
|
465 |
-
continue;
|
466 |
-
}
|
467 |
-
|
468 |
-
$found_products = wc_get_products( [
|
469 |
-
'limit' => -1,
|
470 |
-
'return' => 'ids',
|
471 |
-
$tax_query_arg => [ $term->slug ],
|
472 |
-
] );
|
473 |
-
|
474 |
-
foreach ( $found_products as $product_id ) {
|
475 |
-
|
476 |
-
$products[] = [
|
477 |
-
'product_id' => $product_id,
|
478 |
-
'visibility' => $term_data['visibility']
|
479 |
-
];
|
480 |
-
}
|
481 |
-
}
|
482 |
-
|
483 |
-
return $products;
|
484 |
-
}
|
485 |
-
|
486 |
-
|
487 |
-
/**
|
488 |
-
* Sets products visibility in Facebook.
|
489 |
-
*
|
490 |
-
* @internal
|
491 |
-
*
|
492 |
-
* @since 1.10.0
|
493 |
-
*/
|
494 |
-
public function set_products_visibility() {
|
495 |
-
|
496 |
-
check_ajax_referer( 'set-products-visibility', 'security' );
|
497 |
-
|
498 |
-
// phpcs:disable WordPress.Security.NonceVerification.Missing
|
499 |
-
|
500 |
-
$integration = facebook_for_woocommerce()->get_integration();
|
501 |
-
$products = isset( $_POST['products'] ) ? (array) $_POST['products'] : [];
|
502 |
-
|
503 |
-
if ( ! empty( $_POST['product_categories'] ) && is_array( $_POST['product_categories'] ) ) {
|
504 |
-
$products = array_merge( $products, $this->get_product_ids_for_visibility_from_terms( $_POST['product_categories'] ) );
|
505 |
-
}
|
506 |
-
|
507 |
-
if ( ! empty( $_POST['product_tags'] ) && is_array( $_POST['product_tags'] ) ) {
|
508 |
-
$products = array_merge( $products, $this->get_product_ids_for_visibility_from_terms( $_POST['product_tags'] ) );
|
509 |
-
}
|
510 |
-
|
511 |
-
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
512 |
-
|
513 |
-
$error = 'No products found to set visibility for.'; // console error message
|
514 |
-
|
515 |
-
if ( $integration && ! empty( $products ) ) {
|
516 |
-
|
517 |
-
$processed_products = [];
|
518 |
-
|
519 |
-
foreach ( $products as $product_data ) {
|
520 |
-
|
521 |
-
$product_id = isset( $product_data['product_id'] ) ? absint( $product_data['product_id'] ) : 0;
|
522 |
-
|
523 |
-
// bail if already processed
|
524 |
-
if ( in_array( $product_id, $processed_products, true ) ) {
|
525 |
-
continue;
|
526 |
-
}
|
527 |
-
|
528 |
-
$visibility_meta_value = isset( $product_data['visibility'] ) ? wc_string_to_bool( $product_data['visibility'] ) : null;
|
529 |
-
|
530 |
-
// bail if visibility value is not valid
|
531 |
-
if ( ! is_bool( $visibility_meta_value ) ) {
|
532 |
-
continue;
|
533 |
-
}
|
534 |
-
|
535 |
-
$visibility_api_value = $visibility_meta_value ? $integration::FB_SHOP_PRODUCT_VISIBLE : $integration::FB_SHOP_PRODUCT_HIDDEN;
|
536 |
-
|
537 |
-
$product = $product_id > 0 ? wc_get_product( $product_id ) : null;
|
538 |
-
|
539 |
-
if ( $product instanceof \WC_Product ) {
|
540 |
-
|
541 |
-
// also extend toggle to child variations
|
542 |
-
if ( $product->is_type( 'variable' ) ) {
|
543 |
-
|
544 |
-
foreach ( $product->get_children() as $variation_id ) {
|
545 |
-
|
546 |
-
// bail if already processed
|
547 |
-
if ( in_array( $variation_id, $processed_products, true ) ) {
|
548 |
-
continue;
|
549 |
-
}
|
550 |
-
|
551 |
-
if ( $variation_product = wc_get_product( $variation_id ) ) {
|
552 |
-
|
553 |
-
$fb_item_id = $integration->get_product_fbid( \WC_Facebookcommerce_Integration::FB_PRODUCT_ITEM_ID, $variation_product->get_id() );
|
554 |
-
$fb_request = $integration->fbgraph->update_product_item( $fb_item_id, [
|
555 |
-
'visibility' => $visibility_api_value,
|
556 |
-
] );
|
557 |
-
|
558 |
-
if ( $integration->check_api_result( $fb_request ) ) {
|
559 |
-
Products::set_product_visibility( $variation_product, $visibility_meta_value );
|
560 |
-
}
|
561 |
-
|
562 |
-
$processed_products[] = $variation_id;
|
563 |
-
}
|
564 |
-
}
|
565 |
-
|
566 |
-
Products::set_product_visibility( $product, $visibility_meta_value );
|
567 |
-
|
568 |
-
} else {
|
569 |
-
|
570 |
-
$fb_item_id = $integration->get_product_fbid( \WC_Facebookcommerce_Integration::FB_PRODUCT_ITEM_ID, $product->get_id() );
|
571 |
-
$fb_request = $integration->fbgraph->update_product_item( $fb_item_id, [
|
572 |
-
'visibility' => $visibility_api_value,
|
573 |
-
] );
|
574 |
-
|
575 |
-
if ( $integration->check_api_result( $fb_request ) ) {
|
576 |
-
Products::set_product_visibility( $product, $visibility_meta_value );
|
577 |
-
}
|
578 |
-
}
|
579 |
-
|
580 |
-
$processed_products[] = $product_id;
|
581 |
-
}
|
582 |
-
}
|
583 |
-
|
584 |
-
wp_send_json_success( $processed_products );
|
585 |
-
}
|
586 |
-
|
587 |
-
wp_send_json_error( $error );
|
588 |
-
}
|
589 |
-
|
590 |
-
|
591 |
}
|
10 |
|
11 |
namespace SkyVerge\WooCommerce\Facebook;
|
12 |
|
13 |
+
use SkyVerge\WooCommerce\Facebook\Admin\Settings_Screens\Product_Sync;
|
14 |
+
|
15 |
defined( 'ABSPATH' ) or exit;
|
16 |
|
17 |
/**
|
36 |
// maybe output a modal prompt when setting excluded terms
|
37 |
add_action( 'wp_ajax_facebook_for_woocommerce_set_excluded_terms_prompt', [ $this, 'handle_set_excluded_terms_prompt' ] );
|
38 |
|
39 |
+
// sync all products via AJAX
|
40 |
+
add_action( 'wp_ajax_wc_facebook_sync_products', [ $this, 'sync_products' ] );
|
41 |
+
|
42 |
+
// get the current sync status
|
43 |
+
add_action( 'wp_ajax_wc_facebook_get_sync_status', [ $this, 'get_sync_status' ] );
|
44 |
+
}
|
45 |
+
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Syncs all products via AJAX.
|
49 |
+
*
|
50 |
+
* @internal
|
51 |
+
*
|
52 |
+
* @since 2.0.0
|
53 |
+
*/
|
54 |
+
public function sync_products() {
|
55 |
+
|
56 |
+
check_admin_referer( Product_Sync::ACTION_SYNC_PRODUCTS, 'nonce' );
|
57 |
+
|
58 |
+
facebook_for_woocommerce()->get_products_sync_handler()->create_or_update_all_products();
|
59 |
+
|
60 |
+
wp_send_json_success();
|
61 |
+
}
|
62 |
+
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Gets the current sync status.
|
66 |
+
*
|
67 |
+
* @internal
|
68 |
+
*
|
69 |
+
* @since 2.0.0
|
70 |
+
*/
|
71 |
+
public function get_sync_status() {
|
72 |
+
|
73 |
+
check_admin_referer( Product_Sync::ACTION_GET_SYNC_STATUS, 'nonce' );
|
74 |
+
|
75 |
+
$remaining_products = 0;
|
76 |
+
|
77 |
+
$jobs = facebook_for_woocommerce()->get_products_sync_background_handler()->get_jobs( [
|
78 |
+
'status' => 'processing',
|
79 |
+
] );
|
80 |
+
|
81 |
+
if ( ! empty( $jobs ) ) {
|
82 |
+
|
83 |
+
// there should only be one processing job at a time, pluck the latest to convey status
|
84 |
+
$job = $jobs[0];
|
85 |
+
|
86 |
+
$remaining_products = ! empty( $job->total ) ? $job->total : count( $job->requests );
|
87 |
+
|
88 |
+
if ( ! empty( $job->progress ) ) {
|
89 |
+
$remaining_products -= $job->progress;
|
90 |
+
}
|
91 |
+
|
92 |
+
}
|
93 |
+
|
94 |
+
wp_send_json_success( $remaining_products );
|
95 |
}
|
96 |
|
97 |
|
123 |
|
124 |
if ( $product instanceof \WC_Product ) {
|
125 |
|
126 |
+
if ( ( 'enabled' === $sync_enabled && ! $product->is_type( 'variable' ) ) || ( 'enabled' === $var_sync_enabled && $product->is_type( 'variable' ) ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
|
128 |
$has_excluded_terms = false;
|
129 |
|
132 |
// try with categories first, since we have already IDs
|
133 |
$has_excluded_terms = ! empty( $product_cats ) && array_intersect( $product_cats, $integration->get_excluded_product_category_ids() );
|
134 |
|
135 |
+
// the form post can send an array with empty items, so filter them out
|
136 |
+
$product_tags = array_filter( $product_tags );
|
137 |
+
|
138 |
// try next with tags, but WordPress only gives us tag names
|
139 |
if ( ! $has_excluded_terms && ! empty( $product_tags ) ) {
|
140 |
|
142 |
|
143 |
foreach ( $product_tags as $product_tag_name_or_id ) {
|
144 |
|
145 |
+
$term = get_term_by( 'name', $product_tag_name_or_id, 'product_tag' );
|
146 |
+
|
147 |
+
if ( $term instanceof \WP_Term ) {
|
148 |
|
149 |
$product_tag_ids[] = $term->term_id;
|
150 |
|
151 |
+
} else {
|
152 |
|
153 |
+
$term = get_term( (int) $product_tag_name_or_id, 'product_tag' );
|
154 |
+
|
155 |
+
if ( $term instanceof \WP_Term ) {
|
156 |
+
$product_tag_ids[] = $term->term_id;
|
157 |
+
}
|
158 |
}
|
159 |
}
|
160 |
|
170 |
<a
|
171 |
id="facebook-for-woocommerce-go-to-settings"
|
172 |
class="button button-large"
|
173 |
+
href="<?php echo esc_url( add_query_arg( 'tab', Product_Sync::ID, facebook_for_woocommerce()->get_settings_url() ) ); ?>"
|
174 |
><?php esc_html_e( 'Go to Settings', 'facebook-for-woocommerce' ); ?></a>
|
175 |
<button
|
176 |
id="facebook-for-woocommerce-cancel-sync"
|
214 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
215 |
$toggle = isset( $_POST['toggle'] ) ? (string) $_POST['toggle'] : '';
|
216 |
|
217 |
+
if ( ! empty( $product_ids ) && ! empty( $toggle ) && 'facebook_include' === $toggle ) {
|
218 |
+
|
219 |
+
$has_excluded_term = false;
|
220 |
+
|
221 |
+
foreach ( $product_ids as $product_id ) {
|
222 |
+
|
223 |
+
$product = wc_get_product( $product_id );
|
224 |
|
225 |
+
// product belongs to at least one excluded term: break the loop
|
226 |
+
if ( $product instanceof \WC_Product && Products::is_sync_excluded_for_product_terms( $product ) ) {
|
227 |
+
|
228 |
+
$has_excluded_term = true;
|
229 |
+
break;
|
230 |
+
}
|
231 |
+
}
|
232 |
+
|
233 |
+
// show modal if there's at least one product that belongs to an excluded term
|
234 |
+
if ( $has_excluded_term ) {
|
235 |
|
236 |
ob_start();
|
237 |
|
238 |
?>
|
239 |
+
<a
|
240 |
+
id="facebook-for-woocommerce-go-to-settings"
|
241 |
+
class="button button-large"
|
242 |
+
href="<?php echo esc_url( add_query_arg( 'tab', Product_Sync::ID, facebook_for_woocommerce()->get_settings_url() ) ); ?>"
|
243 |
+
><?php esc_html_e( 'Go to Settings', 'facebook-for-woocommerce' ); ?></a>
|
244 |
<button
|
245 |
+
id="facebook-for-woocommerce-cancel-sync"
|
246 |
+
class="button button-large button-primary"
|
247 |
+
onclick="jQuery( '.modal-close' ).trigger( 'click' )"
|
248 |
+
><?php esc_html_e( 'Cancel', 'facebook-for-woocommerce' ); ?></button>
|
|
|
|
|
|
|
249 |
<?php
|
250 |
|
251 |
$buttons = ob_get_clean();
|
252 |
|
253 |
wp_send_json_error( [
|
254 |
+
'message' => __( '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.', 'facebook-for-woocommerce' ),
|
255 |
'buttons' => $buttons,
|
256 |
] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
257 |
}
|
258 |
}
|
259 |
|
305 |
class="button button-large button-primary facebook-for-woocommerce-confirm-settings-change"
|
306 |
><?php esc_html_e( 'Exclude Products', 'facebook-for-woocommerce' ); ?></button>
|
307 |
|
|
|
|
|
|
|
|
|
|
|
|
|
308 |
<button
|
309 |
id="facebook-for-woocommerce-cancel-settings-change"
|
310 |
class="button button-large button-primary"
|
441 |
}
|
442 |
|
443 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
444 |
}
|
includes/API.php
ADDED
@@ -0,0 +1,588 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API\Request;
|
16 |
+
use SkyVerge\WooCommerce\Facebook\API\Response;
|
17 |
+
use SkyVerge\WooCommerce\Facebook\Events\Event;
|
18 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* API handler.
|
22 |
+
*
|
23 |
+
* @since 2.0.0
|
24 |
+
*
|
25 |
+
* @method Response perform_request( $request )
|
26 |
+
*/
|
27 |
+
class API extends Framework\SV_WC_API_Base {
|
28 |
+
|
29 |
+
|
30 |
+
use API\Traits\Rate_Limited_API;
|
31 |
+
|
32 |
+
|
33 |
+
/** @var string URI used for the request */
|
34 |
+
protected $request_uri = 'https://graph.facebook.com/v7.0';
|
35 |
+
|
36 |
+
/** @var string the configured access token */
|
37 |
+
protected $access_token;
|
38 |
+
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Constructor.
|
42 |
+
*
|
43 |
+
* @since 2.0.0
|
44 |
+
*/
|
45 |
+
public function __construct( $access_token ) {
|
46 |
+
|
47 |
+
$this->access_token = $access_token;
|
48 |
+
|
49 |
+
$this->request_headers = [
|
50 |
+
'Authorization' => "Bearer {$access_token}",
|
51 |
+
];
|
52 |
+
|
53 |
+
$this->set_request_content_type_header( 'application/json' );
|
54 |
+
$this->set_request_accept_header( 'application/json' );
|
55 |
+
}
|
56 |
+
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Validates a response after it has been parsed and instantiated.
|
60 |
+
*
|
61 |
+
* Throws an exception if a rate limit or general API error is included in the response.
|
62 |
+
*
|
63 |
+
* @since 2.0.0
|
64 |
+
*
|
65 |
+
* @throws Framework\SV_WC_API_Exception
|
66 |
+
*/
|
67 |
+
protected function do_post_parse_response_validation() {
|
68 |
+
|
69 |
+
/** @var API\Response $response */
|
70 |
+
$response = $this->get_response();
|
71 |
+
|
72 |
+
if ( $response && $response->has_api_error() ) {
|
73 |
+
|
74 |
+
$code = $response->get_api_error_code();
|
75 |
+
$message = sprintf( '%s: %s', $response->get_api_error_type(), $response->get_api_error_message() );
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Graph API
|
79 |
+
*
|
80 |
+
* 4 - API Too Many Calls
|
81 |
+
* 17 - API User Too Many Calls
|
82 |
+
* 32 - Page-level throttling
|
83 |
+
* 613 - Custom-level throttling
|
84 |
+
*
|
85 |
+
* Marketing API (Catalog Batch API)
|
86 |
+
*
|
87 |
+
* 80004 - There have been too many calls to this ad-account
|
88 |
+
*
|
89 |
+
* @link https://developers.facebook.com/docs/graph-api/using-graph-api/error-handling#errorcodes
|
90 |
+
* @link https://developers.facebook.com/docs/graph-api/using-graph-api/error-handling#rate-limiting-error-codes
|
91 |
+
* @link https://developers.facebook.com/docs/marketing-api/reference/product-catalog/batch/#validation-rules
|
92 |
+
*/
|
93 |
+
if ( in_array( $code, [ 4, 17, 32, 613, 80004 ], true ) ) {
|
94 |
+
throw new API\Exceptions\Request_Limit_Reached( $message, $code );
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Handle invalid token errors
|
99 |
+
*
|
100 |
+
* @link https://developers.facebook.com/docs/graph-api/using-graph-api/error-handling#errorcodes
|
101 |
+
*/
|
102 |
+
if ( ( $code >= 200 && $code < 300 ) || in_array( $code, [ 10, 102, 190 ], false ) ) {
|
103 |
+
set_transient( 'wc_facebook_connection_invalid', time(), DAY_IN_SECONDS );
|
104 |
+
} else {
|
105 |
+
// this was an unrelated error, so the OAuth connection may still be valid
|
106 |
+
delete_transient( 'wc_facebook_connection_invalid' );
|
107 |
+
}
|
108 |
+
|
109 |
+
throw new Framework\SV_WC_API_Exception( $message, $code );
|
110 |
+
}
|
111 |
+
|
112 |
+
// if we get this far we're connected, so delete any invalid connection flag
|
113 |
+
delete_transient( 'wc_facebook_connection_invalid' );
|
114 |
+
}
|
115 |
+
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Gets the FBE installation IDs.
|
119 |
+
*
|
120 |
+
* @since 2.0.0
|
121 |
+
*
|
122 |
+
* @param string $external_business_id external business ID
|
123 |
+
* @return API\FBE\Installation\Read\Response
|
124 |
+
* @throws Framework\SV_WC_API_Exception
|
125 |
+
*/
|
126 |
+
public function get_installation_ids( $external_business_id ) {
|
127 |
+
|
128 |
+
$request = new API\FBE\Installation\Read\Request( $external_business_id );
|
129 |
+
|
130 |
+
$this->set_response_handler( API\FBE\Installation\Read\Response::class );
|
131 |
+
|
132 |
+
return $this->perform_request( $request );
|
133 |
+
}
|
134 |
+
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Gets a Page object from Facebook.
|
138 |
+
*
|
139 |
+
* @since 2.0.0
|
140 |
+
*
|
141 |
+
* @param string $page_id page ID
|
142 |
+
* @return API\Pages\Read\Response
|
143 |
+
* @throws Framework\SV_WC_API_Exception
|
144 |
+
*/
|
145 |
+
public function get_page( $page_id ) {
|
146 |
+
|
147 |
+
$request = new API\Pages\Read\Request( $page_id );
|
148 |
+
|
149 |
+
$this->set_response_handler( API\Pages\Read\Response::class );
|
150 |
+
|
151 |
+
return $this->perform_request( $request );
|
152 |
+
}
|
153 |
+
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Gets a business manager object from Facebook.
|
157 |
+
*
|
158 |
+
* @since 2.0.0
|
159 |
+
*
|
160 |
+
* @param string $business_manager_id business manager ID
|
161 |
+
* @return API\Business_Manager\Response
|
162 |
+
* @throws Framework\SV_WC_API_Exception
|
163 |
+
*/
|
164 |
+
public function get_business_manager( $business_manager_id ) {
|
165 |
+
|
166 |
+
$request = new API\Business_Manager\Request( $business_manager_id );
|
167 |
+
|
168 |
+
$this->set_response_handler( API\Business_Manager\Response::class );
|
169 |
+
|
170 |
+
return $this->perform_request( $request );
|
171 |
+
}
|
172 |
+
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Gets a Catalog object from Facebook.
|
176 |
+
*
|
177 |
+
* @since 2.0.0
|
178 |
+
*
|
179 |
+
* @param string $catalog_id catalog ID
|
180 |
+
* @return API\Catalog\Response
|
181 |
+
* @throws Framework\SV_WC_API_Exception
|
182 |
+
*/
|
183 |
+
public function get_catalog( $catalog_id ) {
|
184 |
+
|
185 |
+
$request = new API\Catalog\Request( $catalog_id );
|
186 |
+
|
187 |
+
$this->set_response_handler( API\Catalog\Response::class );
|
188 |
+
|
189 |
+
return $this->perform_request( $request );
|
190 |
+
}
|
191 |
+
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Gets a user object from Facebook.
|
195 |
+
*
|
196 |
+
* @since 2.0.0
|
197 |
+
*
|
198 |
+
* @param string $user_id user ID. Defaults to the currently authenticated user
|
199 |
+
* @return API\User\Response
|
200 |
+
* @throws Framework\SV_WC_API_Exception
|
201 |
+
*/
|
202 |
+
public function get_user( $user_id = '' ) {
|
203 |
+
|
204 |
+
$request = new API\User\Request( $user_id );
|
205 |
+
|
206 |
+
$this->set_response_handler( API\User\Response::class );
|
207 |
+
|
208 |
+
return $this->perform_request( $request );
|
209 |
+
}
|
210 |
+
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Delete's a user's API permission.
|
214 |
+
*
|
215 |
+
* This is their form of "revoke".
|
216 |
+
*
|
217 |
+
* @since 2.0.0
|
218 |
+
*
|
219 |
+
* @param string $user_id user ID. Defaults to the currently authenticated user
|
220 |
+
* @param string $permission permission to delete
|
221 |
+
* @return API\User\Response
|
222 |
+
* @throws Framework\SV_WC_API_Exception
|
223 |
+
*/
|
224 |
+
public function delete_user_permission( $user_id, $permission ) {
|
225 |
+
|
226 |
+
$request = new API\User\Permissions\Delete\Request( $user_id, $permission );
|
227 |
+
|
228 |
+
$this->set_response_handler( API\User\Response::class );
|
229 |
+
|
230 |
+
return $this->perform_request( $request );
|
231 |
+
}
|
232 |
+
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Gets the business configuration.
|
236 |
+
*
|
237 |
+
* @since 2.0.0
|
238 |
+
*
|
239 |
+
* @param string $external_business_id external business ID
|
240 |
+
* @return API\FBE\Configuration\Read\Response
|
241 |
+
* @throws Framework\SV_WC_API_Exception
|
242 |
+
*/
|
243 |
+
public function get_business_configuration( $external_business_id ) {
|
244 |
+
|
245 |
+
$request = new API\FBE\Configuration\Request( $external_business_id, 'GET' );
|
246 |
+
|
247 |
+
$this->set_response_handler( API\FBE\Configuration\Read\Response::class );
|
248 |
+
|
249 |
+
return $this->perform_request( $request );
|
250 |
+
}
|
251 |
+
|
252 |
+
|
253 |
+
/**
|
254 |
+
* Updates the messenger configuration.
|
255 |
+
*
|
256 |
+
* @since 2.0.0
|
257 |
+
*
|
258 |
+
* @param string $external_business_id external business ID
|
259 |
+
* @param API\FBE\Configuration\Messenger $configuration messenger configuration
|
260 |
+
* @return Response
|
261 |
+
* @throws Framework\SV_WC_API_Exception
|
262 |
+
*/
|
263 |
+
public function update_messenger_configuration( $external_business_id, API\FBE\Configuration\Messenger $configuration ) {
|
264 |
+
|
265 |
+
$request = new API\FBE\Configuration\Update\Request( $external_business_id );
|
266 |
+
|
267 |
+
$request->set_messenger_configuration( $configuration );
|
268 |
+
|
269 |
+
$this->set_response_handler( API\Response::class );
|
270 |
+
|
271 |
+
return $this->perform_request( $request );
|
272 |
+
}
|
273 |
+
|
274 |
+
|
275 |
+
/**
|
276 |
+
* Uses the Catalog Batch API to update or remove items from catalog.
|
277 |
+
*
|
278 |
+
* @see Sync::create_or_update_products()
|
279 |
+
*
|
280 |
+
* @since 2.0.0
|
281 |
+
*
|
282 |
+
* @param string $catalog_id catalog ID
|
283 |
+
* @param array $requests array of prefixed product IDs to create, update or remove
|
284 |
+
* @param bool $allow_upsert whether to allow updates to insert new items
|
285 |
+
* @return \SkyVerge\WooCommerce\Facebook\API\Catalog\Send_Item_Updates\Response
|
286 |
+
* @throws Framework\SV_WC_API_Exception
|
287 |
+
*/
|
288 |
+
public function send_item_updates( $catalog_id, $requests, $allow_upsert ) {
|
289 |
+
|
290 |
+
$request = new \SkyVerge\WooCommerce\Facebook\API\Catalog\Send_Item_Updates\Request( $catalog_id );
|
291 |
+
|
292 |
+
$request->set_requests( $requests );
|
293 |
+
$request->set_allow_upsert( $allow_upsert );
|
294 |
+
|
295 |
+
$this->set_response_handler( \SkyVerge\WooCommerce\Facebook\API\Catalog\Send_Item_Updates\Response::class );
|
296 |
+
|
297 |
+
return $this->perform_request( $request );
|
298 |
+
}
|
299 |
+
|
300 |
+
|
301 |
+
/**
|
302 |
+
* Creates a Product Group object.
|
303 |
+
*
|
304 |
+
* @since 2.0.0
|
305 |
+
*
|
306 |
+
* @param string $catalog_id catalog ID
|
307 |
+
* @param array $data product group data
|
308 |
+
* @return Response
|
309 |
+
* @throws Framework\SV_WC_API_Exception
|
310 |
+
*/
|
311 |
+
public function create_product_group( $catalog_id, $data ) {
|
312 |
+
|
313 |
+
$request = $this->get_new_request( [
|
314 |
+
'path' => "/{$catalog_id}/product_groups",
|
315 |
+
'method' => 'POST',
|
316 |
+
] );
|
317 |
+
|
318 |
+
$request->set_data( $data );
|
319 |
+
|
320 |
+
$this->set_response_handler( Response::class );
|
321 |
+
|
322 |
+
return $this->perform_request( $request );
|
323 |
+
}
|
324 |
+
|
325 |
+
|
326 |
+
/**
|
327 |
+
* Updates the default product item and the available variation attributes of a product group.
|
328 |
+
*
|
329 |
+
* @since 2.0.0
|
330 |
+
*
|
331 |
+
* @param string $product_group_id product group ID
|
332 |
+
* @param array $data product group data
|
333 |
+
* @return Response
|
334 |
+
* @throws Framework\SV_WC_API_Exception
|
335 |
+
*/
|
336 |
+
public function update_product_group( $product_group_id, $data ) {
|
337 |
+
|
338 |
+
$request = $this->get_new_request( [
|
339 |
+
'path' => "/{$product_group_id}",
|
340 |
+
'method' => 'POST',
|
341 |
+
] );
|
342 |
+
|
343 |
+
$request->set_data( $data );
|
344 |
+
|
345 |
+
$this->set_response_handler( Response::class );
|
346 |
+
|
347 |
+
return $this->perform_request( $request );
|
348 |
+
}
|
349 |
+
|
350 |
+
|
351 |
+
/**
|
352 |
+
* Deletes a Product Group object.
|
353 |
+
*
|
354 |
+
* @since 2.0.0
|
355 |
+
*
|
356 |
+
* @param string $product_group_id
|
357 |
+
* @return Response
|
358 |
+
* @throws Framework\SV_WC_API_Exception
|
359 |
+
*/
|
360 |
+
public function delete_product_group( $product_group_id ) {
|
361 |
+
|
362 |
+
$request = $this->get_new_request( [
|
363 |
+
'path' => "/{$product_group_id}",
|
364 |
+
'method' => 'DELETE',
|
365 |
+
] );
|
366 |
+
|
367 |
+
$this->set_response_handler( Response::class );
|
368 |
+
|
369 |
+
return $this->perform_request( $request );
|
370 |
+
}
|
371 |
+
|
372 |
+
|
373 |
+
/**
|
374 |
+
* Gets a list of Product Items in the given Product Group.
|
375 |
+
*
|
376 |
+
* @since 2.0.0
|
377 |
+
*
|
378 |
+
* @param string $product_group_id product group ID
|
379 |
+
* @param int $limit max number of results returned per page of data
|
380 |
+
* @return API\Catalog\Product_Group\Products\Read\Response
|
381 |
+
* @throws Framework\SV_WC_API_Exception
|
382 |
+
*/
|
383 |
+
public function get_product_group_products( $product_group_id, $limit = 1000 ) {
|
384 |
+
|
385 |
+
$request = new API\Catalog\Product_Group\Products\Read\Request( $product_group_id, $limit );
|
386 |
+
|
387 |
+
$this->set_response_handler( API\Catalog\Product_Group\Products\Read\Response::class );
|
388 |
+
|
389 |
+
return $this->perform_request( $request );
|
390 |
+
}
|
391 |
+
|
392 |
+
|
393 |
+
/**
|
394 |
+
* Finds a Product Item using the Catalog ID and the Retailer ID of the product or product variation.
|
395 |
+
*
|
396 |
+
* @since 2.0.0
|
397 |
+
*
|
398 |
+
* @param string $catalog_id catalog ID
|
399 |
+
* @param string $retailer_id retailer ID of the product
|
400 |
+
* @return Response
|
401 |
+
* @throws Framework\SV_WC_API_Exception
|
402 |
+
*/
|
403 |
+
public function find_product_item( $catalog_id, $retailer_id ) {
|
404 |
+
|
405 |
+
$request = new \SkyVerge\WooCommerce\Facebook\API\Catalog\Product_Item\Find\Request( $catalog_id, $retailer_id );
|
406 |
+
|
407 |
+
$this->set_response_handler( \SkyVerge\WooCommerce\Facebook\API\Catalog\Product_Item\Response::class );
|
408 |
+
|
409 |
+
return $this->perform_request( $request );
|
410 |
+
}
|
411 |
+
|
412 |
+
|
413 |
+
/**
|
414 |
+
* Creates a Product Item object.
|
415 |
+
*
|
416 |
+
* @since 2.0.0
|
417 |
+
*
|
418 |
+
* @param string $product_group_id parent product ID
|
419 |
+
* @param array $data product data
|
420 |
+
* @return Response
|
421 |
+
* @throws Framework\SV_WC_API_Exception
|
422 |
+
*/
|
423 |
+
public function create_product_item( $product_group_id, $data ) {
|
424 |
+
|
425 |
+
$request = $this->get_new_request( [
|
426 |
+
'path' => "/{$product_group_id}/products",
|
427 |
+
'method' => 'POST',
|
428 |
+
] );
|
429 |
+
|
430 |
+
$request->set_data( $data );
|
431 |
+
|
432 |
+
$this->set_response_handler( Response::class );
|
433 |
+
|
434 |
+
return $this->perform_request( $request );
|
435 |
+
}
|
436 |
+
|
437 |
+
|
438 |
+
/**
|
439 |
+
* Updates a Product Item object.
|
440 |
+
*
|
441 |
+
* @since 2.0.0
|
442 |
+
*
|
443 |
+
* @param string $product_item_id product item ID
|
444 |
+
* @param array $data product data
|
445 |
+
* @return Response
|
446 |
+
* @throws Framework\SV_WC_API_Exception
|
447 |
+
*/
|
448 |
+
public function update_product_item( $product_item_id, $data ) {
|
449 |
+
|
450 |
+
$request = $this->get_new_request( [
|
451 |
+
'path' => "/{$product_item_id}",
|
452 |
+
'method' => 'POST',
|
453 |
+
] );
|
454 |
+
|
455 |
+
$request->set_data( $data );
|
456 |
+
|
457 |
+
$this->set_response_handler( Response::class );
|
458 |
+
|
459 |
+
return $this->perform_request( $request );
|
460 |
+
}
|
461 |
+
|
462 |
+
|
463 |
+
/**
|
464 |
+
* Deletes a Product Item object.
|
465 |
+
*
|
466 |
+
* @since 2.0.0
|
467 |
+
*
|
468 |
+
* @param string $product_item_id product item ID
|
469 |
+
* @return Response
|
470 |
+
* @throws Framework\SV_WC_API_Exception
|
471 |
+
*/
|
472 |
+
public function delete_product_item( $product_item_id ) {
|
473 |
+
|
474 |
+
$request = $this->get_new_request( [
|
475 |
+
'path' => "/{$product_item_id}",
|
476 |
+
'method' => 'DELETE',
|
477 |
+
] );
|
478 |
+
|
479 |
+
$this->set_response_handler( Response::class );
|
480 |
+
|
481 |
+
return $this->perform_request( $request );
|
482 |
+
}
|
483 |
+
|
484 |
+
|
485 |
+
/**
|
486 |
+
* Sends Pixel events.
|
487 |
+
*
|
488 |
+
* @since 2.0.0
|
489 |
+
*
|
490 |
+
* @param string $pixel_id pixel ID
|
491 |
+
* @param Event[] $events events to send
|
492 |
+
* @return Response
|
493 |
+
* @throws Framework\SV_WC_API_Exception
|
494 |
+
*/
|
495 |
+
public function send_pixel_events( $pixel_id, array $events ) {
|
496 |
+
|
497 |
+
$request = new API\Pixel\Events\Request( $pixel_id, $events );
|
498 |
+
|
499 |
+
$this->set_response_handler( Response::class );
|
500 |
+
|
501 |
+
return $this->perform_request( $request );
|
502 |
+
}
|
503 |
+
|
504 |
+
|
505 |
+
/**
|
506 |
+
* Gets the next page of results for a paginated response.
|
507 |
+
*
|
508 |
+
* @since 2.0.0
|
509 |
+
*
|
510 |
+
* @param API\Response $response previous response object
|
511 |
+
* @param int $additional_pages number of additional pages of results to retrieve
|
512 |
+
* @return API\Response|null
|
513 |
+
* @throws Framework\SV_WC_API_Exception
|
514 |
+
*/
|
515 |
+
public function next( API\Response $response, $additional_pages = null ) {
|
516 |
+
|
517 |
+
$next_response = null;
|
518 |
+
|
519 |
+
// get the next page if we haven't reached the limit of pages to retrieve and the endpoint for the next page is available
|
520 |
+
if ( ( null === $additional_pages || $response->get_pages_retrieved() <= $additional_pages ) && $response->get_next_page_endpoint() ) {
|
521 |
+
|
522 |
+
$components = parse_url( str_replace( $this->request_uri, '', $response->get_next_page_endpoint() ) );
|
523 |
+
|
524 |
+
$request = $this->get_new_request( [
|
525 |
+
'path' => isset( $components['path'] ) ? $components['path'] : '',
|
526 |
+
'method' => 'GET',
|
527 |
+
'params' => isset( $components['query'] ) ? wp_parse_args( $components['query'] ) : [],
|
528 |
+
] );
|
529 |
+
|
530 |
+
$this->set_response_handler( get_class( $response ) );
|
531 |
+
|
532 |
+
$next_response = $this->perform_request( $request );
|
533 |
+
|
534 |
+
// this is the n + 1 page of results for the original response
|
535 |
+
$next_response->set_pages_retrieved( $response->get_pages_retrieved() + 1 );
|
536 |
+
}
|
537 |
+
|
538 |
+
return $next_response;
|
539 |
+
}
|
540 |
+
|
541 |
+
|
542 |
+
/**
|
543 |
+
* Returns a new request object.
|
544 |
+
*
|
545 |
+
* @since 2.0.0
|
546 |
+
*
|
547 |
+
* @param array $args {
|
548 |
+
* Optional. An array of request arguments.
|
549 |
+
*
|
550 |
+
* @type string $path request path
|
551 |
+
* @type string $method request method
|
552 |
+
* @type array $params request parameters
|
553 |
+
* }
|
554 |
+
* @return Request
|
555 |
+
*/
|
556 |
+
protected function get_new_request( $args = [] ) {
|
557 |
+
|
558 |
+
$defaults = [
|
559 |
+
'path' => '/',
|
560 |
+
'method' => 'GET',
|
561 |
+
'params' => [],
|
562 |
+
];
|
563 |
+
|
564 |
+
$args = wp_parse_args( $args, $defaults );
|
565 |
+
$request = new Request( $args['path'], $args['method'] );
|
566 |
+
|
567 |
+
if ( $args['params'] ) {
|
568 |
+
$request->set_params( $args['params'] );
|
569 |
+
}
|
570 |
+
|
571 |
+
return $request;
|
572 |
+
}
|
573 |
+
|
574 |
+
|
575 |
+
/**
|
576 |
+
* Returns the plugin class instance associated with this API.
|
577 |
+
*
|
578 |
+
* @since 2.0.0
|
579 |
+
*
|
580 |
+
* @return \WC_Facebookcommerce
|
581 |
+
*/
|
582 |
+
protected function get_plugin() {
|
583 |
+
|
584 |
+
return facebook_for_woocommerce();
|
585 |
+
}
|
586 |
+
|
587 |
+
|
588 |
+
}
|
includes/API/Business_Manager/Request.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Business_Manager;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Request object for the Business Manager API.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Request extends API\Request {
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* API request constructor.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*
|
30 |
+
* @param string $business_manager_id business manager ID
|
31 |
+
*/
|
32 |
+
public function __construct( $business_manager_id ) {
|
33 |
+
|
34 |
+
parent::__construct( "/{$business_manager_id}", 'GET' );
|
35 |
+
}
|
36 |
+
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Gets the request parameters.
|
40 |
+
*
|
41 |
+
* @since 2.0.0
|
42 |
+
*
|
43 |
+
* @return array
|
44 |
+
*/
|
45 |
+
public function get_params() {
|
46 |
+
|
47 |
+
return [ 'fields' => 'name,link' ];
|
48 |
+
}
|
49 |
+
|
50 |
+
|
51 |
+
}
|
includes/API/Business_Manager/Response.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Business_Manager;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Business Manager API response object
|
17 |
+
*
|
18 |
+
* @since 2.0.0
|
19 |
+
*/
|
20 |
+
class Response extends \SkyVerge\WooCommerce\Facebook\API\Response {
|
21 |
+
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Gets the business manager name.
|
25 |
+
*
|
26 |
+
* @since 2.0.0
|
27 |
+
*
|
28 |
+
* @return string|null
|
29 |
+
*/
|
30 |
+
public function get_name() {
|
31 |
+
|
32 |
+
return $this->name;
|
33 |
+
}
|
34 |
+
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Gets the business manager name.
|
38 |
+
*
|
39 |
+
* @since 2.0.0
|
40 |
+
*
|
41 |
+
* @return string|null
|
42 |
+
*/
|
43 |
+
public function get_url() {
|
44 |
+
|
45 |
+
return $this->link;
|
46 |
+
}
|
47 |
+
|
48 |
+
|
49 |
+
}
|
includes/API/Catalog/Product_Group/Products/Read/Request.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Catalog\Product_Group\Products\Read;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Request object for the API endpoint that returns a list of Product Items in a particular Product Group.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Request extends API\Request {
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Constructor for the Product Group Products read request.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*
|
30 |
+
* @param string $product_group_id product group ID
|
31 |
+
* @param int $limit max number of results returned
|
32 |
+
*/
|
33 |
+
public function __construct( $product_group_id, $limit ) {
|
34 |
+
|
35 |
+
parent::__construct( "/{$product_group_id}/products", 'GET' );
|
36 |
+
|
37 |
+
$this->set_params( [
|
38 |
+
'fields' => 'id,retailer_id',
|
39 |
+
'limit' => $limit,
|
40 |
+
] );
|
41 |
+
}
|
42 |
+
|
43 |
+
|
44 |
+
}
|
includes/API/Catalog/Product_Group/Products/Read/Response.php
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Catalog\Product_Group\Products\Read;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Response object for the API endpoint that returns a list of Product Items in a particular Product Group.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Response extends API\Response {
|
23 |
+
|
24 |
+
|
25 |
+
use API\Traits\Paginated_Response;
|
26 |
+
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Gets the Product Item IDs indexed by the retailer ID.
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*
|
33 |
+
* @return array
|
34 |
+
*/
|
35 |
+
public function get_ids() {
|
36 |
+
|
37 |
+
$product_item_ids = [];
|
38 |
+
|
39 |
+
foreach ( $this->get_data() as $entry ) {
|
40 |
+
$product_item_ids[ $entry->retailer_id ] = $entry->id;
|
41 |
+
}
|
42 |
+
|
43 |
+
return $product_item_ids;
|
44 |
+
}
|
45 |
+
|
46 |
+
|
47 |
+
}
|
includes/API/Catalog/Product_Item/Find/Request.php
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Catalog\Product_Item\Find;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Find Product Item API request object.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Request extends API\Request {
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Gets the ID of this request for rate limiting purposes.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*
|
30 |
+
* @return string
|
31 |
+
*/
|
32 |
+
public static function get_rate_limit_id() {
|
33 |
+
|
34 |
+
return 'wc_facebook_ads_management_api_request';
|
35 |
+
}
|
36 |
+
|
37 |
+
|
38 |
+
/**
|
39 |
+
* API request constructor.
|
40 |
+
*
|
41 |
+
* @since 2.0.0
|
42 |
+
*
|
43 |
+
* @param string $catalog_id catalog ID
|
44 |
+
* @param string $retailer_id retailer ID of the product
|
45 |
+
*/
|
46 |
+
public function __construct( $catalog_id, $retailer_id ) {
|
47 |
+
|
48 |
+
parent::__construct( "catalog:{$catalog_id}:" . base64_encode( $retailer_id ), 'GET' );
|
49 |
+
}
|
50 |
+
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Gets the request parameters.
|
54 |
+
*
|
55 |
+
* @since 2.0.0
|
56 |
+
*
|
57 |
+
* @return array
|
58 |
+
*/
|
59 |
+
public function get_params() {
|
60 |
+
|
61 |
+
return [ 'fields' => 'id,product_group{id}' ];
|
62 |
+
}
|
63 |
+
|
64 |
+
|
65 |
+
}
|
includes/API/Catalog/Product_Item/Response.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Catalog\Product_Item;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Response object for API requests that return a Product Item.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Response extends API\Response {
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Gets the Product Item group ID.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*
|
30 |
+
* @return string
|
31 |
+
*/
|
32 |
+
public function get_group_id() {
|
33 |
+
|
34 |
+
$product_group_id = '';
|
35 |
+
|
36 |
+
if ( isset( $this->response_data->product_group->id ) ) {
|
37 |
+
$product_group_id = $this->response_data->product_group->id;
|
38 |
+
}
|
39 |
+
|
40 |
+
return $product_group_id;
|
41 |
+
}
|
42 |
+
|
43 |
+
|
44 |
+
}
|
includes/API/Catalog/Request.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Catalog;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Request object for the Catalog API.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Request extends API\Request {
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* API request constructor.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*
|
30 |
+
* @param string $catalog_id catalog ID
|
31 |
+
*/
|
32 |
+
public function __construct( $catalog_id ) {
|
33 |
+
|
34 |
+
parent::__construct( "/{$catalog_id}", 'GET' );
|
35 |
+
}
|
36 |
+
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Gets the request parameters.
|
40 |
+
*
|
41 |
+
* @since 2.0.0
|
42 |
+
*
|
43 |
+
* @return array
|
44 |
+
*/
|
45 |
+
public function get_params() {
|
46 |
+
|
47 |
+
return [ 'fields' => 'name' ];
|
48 |
+
}
|
49 |
+
|
50 |
+
|
51 |
+
}
|
includes/API/Catalog/Response.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Catalog;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Catalog API response object
|
17 |
+
*
|
18 |
+
* @since 2.0.0
|
19 |
+
*/
|
20 |
+
class Response extends \SkyVerge\WooCommerce\Facebook\API\Response {
|
21 |
+
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Gets the catalog name.
|
25 |
+
*
|
26 |
+
* @since 2.0.0
|
27 |
+
*
|
28 |
+
* @return string|null
|
29 |
+
*/
|
30 |
+
public function get_name() {
|
31 |
+
|
32 |
+
return $this->name;
|
33 |
+
}
|
34 |
+
|
35 |
+
|
36 |
+
}
|
includes/API/Catalog/Send_Item_Updates/Request.php
ADDED
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Catalog\Send_Item_Updates;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Request object for the Send Item Updates API request.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Request extends API\Request {
|
23 |
+
|
24 |
+
|
25 |
+
/** @var array an array of item update requests */
|
26 |
+
protected $requests = [];
|
27 |
+
|
28 |
+
/** @var bool determines whether updates for products that are not currently in the catalog should create new items */
|
29 |
+
protected $allow_upsert = true;
|
30 |
+
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Gets the ID of this request for rate limiting purposes.
|
34 |
+
*
|
35 |
+
* @since 2.0.0
|
36 |
+
*
|
37 |
+
* @return string
|
38 |
+
*/
|
39 |
+
public static function get_rate_limit_id() {
|
40 |
+
|
41 |
+
return 'ads_management_api_request';
|
42 |
+
}
|
43 |
+
|
44 |
+
|
45 |
+
/**
|
46 |
+
* API request constructor.
|
47 |
+
*
|
48 |
+
* @since 2.0.0
|
49 |
+
*
|
50 |
+
* @param string $catalog_id catalog ID
|
51 |
+
*/
|
52 |
+
public function __construct( $catalog_id ) {
|
53 |
+
|
54 |
+
parent::__construct( "/{$catalog_id}/batch", 'POST' );
|
55 |
+
}
|
56 |
+
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Sets the array of item update requests.
|
60 |
+
*
|
61 |
+
* @since 2.0.0
|
62 |
+
*
|
63 |
+
* @param array $requests item update requests
|
64 |
+
*/
|
65 |
+
public function set_requests( array $requests ) {
|
66 |
+
|
67 |
+
$this->requests = $requests;
|
68 |
+
}
|
69 |
+
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Gets the array of item update requests.
|
73 |
+
*
|
74 |
+
* @since 2.0.0
|
75 |
+
*
|
76 |
+
* @return array
|
77 |
+
*/
|
78 |
+
public function get_requests() {
|
79 |
+
|
80 |
+
return $this->requests;
|
81 |
+
}
|
82 |
+
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Sets whether updates for products that are not currently in the catalog should create new items.
|
86 |
+
*
|
87 |
+
* @since 2.0.0
|
88 |
+
*
|
89 |
+
* @param bool $allow_upsert whether to allow updates to insert new items
|
90 |
+
*/
|
91 |
+
public function set_allow_upsert( $allow_upsert ) {
|
92 |
+
|
93 |
+
$this->allow_upsert = (bool) $allow_upsert;
|
94 |
+
}
|
95 |
+
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Gets whether updates for products that are not currently in the catalog should create new items.
|
99 |
+
*
|
100 |
+
* @since 2.0.0
|
101 |
+
*
|
102 |
+
* @return bool
|
103 |
+
*/
|
104 |
+
public function get_allow_upsert() {
|
105 |
+
|
106 |
+
return $this->allow_upsert;
|
107 |
+
}
|
108 |
+
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Gets the request data.
|
112 |
+
*
|
113 |
+
* @since 2.0.0
|
114 |
+
*/
|
115 |
+
public function get_data() {
|
116 |
+
|
117 |
+
return [
|
118 |
+
'allow_upsert' => $this->get_allow_upsert(),
|
119 |
+
'requests' => $this->get_requests(),
|
120 |
+
];
|
121 |
+
}
|
122 |
+
|
123 |
+
|
124 |
+
}
|
includes/API/Catalog/Send_Item_Updates/Response.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Catalog\Send_Item_Updates;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Send_Item_Updates API response object
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Response extends \SkyVerge\WooCommerce\Facebook\API\Response {
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Gets the handles field from the response.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*
|
30 |
+
* @return array|null
|
31 |
+
*/
|
32 |
+
public function get_handles() {
|
33 |
+
|
34 |
+
return $this->handles;
|
35 |
+
}
|
36 |
+
|
37 |
+
|
38 |
+
}
|
includes/API/Exceptions/Request_Limit_Reached.php
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Exceptions;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Exception thrown in response to a rate limiting error.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Request_Limit_Reached extends Framework\SV_WC_API_Exception {
|
23 |
+
|
24 |
+
|
25 |
+
}
|
includes/API/FBE/Configuration/Messenger.php
ADDED
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\FBE\Configuration;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* The messenger configuration object.
|
17 |
+
*
|
18 |
+
* @since 2.0.0
|
19 |
+
*/
|
20 |
+
class Messenger {
|
21 |
+
|
22 |
+
|
23 |
+
/** @var bool whether messenger is enabled */
|
24 |
+
private $enabled;
|
25 |
+
|
26 |
+
/** @var string default locale */
|
27 |
+
private $default_locale;
|
28 |
+
|
29 |
+
/** @var string[] approved domains */
|
30 |
+
private $domains = [];
|
31 |
+
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Messenger constructor.
|
35 |
+
*
|
36 |
+
* @param array $data configuration data
|
37 |
+
*/
|
38 |
+
public function __construct( array $data = [] ) {
|
39 |
+
|
40 |
+
$data = wp_parse_args( $data, [
|
41 |
+
'enabled' => false,
|
42 |
+
'default_locale' => '',
|
43 |
+
'domains' => [],
|
44 |
+
] );
|
45 |
+
|
46 |
+
$this->set_enabled( $data['enabled'] );
|
47 |
+
$this->set_default_locale( $data['default_locale'] );
|
48 |
+
$this->set_domains( $data['domains'] );
|
49 |
+
}
|
50 |
+
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Determines if messenger is enabled.
|
54 |
+
*
|
55 |
+
* @since 2.0.0
|
56 |
+
*
|
57 |
+
* @return bool
|
58 |
+
*/
|
59 |
+
public function is_enabled() {
|
60 |
+
|
61 |
+
return $this->enabled;
|
62 |
+
}
|
63 |
+
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Gets the default locale.
|
67 |
+
*
|
68 |
+
* @since 2.0.0
|
69 |
+
*
|
70 |
+
* @return string
|
71 |
+
*/
|
72 |
+
public function get_default_locale() {
|
73 |
+
|
74 |
+
return $this->default_locale;
|
75 |
+
}
|
76 |
+
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Gets the domains that messenger is configured for.
|
80 |
+
*
|
81 |
+
* @since 2.0.0
|
82 |
+
*
|
83 |
+
* @return string[]
|
84 |
+
*/
|
85 |
+
public function get_domains() {
|
86 |
+
|
87 |
+
if ( is_array( $this->domains ) ) {
|
88 |
+
$domains = array_map( 'trailingslashit', $this->domains );
|
89 |
+
} else {
|
90 |
+
$domains = [];
|
91 |
+
}
|
92 |
+
|
93 |
+
return $domains;
|
94 |
+
}
|
95 |
+
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Sets whether messenger is enabled.
|
99 |
+
*
|
100 |
+
* @since 2.0.0
|
101 |
+
*
|
102 |
+
* @param bool $is_enabled whether messenger is enabled
|
103 |
+
*/
|
104 |
+
public function set_enabled( $is_enabled ) {
|
105 |
+
|
106 |
+
$this->enabled = (bool) $is_enabled;
|
107 |
+
}
|
108 |
+
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Sets the default locale.
|
112 |
+
*
|
113 |
+
* @since 2.0.0
|
114 |
+
*
|
115 |
+
* @param string $locale default locale
|
116 |
+
*/
|
117 |
+
public function set_default_locale( $locale ) {
|
118 |
+
|
119 |
+
$this->default_locale = (string) $locale;
|
120 |
+
}
|
121 |
+
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Adds a domain to the list of approved domains.
|
125 |
+
*
|
126 |
+
* @since 2.0.0
|
127 |
+
*
|
128 |
+
* @param string $domain domain to add
|
129 |
+
*/
|
130 |
+
public function add_domain( $domain ) {
|
131 |
+
|
132 |
+
$domains = is_array( $this->domains ) ? $this->domains : [];
|
133 |
+
|
134 |
+
$domains[] = $domain;
|
135 |
+
|
136 |
+
$this->set_domains( $domains );
|
137 |
+
}
|
138 |
+
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Sets the list of approved domains.
|
142 |
+
*
|
143 |
+
* @since 2.0.0
|
144 |
+
*
|
145 |
+
* @param string[] $domains list of domains
|
146 |
+
*/
|
147 |
+
public function set_domains( array $domains ) {
|
148 |
+
|
149 |
+
$this->domains = array_unique( array_filter( $domains, 'wc_is_valid_url' ) );
|
150 |
+
}
|
151 |
+
|
152 |
+
|
153 |
+
}
|
includes/API/FBE/Configuration/Read/Response.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\FBE\Configuration\Read;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* FBE Configuration API read response object.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Response extends API\Response {
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Gets the messenger configuration object.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*
|
30 |
+
* @return null|API\FBE\Configuration\Messenger
|
31 |
+
*/
|
32 |
+
public function get_messenger_configuration() {
|
33 |
+
|
34 |
+
$configuration = null;
|
35 |
+
|
36 |
+
if ( ! empty( $this->response_data->messenger_chat ) && is_object( $this->response_data->messenger_chat ) ) {
|
37 |
+
$configuration = new API\FBE\Configuration\Messenger( (array) $this->response_data->messenger_chat );
|
38 |
+
}
|
39 |
+
|
40 |
+
return $configuration;
|
41 |
+
}
|
42 |
+
|
43 |
+
|
44 |
+
}
|
includes/API/FBE/Configuration/Request.php
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\FBE\Configuration;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* FBE Configuration API request object.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Request extends API\Request {
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* API request constructor.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*
|
30 |
+
* @param string $external_business_id external business ID
|
31 |
+
* @param string $method request method
|
32 |
+
*/
|
33 |
+
public function __construct( $external_business_id, $method ) {
|
34 |
+
|
35 |
+
parent::__construct( '/fbe_business', $method );
|
36 |
+
|
37 |
+
$this->params = [
|
38 |
+
'fbe_external_business_id' => $external_business_id,
|
39 |
+
];
|
40 |
+
}
|
41 |
+
|
42 |
+
|
43 |
+
}
|
includes/API/FBE/Configuration/Update/Request.php
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\FBE\Configuration\Update;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API\FBE\Configuration;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* FBE Configuration update request object.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Request extends Configuration\Request {
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* API request constructor.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*
|
30 |
+
* @param string $external_business_id external business ID
|
31 |
+
*/
|
32 |
+
public function __construct( $external_business_id ) {
|
33 |
+
|
34 |
+
parent::__construct( $external_business_id, 'POST' );
|
35 |
+
|
36 |
+
// include the business ID in the request body
|
37 |
+
$this->data['fbe_external_business_id'] = $external_business_id;
|
38 |
+
}
|
39 |
+
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Sets the messenger configuration.
|
43 |
+
*
|
44 |
+
* Only the enabled and domains values are able to accept updates right now.
|
45 |
+
*
|
46 |
+
* @since 2.0.0
|
47 |
+
*
|
48 |
+
* @param Configuration\Messenger $configuration messenger configuration object
|
49 |
+
*/
|
50 |
+
public function set_messenger_configuration( Configuration\Messenger $configuration ) {
|
51 |
+
|
52 |
+
$this->data['messenger_chat'] = [
|
53 |
+
'enabled' => $configuration->is_enabled(),
|
54 |
+
'domains' => $configuration->get_domains(),
|
55 |
+
];
|
56 |
+
}
|
57 |
+
|
58 |
+
|
59 |
+
}
|
includes/API/FBE/Installation/Read/Request.php
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\FBE\Installation\Read;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API\FBE\Installation;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* FBE installation API read request object.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Request extends Installation\Request {
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* API request constructor.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*
|
30 |
+
* @param string $external_business_id external business_id
|
31 |
+
*/
|
32 |
+
public function __construct( $external_business_id ) {
|
33 |
+
|
34 |
+
parent::__construct( 'fbe_installs', 'GET' );
|
35 |
+
|
36 |
+
$this->params = [
|
37 |
+
'fbe_external_business_id' => $external_business_id,
|
38 |
+
];
|
39 |
+
}
|
40 |
+
|
41 |
+
|
42 |
+
}
|
includes/API/FBE/Installation/Read/Response.php
ADDED
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\FBE\Installation\Read;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* FBE Installation API read response object.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Response extends API\Response {
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Gets the pixel ID.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*
|
30 |
+
* @return string
|
31 |
+
*/
|
32 |
+
public function get_pixel_id() {
|
33 |
+
|
34 |
+
return ! empty( $this->get_data()->pixel_id ) ? $this->get_data()->pixel_id : '';
|
35 |
+
}
|
36 |
+
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Gets the business manager ID.
|
40 |
+
*
|
41 |
+
* @since 2.0.0
|
42 |
+
*
|
43 |
+
* @return string
|
44 |
+
*/
|
45 |
+
public function get_business_manager_id() {
|
46 |
+
|
47 |
+
return ! empty( $this->get_data()->business_manager_id ) ? $this->get_data()->business_manager_id : '';
|
48 |
+
}
|
49 |
+
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Gets the ad account ID.
|
53 |
+
*
|
54 |
+
* @since 2.0.0
|
55 |
+
*
|
56 |
+
* @return string
|
57 |
+
*/
|
58 |
+
public function get_ad_account_id() {
|
59 |
+
|
60 |
+
return ! empty( $this->get_data()->ad_account_id ) ? $this->get_data()->ad_account_id : '';
|
61 |
+
}
|
62 |
+
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Gets the catalog ID.
|
66 |
+
*
|
67 |
+
* @since 2.0.0
|
68 |
+
*
|
69 |
+
* @return string
|
70 |
+
*/
|
71 |
+
public function get_catalog_id() {
|
72 |
+
|
73 |
+
return ! empty( $this->get_data()->catalog_id ) ? $this->get_data()->catalog_id : '';
|
74 |
+
}
|
75 |
+
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Gets the page ID.
|
79 |
+
*
|
80 |
+
* @since 2.0.0
|
81 |
+
*
|
82 |
+
* @return string
|
83 |
+
*/
|
84 |
+
public function get_page_id() {
|
85 |
+
|
86 |
+
$pages = $this->get_data()->pages;
|
87 |
+
|
88 |
+
return ! empty( $pages ) && is_array( $pages ) ? current( $pages ) : '';
|
89 |
+
}
|
90 |
+
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Gets the profiles.
|
94 |
+
*
|
95 |
+
* @since 2.0.0
|
96 |
+
*
|
97 |
+
* @return string[]
|
98 |
+
*/
|
99 |
+
public function get_profiles() {
|
100 |
+
|
101 |
+
return ! empty( $this->get_data()->profiles ) ? $this->get_data()->profiles : [];
|
102 |
+
}
|
103 |
+
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Gets the response data.
|
107 |
+
*
|
108 |
+
* @since 2.0.0
|
109 |
+
*
|
110 |
+
* @return \stdClass
|
111 |
+
*/
|
112 |
+
public function get_data() {
|
113 |
+
|
114 |
+
$data = ! empty( $this->response_data->data ) && is_array( $this->response_data->data ) ? $this->response_data->data : [];
|
115 |
+
|
116 |
+
return is_object( $data[0] ) ? $data[0] : new \stdClass();
|
117 |
+
}
|
118 |
+
|
119 |
+
|
120 |
+
}
|
includes/API/FBE/Installation/Request.php
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\FBE\Installation;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* FBE API request object.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Request extends API\Request {
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* API request constructor.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*
|
30 |
+
* @param string $path desired path
|
31 |
+
* @param string $method request method
|
32 |
+
*/
|
33 |
+
public function __construct( $path, $method ) {
|
34 |
+
|
35 |
+
parent::__construct( "/fbe_business/{$path}", $method );
|
36 |
+
}
|
37 |
+
|
38 |
+
|
39 |
+
}
|
includes/API/Pages/Read/Request.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Pages\Read;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Page API request object.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Request extends API\Request {
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* API request constructor.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*
|
30 |
+
* @param string $page_id page ID
|
31 |
+
*/
|
32 |
+
public function __construct( $page_id ) {
|
33 |
+
|
34 |
+
parent::__construct( "/{$page_id}", 'GET' );
|
35 |
+
}
|
36 |
+
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Gets the request parameters.
|
40 |
+
*
|
41 |
+
* @since 2.0.0
|
42 |
+
*
|
43 |
+
* @return array
|
44 |
+
*/
|
45 |
+
public function get_params() {
|
46 |
+
|
47 |
+
return [ 'fields' => 'name,link' ];
|
48 |
+
}
|
49 |
+
|
50 |
+
|
51 |
+
}
|
includes/API/Pages/Read/Response.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Pages\Read;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Page API response object.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Response extends API\Response {
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Gets the page name.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*
|
30 |
+
* @return string|null
|
31 |
+
*/
|
32 |
+
public function get_name() {
|
33 |
+
|
34 |
+
return $this->name;
|
35 |
+
}
|
36 |
+
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Gets the page URL.
|
40 |
+
*
|
41 |
+
* @since 2.0.0
|
42 |
+
*
|
43 |
+
* @return string|null
|
44 |
+
*/
|
45 |
+
public function get_url() {
|
46 |
+
|
47 |
+
return $this->link;
|
48 |
+
}
|
49 |
+
|
50 |
+
|
51 |
+
}
|
includes/API/Pixel/Events/Request.php
ADDED
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Pixel\Events;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API;
|
16 |
+
use SkyVerge\WooCommerce\Facebook\Events\Event;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Base S2S API request object.
|
20 |
+
*
|
21 |
+
* @since 2.0.0
|
22 |
+
*/
|
23 |
+
class Request extends API\Request {
|
24 |
+
|
25 |
+
|
26 |
+
/** @var Event[] events to send */
|
27 |
+
private $events;
|
28 |
+
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Request constructor.
|
32 |
+
*
|
33 |
+
* @param string $pixel_id
|
34 |
+
* @param Event[] $events events to send
|
35 |
+
*/
|
36 |
+
public function __construct( $pixel_id, array $events ) {
|
37 |
+
|
38 |
+
$this->events = $events;
|
39 |
+
|
40 |
+
parent::__construct( "/{$pixel_id}/events", 'POST' );
|
41 |
+
}
|
42 |
+
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Gets the request data.
|
46 |
+
*
|
47 |
+
* @since 2.0.0
|
48 |
+
*
|
49 |
+
* @return array
|
50 |
+
*/
|
51 |
+
public function get_data() {
|
52 |
+
|
53 |
+
$data = [
|
54 |
+
'data' => [],
|
55 |
+
'partner_agent' => Event::get_platform_identifier(),
|
56 |
+
];
|
57 |
+
|
58 |
+
foreach ( $this->events as $event ) {
|
59 |
+
|
60 |
+
if ( ! $event instanceof Event ) {
|
61 |
+
continue;
|
62 |
+
}
|
63 |
+
|
64 |
+
$event_data = $event->get_data();
|
65 |
+
|
66 |
+
if ( isset( $event_data['user_data']['click_id'] ) ) {
|
67 |
+
|
68 |
+
$event_data['user_data']['fbc'] = $event_data['user_data']['click_id'];
|
69 |
+
|
70 |
+
unset( $event_data['user_data']['click_id'] );
|
71 |
+
}
|
72 |
+
|
73 |
+
if ( isset( $event_data['user_data']['browser_id'] ) ) {
|
74 |
+
|
75 |
+
$event_data['user_data']['fbp'] = $event_data['user_data']['browser_id'];
|
76 |
+
|
77 |
+
unset( $event_data['user_data']['browser_id'] );
|
78 |
+
}
|
79 |
+
|
80 |
+
$data['data'][] = array_filter( $event_data );
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Filters the Pixel event API request data.
|
85 |
+
*
|
86 |
+
* @since 2.0.0
|
87 |
+
*
|
88 |
+
* @param array $data request data
|
89 |
+
* @param Request $request request object
|
90 |
+
*/
|
91 |
+
return apply_filters( 'wc_facebook_api_pixel_event_request_data', $data, $this);
|
92 |
+
}
|
93 |
+
|
94 |
+
|
95 |
+
}
|
includes/API/Request.php
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Base API request object.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Request extends Framework\SV_WC_API_JSON_Request {
|
23 |
+
|
24 |
+
|
25 |
+
use Traits\Rate_Limited_Request;
|
26 |
+
|
27 |
+
|
28 |
+
/**
|
29 |
+
* API request constructor.
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*
|
33 |
+
* @param string $path endpoint route
|
34 |
+
* @param string $method HTTP method
|
35 |
+
*/
|
36 |
+
public function __construct( $path, $method ) {
|
37 |
+
|
38 |
+
$this->method = $method;
|
39 |
+
$this->path = $path;
|
40 |
+
}
|
41 |
+
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Sets the request parameters.
|
45 |
+
*
|
46 |
+
* @since 2.0.0
|
47 |
+
*
|
48 |
+
* @param array $params request parameters
|
49 |
+
*/
|
50 |
+
public function set_params( $params ) {
|
51 |
+
|
52 |
+
$this->params = $params;
|
53 |
+
}
|
54 |
+
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Sets the request data.
|
58 |
+
*
|
59 |
+
* @since 2.0.0
|
60 |
+
*
|
61 |
+
* @param array $data request data
|
62 |
+
*/
|
63 |
+
public function set_data( $data ) {
|
64 |
+
|
65 |
+
$this->data = $data;
|
66 |
+
}
|
67 |
+
|
68 |
+
|
69 |
+
}
|
includes/API/Response.php
ADDED
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Base API response object
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Response extends Framework\SV_WC_API_JSON_Response {
|
23 |
+
|
24 |
+
|
25 |
+
use Traits\Rate_Limited_Response;
|
26 |
+
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Gets the response ID.
|
30 |
+
*
|
31 |
+
* @since 2.0.0
|
32 |
+
*
|
33 |
+
* @return string
|
34 |
+
*/
|
35 |
+
public function get_id() {
|
36 |
+
|
37 |
+
return $this->id;
|
38 |
+
}
|
39 |
+
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Determines whether the response includes an API error.
|
43 |
+
*
|
44 |
+
* @link https://developers.facebook.com/docs/graph-api/using-graph-api/error-handling#handling-errors
|
45 |
+
*
|
46 |
+
* @since 2.0.0
|
47 |
+
*
|
48 |
+
* @return boolean
|
49 |
+
*/
|
50 |
+
public function has_api_error() {
|
51 |
+
|
52 |
+
return (bool) $this->error;
|
53 |
+
}
|
54 |
+
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Gets the API error type.
|
58 |
+
*
|
59 |
+
* @since 2.0.0
|
60 |
+
*
|
61 |
+
* @return string|null
|
62 |
+
*/
|
63 |
+
public function get_api_error_type() {
|
64 |
+
|
65 |
+
return isset( $this->error->type ) ? $this->error->type : null;
|
66 |
+
}
|
67 |
+
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Gets the API error message.
|
71 |
+
*
|
72 |
+
* @since 2.0.0
|
73 |
+
*
|
74 |
+
* @return string|null
|
75 |
+
*/
|
76 |
+
public function get_api_error_message() {
|
77 |
+
|
78 |
+
return isset( $this->error->message ) ? $this->error->message : null;
|
79 |
+
}
|
80 |
+
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Gets the API error code.
|
84 |
+
*
|
85 |
+
* @since 2.0.0
|
86 |
+
*
|
87 |
+
* @return int|null
|
88 |
+
*/
|
89 |
+
public function get_api_error_code() {
|
90 |
+
|
91 |
+
return isset( $this->error->code ) ? (int) $this->error->code : null;
|
92 |
+
}
|
93 |
+
|
94 |
+
|
95 |
+
}
|
includes/API/Traits/Paginated_Response.php
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Traits;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Helper methods to traverse Graph API paged results.
|
18 |
+
*
|
19 |
+
* @link https://developers.facebook.com/docs/graph-api/using-graph-api/#paging
|
20 |
+
*
|
21 |
+
* @since 2.0.0
|
22 |
+
*/
|
23 |
+
trait Paginated_Response {
|
24 |
+
|
25 |
+
|
26 |
+
/** @var string number of pages retrieved from this response */
|
27 |
+
private $pages_retrieved = 1;
|
28 |
+
|
29 |
+
/** @var mixed decoded response data */
|
30 |
+
public $response_data;
|
31 |
+
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Sets the number of pages retrieved from this response.
|
35 |
+
*
|
36 |
+
* @since 2.0.0
|
37 |
+
*
|
38 |
+
* @param int $pages_retrieved
|
39 |
+
*/
|
40 |
+
public function set_pages_retrieved( $pages_retrieved ) {
|
41 |
+
|
42 |
+
$this->pages_retrieved = $pages_retrieved;
|
43 |
+
}
|
44 |
+
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Gets the number of pages retrieved from this response.
|
48 |
+
*
|
49 |
+
* @since 2.0.0
|
50 |
+
*
|
51 |
+
* @return int
|
52 |
+
*/
|
53 |
+
public function get_pages_retrieved() {
|
54 |
+
|
55 |
+
return $this->pages_retrieved;
|
56 |
+
}
|
57 |
+
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Gets the response data.
|
61 |
+
*
|
62 |
+
* @since 2.0.0
|
63 |
+
*
|
64 |
+
* @return array
|
65 |
+
*/
|
66 |
+
public function get_data() {
|
67 |
+
|
68 |
+
return ! empty( $this->response_data->data ) ? $this->response_data->data : [];
|
69 |
+
}
|
70 |
+
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Gets the pagination data.
|
74 |
+
*
|
75 |
+
* @since 2.0.0
|
76 |
+
*
|
77 |
+
* @return object
|
78 |
+
*/
|
79 |
+
public function get_pagination_data() {
|
80 |
+
|
81 |
+
return ! empty( $this->response_data->paging ) ? $this->response_data->paging : new \stdClass();
|
82 |
+
}
|
83 |
+
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Gets the API endpoint for the next page of results.
|
87 |
+
*
|
88 |
+
* @since 2.0.0
|
89 |
+
*
|
90 |
+
* @return string
|
91 |
+
*/
|
92 |
+
public function get_next_page_endpoint() {
|
93 |
+
|
94 |
+
return ! empty( $this->get_pagination_data()->next ) ? $this->get_pagination_data()->next : '';
|
95 |
+
}
|
96 |
+
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Gets the API endpoint for the previous page of results.
|
100 |
+
*
|
101 |
+
* @since 2.0.0
|
102 |
+
*
|
103 |
+
* @param string
|
104 |
+
*/
|
105 |
+
public function get_previous_page_endpoint() {
|
106 |
+
|
107 |
+
return ! empty( $this->get_pagination_data()->previous ) ? $this->get_pagination_data()->previous : '';
|
108 |
+
}
|
109 |
+
|
110 |
+
|
111 |
+
}
|
includes/API/Traits/Rate_Limited_API.php
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Traits;
|
12 |
+
|
13 |
+
use SkyVerge\WooCommerce\Facebook\API\Response;
|
14 |
+
|
15 |
+
defined( 'ABSPATH' ) or exit;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Rate limited API trait.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
trait Rate_Limited_API {
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Stores the delay, in seconds, for requests with the given rate limit ID.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*
|
30 |
+
* @param string $rate_limit_id request ID for rate limiting
|
31 |
+
* @param int $delay delay in seconds
|
32 |
+
*/
|
33 |
+
public function set_rate_limit_delay( $rate_limit_id, $delay ) {
|
34 |
+
|
35 |
+
update_option( "wc_facebook_rate_limit_${rate_limit_id}", $delay );
|
36 |
+
}
|
37 |
+
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Gets the number of seconds before a new request with the given rate limit ID can be made.
|
41 |
+
*
|
42 |
+
* @since 2.0.0
|
43 |
+
*
|
44 |
+
* @param string $rate_limit_id request ID for rate limiting
|
45 |
+
* @return int
|
46 |
+
*/
|
47 |
+
public function get_rate_limit_delay( $rate_limit_id ) {
|
48 |
+
|
49 |
+
return (int) get_option( "wc_facebook_rate_limit_${rate_limit_id}", 0 );
|
50 |
+
}
|
51 |
+
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Uses the response object and the array of headers to get information about the API usage
|
55 |
+
* and calculate the next delay for requests of the same type.
|
56 |
+
*
|
57 |
+
* @since 2.0.0
|
58 |
+
*
|
59 |
+
* @param Rate_Limited_Response $response API response object
|
60 |
+
* @param array $headers API response headers
|
61 |
+
* @return int
|
62 |
+
*/
|
63 |
+
protected function calculate_rate_limit_delay( $response, $headers ) {
|
64 |
+
|
65 |
+
// TODO: Implement calculate_rate_limit_delay() method.
|
66 |
+
return $response->get_rate_limit_estimated_time_to_regain_access( $headers );
|
67 |
+
}
|
68 |
+
|
69 |
+
|
70 |
+
}
|
includes/API/Traits/Rate_Limited_Request.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Traits;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Rate limited request trait.
|
17 |
+
*
|
18 |
+
* @since 2.0.0
|
19 |
+
*/
|
20 |
+
trait Rate_Limited_Request {
|
21 |
+
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Gets the ID of this request for rate limiting purposes.
|
25 |
+
*
|
26 |
+
* @since 2.0.0
|
27 |
+
*
|
28 |
+
* @return string
|
29 |
+
*/
|
30 |
+
public static function get_rate_limit_id() {
|
31 |
+
|
32 |
+
return 'graph_api_request';
|
33 |
+
}
|
34 |
+
|
35 |
+
|
36 |
+
}
|
includes/API/Traits/Rate_Limited_Response.php
ADDED
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\Traits;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Rate limited response trait.
|
17 |
+
*
|
18 |
+
* @since 2.0.0
|
19 |
+
*/
|
20 |
+
trait Rate_Limited_Response {
|
21 |
+
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Gets usage information from the response headers.
|
25 |
+
*
|
26 |
+
* @see https://developers.facebook.com/docs/graph-api/overview/rate-limiting#headers-2
|
27 |
+
* @see https://developers.facebook.com/docs/graph-api/overview/rate-limiting#headers
|
28 |
+
*
|
29 |
+
* @since 2.0.0
|
30 |
+
*
|
31 |
+
* @param array $headers response headers
|
32 |
+
* @return array
|
33 |
+
*/
|
34 |
+
private function get_usage_data( $headers ) {
|
35 |
+
|
36 |
+
$usage_data = [];
|
37 |
+
|
38 |
+
if ( ! empty( $headers['X-Business-Use-Case-Usage'] ) ) {
|
39 |
+
|
40 |
+
$usage_data = $headers['X-Business-Use-Case-Usage'];
|
41 |
+
|
42 |
+
} elseif ( ! empty( $headers['x-business-use-case-usage'] ) ) {
|
43 |
+
|
44 |
+
$usage_data = $headers['x-business-use-case-usage'];
|
45 |
+
|
46 |
+
} elseif ( ! empty( $headers['X-App-Usage'] ) ) {
|
47 |
+
|
48 |
+
$usage_data = $headers['X-App-Usage'];
|
49 |
+
|
50 |
+
} elseif ( ! empty( $headers['x-app-usage'] ) ) {
|
51 |
+
|
52 |
+
$usage_data = $headers['x-app-usage'];
|
53 |
+
}
|
54 |
+
|
55 |
+
return $usage_data;
|
56 |
+
}
|
57 |
+
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Gets the percentage of calls made by the app over a rolling one hour period.
|
61 |
+
*
|
62 |
+
* @since 2.0.0
|
63 |
+
*
|
64 |
+
* @param array $headers response headers
|
65 |
+
* @return int
|
66 |
+
*/
|
67 |
+
public function get_rate_limit_usage( $headers ) {
|
68 |
+
|
69 |
+
$usage_data = $this->get_usage_data( $headers );
|
70 |
+
|
71 |
+
return isset( $usage_data['call_count'] ) ? (int) $usage_data['call_count'] : 0;
|
72 |
+
}
|
73 |
+
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Gets the percentage of total time allotted for query processing.
|
77 |
+
*
|
78 |
+
* @since 2.0.0
|
79 |
+
*
|
80 |
+
* @param array $headers response headers
|
81 |
+
* @return int
|
82 |
+
*/
|
83 |
+
public function get_rate_limit_total_time( $headers ) {
|
84 |
+
|
85 |
+
$usage_data = $this->get_usage_data( $headers );
|
86 |
+
|
87 |
+
return isset( $usage_data['total_time'] ) ? (int) $usage_data['total_time'] : 0;
|
88 |
+
}
|
89 |
+
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Gets the percentage of CPU time allotted for query processing.
|
93 |
+
*
|
94 |
+
* @since 2.0.0
|
95 |
+
*
|
96 |
+
* @param array $headers response headers
|
97 |
+
* @return int
|
98 |
+
*/
|
99 |
+
public function get_rate_limit_total_cpu_time( $headers ) {
|
100 |
+
|
101 |
+
$usage_data = $this->get_usage_data( $headers );
|
102 |
+
|
103 |
+
return isset( $usage_data['total_cputime'] ) ? (int) $usage_data['total_cputime'] : 0;
|
104 |
+
}
|
105 |
+
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Gets the number of seconds until calls will no longer be throttled.
|
109 |
+
*
|
110 |
+
* @since 2.0.0
|
111 |
+
*
|
112 |
+
* @param array $headers response headers
|
113 |
+
* @return int|null
|
114 |
+
*/
|
115 |
+
public function get_rate_limit_estimated_time_to_regain_access( $headers ) {
|
116 |
+
|
117 |
+
$usage_data = $this->get_usage_data( $headers );
|
118 |
+
|
119 |
+
return ! empty( $usage_data['estimated_time_to_regain_access'] ) ? (int) $usage_data['estimated_time_to_regain_access'] : null;
|
120 |
+
}
|
121 |
+
|
122 |
+
|
123 |
+
}
|
includes/API/User/Permissions/Delete/Request.php
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\User\Permissions\Delete;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Request object for the Business Manager API.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Request extends API\Request {
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* API request constructor.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*
|
30 |
+
* @param string $user_id user ID
|
31 |
+
* @param string $permission permission to revoke
|
32 |
+
*/
|
33 |
+
public function __construct( $user_id, $permission ) {
|
34 |
+
|
35 |
+
parent::__construct( "/{$user_id}/permissions/{$permission}", 'DELETE' );
|
36 |
+
}
|
37 |
+
|
38 |
+
|
39 |
+
}
|
includes/API/User/Request.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\User;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\API;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Request object for the User API.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Request extends API\Request {
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* API request constructor.
|
27 |
+
*
|
28 |
+
* @since 2.0.0
|
29 |
+
*
|
30 |
+
* @param string $user_id user ID
|
31 |
+
*/
|
32 |
+
public function __construct( $user_id = '' ) {
|
33 |
+
|
34 |
+
if ( $user_id ) {
|
35 |
+
$path = "/{$user_id}";
|
36 |
+
} else {
|
37 |
+
$path = '/me';
|
38 |
+
}
|
39 |
+
|
40 |
+
parent::__construct( $path, 'GET' );
|
41 |
+
}
|
42 |
+
|
43 |
+
|
44 |
+
}
|
includes/API/User/Response.php
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\API\User;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* User API response object
|
17 |
+
*
|
18 |
+
* @since 2.0.0
|
19 |
+
*/
|
20 |
+
class Response extends \SkyVerge\WooCommerce\Facebook\API\Response {
|
21 |
+
|
22 |
+
}
|
23 |
+
|
includes/Admin.php
CHANGED
@@ -22,6 +22,16 @@ defined( 'ABSPATH' ) or exit;
|
|
22 |
class Admin {
|
23 |
|
24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
/**
|
26 |
* Admin constructor.
|
27 |
*
|
@@ -32,10 +42,10 @@ class Admin {
|
|
32 |
// enqueue admin scripts
|
33 |
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
|
34 |
|
35 |
-
$
|
36 |
|
37 |
// only alter the admin UI if the plugin is connected to Facebook and ready to sync products
|
38 |
-
if ( ! $
|
39 |
return;
|
40 |
}
|
41 |
|
@@ -44,20 +54,15 @@ class Admin {
|
|
44 |
// may trigger the modal to open to warn the merchant about a conflict with the current product terms
|
45 |
add_action( 'admin_footer', [ $this, 'validate_product_excluded_terms' ] );
|
46 |
|
47 |
-
// add admin
|
48 |
-
add_action( 'admin_notices', [ $this, '
|
49 |
|
50 |
-
// add admin notice
|
51 |
-
add_action( 'admin_notices', [ $this, '
|
52 |
-
|
53 |
-
add_action( 'admin_notices', [ $this, 'add_catalog_visibility_settings_removed_notice' ] );
|
54 |
-
// add admin notice if the user attempted to enable sync for virtual products using the bulk action
|
55 |
-
add_action( 'admin_notices', [ $this, 'add_enabling_virtual_products_sync_notice' ] );
|
56 |
-
// add admin notice to inform sync has been automatically disabled for virtual products
|
57 |
-
add_action( 'admin_notices', [ $this, 'add_disabled_virtual_products_sync_notice' ] );
|
58 |
|
59 |
-
//
|
60 |
-
add_action( '
|
61 |
|
62 |
// add columns for displaying Facebook sync enabled/disabled and catalog visibility status
|
63 |
add_filter( 'manage_product_posts_columns', [ $this, 'add_product_list_table_columns' ] );
|
@@ -120,33 +125,8 @@ class Admin {
|
|
120 |
|
121 |
if ( facebook_for_woocommerce()->is_plugin_settings() ) {
|
122 |
|
123 |
-
|
124 |
-
|
125 |
-
/* translators: Placeholders %1$s - opening <strong> html tag, %2$s closing </strong> html tag, {count} number of remaining items */
|
126 |
-
$sync_remaining_items_string = _n_noop( '%1$sProgress:%2$s {count} item remaining.', '%1$sProgress:%2$s {count} items remaining.', 'facebook-for-woocommerce' );
|
127 |
-
|
128 |
-
wp_localize_script( 'facebook-for-woocommerce-settings-sync', 'facebook_for_woocommerce_settings_sync', [
|
129 |
-
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
130 |
-
'set_excluded_terms_prompt_nonce' => wp_create_nonce( 'set-excluded-terms-prompt' ),
|
131 |
-
'set_product_visibility_nonce' => wp_create_nonce( 'set-products-visibility' ),
|
132 |
-
'i18n' => [
|
133 |
-
/* translators: Placeholders %s - html code for a spinner icon */
|
134 |
-
'confirm_resync' => esc_html__( 'Your products will now be resynced to Facebook, this may take some time.', 'facebook-for-woocommerce' ),
|
135 |
-
'confirm_sync_test' => esc_html__( 'Launch Test?', 'facebook-for-woocommerce' ),
|
136 |
-
'confirm_sync' => esc_html__( "Facebook for WooCommerce automatically syncs your products on create/update. Are you sure you want to force product resync?\n\nThis will query all published products and may take some time. You only need to do this if your products are out of sync or some of your products did not sync.", 'facebook-for-woocommerce' ),
|
137 |
-
'sync_in_progress' => sprintf( esc_html__( 'Syncing... Keep this browser open until sync is complete. %s', 'facebook-for-woocommerce' ), '<span class="spinner is-active"></span>' ),
|
138 |
-
'sync_remaining_items_singular' => sprintf( esc_html( translate_nooped_plural( $sync_remaining_items_string, 1 ) ), '<strong>', '</strong>', '<span class="spinner is-active"></span>' ),
|
139 |
-
'sync_remaining_items_plural' => sprintf( esc_html( translate_nooped_plural( $sync_remaining_items_string, 2 ) ), '<strong>', '</strong>', '<span class="spinner is-active"></span>' ),
|
140 |
-
/* translators: Placeholders %1$s - opening <strong> html tag, %2$s closing </strong> html tag */
|
141 |
-
'integration_test_sucessful' => sprintf( esc_html__( '%1$sStatus:%2$s Test Pass.', 'facebook-for-woocommerce' ), '<strong>', '</strong>' ),
|
142 |
-
/* translators: Placeholders %1$s - opening <strong> html tag, %2$s closing </strong> html tag */
|
143 |
-
'integration_test_in_progress' => sprintf( esc_html__( '%1$sStatus:%2$s Integration test in progress...', 'facebook-for-woocommerce' ), '<strong>', '</strong>' ),
|
144 |
-
/* translators: Placeholders %1$s - opening <strong> html tag, %2$s closing </strong> html tag */
|
145 |
-
'integration_test_failed' => sprintf( esc_html__( '%1$sStatus:%2$s Test Fail.', 'facebook-for-woocommerce' ), '<strong>', '</strong>' ),
|
146 |
-
'general_error' => esc_html__( 'There was an error trying to sync the products to Facebook.', 'facebook-for-woocommerce' ),
|
147 |
-
'feed_upload_error' => esc_html__( 'Something went wrong while uploading the product information, please try again.', 'facebook-for-woocommerce' ),
|
148 |
-
],
|
149 |
-
] );
|
150 |
}
|
151 |
}
|
152 |
}
|
@@ -164,8 +144,7 @@ class Admin {
|
|
164 |
*/
|
165 |
public function add_product_list_table_columns( $columns ) {
|
166 |
|
167 |
-
$columns['
|
168 |
-
// $columns['facebook_catalog_visibility'] = __( 'FB Catalog Visibility', 'facebook-for-woocommerce' );
|
169 |
|
170 |
return $columns;
|
171 |
}
|
@@ -183,75 +162,24 @@ class Admin {
|
|
183 |
public function add_product_list_table_columns_content( $column ) {
|
184 |
global $post;
|
185 |
|
186 |
-
if ( '
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
if ( $product && Products::product_should_be_synced( $product ) ) :
|
191 |
-
esc_html_e( 'Enabled', 'facebook-for-woocommerce' );
|
192 |
-
else :
|
193 |
-
esc_html_e( 'Disabled', 'facebook-for-woocommerce' );
|
194 |
-
endif;
|
195 |
-
|
196 |
-
elseif ( 'facebook_catalog_visibility' === $column ) :
|
197 |
-
|
198 |
-
$integration = facebook_for_woocommerce()->get_integration();
|
199 |
-
$product = wc_get_product( $post );
|
200 |
-
$fb_product = new \WC_Facebook_Product( $post );
|
201 |
-
$fb_product_group_id = $integration && $product && $integration->get_product_fbid( \WC_Facebookcommerce_Integration::FB_PRODUCT_GROUP_ID, $post->ID, $fb_product );
|
202 |
-
|
203 |
-
if ( ! $fb_product_group_id ) :
|
204 |
-
|
205 |
-
?>
|
206 |
-
<span
|
207 |
-
class="facebook-for-woocommerce-product-visibility-toggle"
|
208 |
-
style="cursor:default;"
|
209 |
-
title="<?php
|
210 |
-
/* translators: Points to a product that was never synced with Facebook */
|
211 |
-
esc_attr_e( 'Never synced with Facebook.', 'facebook-for-woocommerce' ); ?>"
|
212 |
-
>–</span>
|
213 |
-
<?php
|
214 |
-
|
215 |
-
else :
|
216 |
|
217 |
-
|
218 |
-
$is_visible = Products::is_product_visible( $product );
|
219 |
-
$is_hidden = ! $is_visible;
|
220 |
|
221 |
-
|
222 |
-
/* translators: Action to hide a product (currently synced with Facebook) from the Facebook catalog */
|
223 |
-
$visible_tooltip_text = __( 'Hide from Facebook catalog. Currently synced with Facebook.', 'facebook-for-woocommerce' );
|
224 |
-
/* translators: Action to publish a product (currently synced with Facebook) in the Facebook catalog */
|
225 |
-
$hidden_tooltip_text = __( 'Publish in Facebook catalog. Currently synced with Facebook.', 'facebook-for-woocommerce' );
|
226 |
-
} else {
|
227 |
-
/* translators: Action to hide a product (currently not synced with Facebook) from the Facebook catalog */
|
228 |
-
$visible_tooltip_text = __( 'Hide from Facebook catalog. Not synced with Facebook.', 'facebook-for-woocommerce' );
|
229 |
-
/* translators: Action to publish a product (currently not synced with Facebook) in the Facebook catalog */
|
230 |
-
$hidden_tooltip_text = __( 'Publish in Facebook catalog. Not synced with Facebook.', 'facebook-for-woocommerce' );
|
231 |
-
}
|
232 |
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
data-action="show"
|
239 |
-
data-product-id="<?php echo esc_attr( $post->ID ); ?>"
|
240 |
-
title="<?php echo esc_attr( $hidden_tooltip_text ); ?>"
|
241 |
-
><?php esc_html_e( 'Show', 'facebook-for-woocommerce' ); ?></button>
|
242 |
-
<button
|
243 |
-
id="facebook-for-woocommerce-product-visibility-hide-<?php echo esc_attr( $post->ID ); ?>"
|
244 |
-
class="button button-large facebook-for-woocommerce-product-visibility-toggle facebook-for-woocommerce-product-visibility-hide"
|
245 |
-
style="<?php echo $is_visible ? 'display:block;' : 'display:none;'; ?>"
|
246 |
-
data-action="hide"
|
247 |
-
data-product-id="<?php echo esc_attr( $post->ID ); ?>"
|
248 |
-
title="<?php echo esc_attr( $visible_tooltip_text ); ?>"
|
249 |
-
><?php esc_html_e( 'Hide', 'facebook-for-woocommerce' ); ?></button>
|
250 |
-
<?php
|
251 |
|
252 |
-
|
253 |
|
254 |
-
|
|
|
255 |
}
|
256 |
|
257 |
|
@@ -275,8 +203,9 @@ class Admin {
|
|
275 |
?>
|
276 |
<select name="fb_sync_enabled">
|
277 |
<option value="" <?php selected( $choice, '' ); ?>><?php esc_html_e( 'Filter by Facebook sync setting', 'facebook-for-woocommerce' ); ?></option>
|
278 |
-
<option value="
|
279 |
-
<option value="
|
|
|
280 |
</select>
|
281 |
<?php
|
282 |
}
|
@@ -294,8 +223,20 @@ class Admin {
|
|
294 |
*/
|
295 |
public function filter_products_by_sync_enabled( $query_vars ) {
|
296 |
|
|
|
|
|
|
|
|
|
|
|
|
|
297 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
298 |
-
if ( isset( $_REQUEST['fb_sync_enabled'] ) && in_array( $_REQUEST['fb_sync_enabled'],
|
|
|
|
|
|
|
|
|
|
|
|
|
299 |
|
300 |
// by default use an "AND" clause if multiple conditions exist for a meta query
|
301 |
if ( ! empty( $query_vars['meta_query'] ) ) {
|
@@ -304,13 +245,15 @@ class Admin {
|
|
304 |
$query_vars['meta_query'] = [];
|
305 |
}
|
306 |
|
307 |
-
|
308 |
-
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
309 |
-
if ( 'yes' === $_REQUEST['fb_sync_enabled'] ) {
|
310 |
|
|
|
311 |
$query_vars = $this->add_query_vars_to_find_products_with_sync_enabled( $query_vars );
|
312 |
|
313 |
-
//
|
|
|
|
|
|
|
314 |
$exclude_products = [];
|
315 |
$found_ids = get_posts( array_merge( $query_vars, [ 'fields' => 'ids' ] ) );
|
316 |
$found_products = empty( $found_ids ) ? [] : wc_get_products( [
|
@@ -322,7 +265,44 @@ class Admin {
|
|
322 |
/** @var \WC_Product[] $found_products */
|
323 |
foreach ( $found_products as $product ) {
|
324 |
|
325 |
-
if ( ! Products::is_sync_enabled_for_product( $product )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
326 |
$exclude_products[] = $product->get_id();
|
327 |
}
|
328 |
}
|
@@ -335,38 +315,107 @@ class Admin {
|
|
335 |
}
|
336 |
}
|
337 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
338 |
} else {
|
339 |
|
|
|
|
|
|
|
|
|
|
|
|
|
340 |
$integration = facebook_for_woocommerce()->get_integration();
|
341 |
$excluded_categories_ids = $integration ? $integration->get_excluded_product_category_ids() : [];
|
342 |
$excluded_tags_ids = $integration ? $integration->get_excluded_product_tag_ids() : [];
|
343 |
|
|
|
344 |
if ( $excluded_categories_ids || $excluded_tags_ids ) {
|
345 |
|
346 |
-
|
347 |
-
$
|
348 |
-
|
349 |
-
'post_status' => ! empty( $query_vars['post_status'] ) ? $query_vars['post_status'] : 'any',
|
350 |
-
'no_found_rows' => true,
|
351 |
-
'update_post_meta_cache' => false,
|
352 |
-
'update_post_term_cache' => false,
|
353 |
-
'fields' => 'ids',
|
354 |
-
'nopaging' => true,
|
355 |
-
];
|
356 |
-
|
357 |
-
$products_query_vars = $this->add_query_vars_to_find_products_with_sync_enabled( $products_query_vars );
|
358 |
|
359 |
-
|
360 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
361 |
|
362 |
-
|
363 |
|
364 |
-
|
|
|
|
|
|
|
|
|
|
|
365 |
'key' => Products::SYNC_ENABLED_META_KEY,
|
366 |
'value' => 'no',
|
367 |
-
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
368 |
}
|
369 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
370 |
}
|
371 |
|
372 |
return $query_vars;
|
@@ -383,16 +432,32 @@ class Admin {
|
|
383 |
*/
|
384 |
private function add_query_vars_to_find_products_with_sync_enabled( array $query_vars ) {
|
385 |
|
386 |
-
$
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
|
|
|
|
394 |
];
|
395 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
396 |
// check whether the product belongs to an excluded product category or tag
|
397 |
$query_vars = $this->maybe_add_tax_query_for_excluded_taxonomies( $query_vars );
|
398 |
|
@@ -401,14 +466,15 @@ class Admin {
|
|
401 |
|
402 |
|
403 |
/**
|
404 |
-
* Adds a tax query to filter out products in excluded product categories and product tags.
|
405 |
*
|
406 |
* @since 1.10.0
|
407 |
*
|
408 |
* @param array $query_vars product query vars for the edit screen
|
|
|
409 |
* @return array
|
410 |
*/
|
411 |
-
private function maybe_add_tax_query_for_excluded_taxonomies( $query_vars ) {
|
412 |
|
413 |
$integration = facebook_for_woocommerce()->get_integration();
|
414 |
|
@@ -422,7 +488,7 @@ class Admin {
|
|
422 |
'taxonomy' => 'product_cat',
|
423 |
'terms' => $excluded_categories_ids,
|
424 |
'field' => 'term_id',
|
425 |
-
'operator' => 'NOT IN',
|
426 |
];
|
427 |
}
|
428 |
|
@@ -433,10 +499,14 @@ class Admin {
|
|
433 |
'taxonomy' => 'product_tag',
|
434 |
'terms' => $excluded_tags_ids,
|
435 |
'field' => 'term_id',
|
436 |
-
'operator' => 'NOT IN',
|
437 |
];
|
438 |
}
|
439 |
|
|
|
|
|
|
|
|
|
440 |
if ( $tax_query && empty( $query_vars['tax_query'] ) ) {
|
441 |
$query_vars['tax_query'] = $tax_query;
|
442 |
} elseif ( $tax_query && is_array( $query_vars ) ) {
|
@@ -448,6 +518,79 @@ class Admin {
|
|
448 |
}
|
449 |
|
450 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
451 |
/**
|
452 |
* Adds bulk actions in the products edit screen.
|
453 |
*
|
@@ -498,66 +641,77 @@ class Admin {
|
|
498 |
|
499 |
if ( ! empty( $product_ids ) ) {
|
500 |
|
501 |
-
$
|
502 |
-
$
|
|
|
|
|
503 |
|
504 |
foreach ( $product_ids as $product_id ) {
|
505 |
|
506 |
if ( $product = wc_get_product( $product_id ) ) {
|
507 |
|
|
|
|
|
508 |
if ( 'facebook_include' === $action ) {
|
509 |
|
510 |
-
if ( $product->is_virtual() ) {
|
511 |
|
512 |
-
$
|
513 |
|
514 |
} else {
|
515 |
|
516 |
-
// products with virtual variations are also added to the list,
|
517 |
-
// because they may have non-virtual variations as well
|
518 |
-
$products[] = $product;
|
519 |
-
|
520 |
if ( $product->is_type( 'variable' ) ) {
|
521 |
|
522 |
-
//
|
523 |
foreach ( $product->get_children() as $variation_id ) {
|
524 |
|
525 |
$variation = wc_get_product( $variation_id );
|
526 |
|
527 |
-
if ( $variation && $variation->is_virtual() ) {
|
528 |
|
529 |
-
$
|
530 |
-
|
531 |
}
|
532 |
}
|
533 |
}
|
534 |
}
|
535 |
-
} else {
|
536 |
-
|
537 |
-
// add the product to the list of products to disable sync from
|
538 |
-
$products[] = $product;
|
539 |
}
|
540 |
}
|
541 |
}
|
542 |
|
543 |
-
|
544 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
545 |
|
546 |
-
|
|
|
|
|
|
|
|
|
547 |
}
|
548 |
|
549 |
if ( 'facebook_include' === $action ) {
|
550 |
|
551 |
Products::enable_sync_for_products( $products );
|
552 |
|
553 |
-
|
554 |
-
foreach ( $products as $product ) {
|
555 |
-
facebook_for_woocommerce()->get_integration()->on_product_publish( $product->get_id() );
|
556 |
-
}
|
557 |
|
558 |
} elseif ( 'facebook_exclude' === $action ) {
|
559 |
|
560 |
Products::disable_sync_for_products( $products );
|
|
|
|
|
561 |
}
|
562 |
}
|
563 |
}
|
@@ -567,177 +721,193 @@ class Admin {
|
|
567 |
|
568 |
|
569 |
/**
|
570 |
-
*
|
571 |
*
|
572 |
-
* @
|
573 |
-
*
|
574 |
-
* TODO: update this method to use the notice handler once we framework the plugin {CW 2020-01-09}
|
575 |
*
|
576 |
-
* @
|
577 |
*/
|
578 |
-
|
579 |
-
global $current_screen;
|
580 |
|
581 |
-
|
582 |
|
583 |
-
|
|
|
584 |
|
585 |
-
if (
|
586 |
|
587 |
-
|
588 |
-
|
589 |
-
<?php printf(
|
590 |
-
/* translators: Placeholders: %1$s - Facebook for Woocommerce, %2$s - opening HTML <a> link tag, %3$s - closing HTML </a> link tag */
|
591 |
-
'<p>' . esc_html__( '%1$s: One or more of your products is using a checkout URL that may be different than your shop checkout URL. %2$sRe-sync your products to update checkout URLs on Facebook%3$s.', 'facebook-for-woocommerce' ) . '</p>',
|
592 |
-
'<strong>' . esc_html__( 'Facebook for WooCommerce', 'facebook-for-woocommerce' ) . '</strong>',
|
593 |
-
'<a href="' . esc_url( WOOCOMMERCE_FACEBOOK_PLUGIN_SETTINGS_URL ) . '">',
|
594 |
-
'</a>'
|
595 |
-
); ?>
|
596 |
-
</div>
|
597 |
-
<?php
|
598 |
|
599 |
-
|
600 |
|
601 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
602 |
}
|
603 |
|
604 |
|
605 |
/**
|
606 |
-
* Prints a notice on products page
|
|
|
|
|
607 |
*
|
608 |
* @internal
|
609 |
*
|
610 |
-
* @since 1.
|
|
|
611 |
*/
|
612 |
-
public function
|
613 |
-
global $current_screen;
|
614 |
-
|
615 |
-
$transient_name = 'wc_' . facebook_for_woocommerce()->get_id() . '_show_product_sync_delay_notice_' . get_current_user_id();
|
616 |
-
|
617 |
-
if ( isset( $current_screen->id ) && in_array( $current_screen->id, [ 'edit-product', 'product' ], true ) && get_transient( $transient_name ) ) {
|
618 |
-
|
619 |
-
if ( isset( $_GET['message'] ) || isset( $_GET['trashed'] ) || isset( $_GET['deleted'] ) ) {
|
620 |
-
|
621 |
-
facebook_for_woocommerce()->get_admin_notice_handler()->add_admin_notice(
|
622 |
-
sprintf(
|
623 |
-
/* 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 */
|
624 |
-
esc_html__( '%1$sHeads up!%2$s Product sync is temporarily changed as we migrate to a more secure experience. An automated sync from Facebook will run every hour to update the catalog with any changes you\'ve made. %3$sLearn more%4$s', 'facebook-for-woocommerce' ),
|
625 |
-
'<strong>',
|
626 |
-
'</strong>',
|
627 |
-
'<a href="https://docs.woocommerce.com/document/facebook-for-woocommerce/#faq-security" target="_blank">',
|
628 |
-
'</a>'
|
629 |
-
)
|
630 |
-
. '</p><p>' // close notice paragraph and open a new one for the button
|
631 |
-
. '<button class="button notice-dismiss-permanently" type="button">' . esc_html__( "Don't show this notice again", 'facebook-for-woocommerce' ) . '</button>',
|
632 |
-
'wc-' . facebook_for_woocommerce()->get_id_dasherized() . '-product-sync-delay',
|
633 |
-
[ 'notice_class' => 'notice-info' ]
|
634 |
-
);
|
635 |
-
}
|
636 |
|
637 |
-
|
638 |
-
}
|
639 |
}
|
640 |
|
641 |
|
642 |
/**
|
643 |
-
*
|
644 |
*
|
645 |
-
* @
|
646 |
*
|
647 |
-
* @
|
648 |
-
*
|
649 |
-
* @param string $message_id the dismissed notice ID
|
650 |
-
* @param int $user_id the ID of the user the noticed was dismissed for
|
651 |
*/
|
652 |
-
public function
|
653 |
-
|
654 |
-
// undismiss product sync delay notice unless 'permanently' is included in the request
|
655 |
-
if ( ! SV_WC_Helper::get_requested_value( 'permanently' ) && 'wc-' . facebook_for_woocommerce()->get_id_dasherized() . '-product-sync-delay' === $message_id ) {
|
656 |
|
657 |
-
|
|
|
658 |
}
|
659 |
}
|
660 |
|
661 |
|
662 |
/**
|
663 |
-
*
|
664 |
*
|
665 |
-
* @
|
666 |
-
*
|
667 |
-
* @since 1.11.0
|
668 |
*/
|
669 |
-
public function
|
670 |
-
|
|
|
|
|
|
|
|
|
671 |
|
672 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
673 |
|
674 |
facebook_for_woocommerce()->get_admin_notice_handler()->add_admin_notice(
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
'
|
679 |
-
'
|
680 |
-
|
681 |
-
'</a>'
|
682 |
-
),
|
683 |
-
'wc-' . facebook_for_woocommerce()->get_id_dasherized() . '-catalog-visibility-settings-removed',
|
684 |
-
[ 'notice_class' => 'notice-info' ]
|
685 |
);
|
|
|
|
|
686 |
}
|
687 |
}
|
688 |
|
689 |
|
690 |
/**
|
691 |
-
* Prints a notice on products page to inform users that the virtual products selected for the Include bulk action will
|
692 |
*
|
693 |
* @internal
|
694 |
*
|
695 |
* @since 1.11.3-dev.2
|
696 |
*/
|
697 |
-
public function
|
698 |
-
|
699 |
-
|
700 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
701 |
|
702 |
facebook_for_woocommerce()->get_admin_notice_handler()->add_admin_notice(
|
703 |
-
|
704 |
-
/* 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 */
|
705 |
-
esc_html__( '%1$sHeads up!%2$s Facebook does not support selling virtual products, so we can\'t include virtual products in your catalog sync. %3$sClick here to read more about Facebook\'s policy%4$s.', 'facebook-for-woocommerce' ),
|
706 |
-
'<strong>',
|
707 |
-
'</strong>',
|
708 |
-
'<a href="https://www.facebook.com/help/130910837313345" target="_blank">',
|
709 |
-
'</a>'
|
710 |
-
),
|
711 |
'wc-' . facebook_for_woocommerce()->get_id_dasherized() . '-enabling-virtual-products-sync',
|
712 |
-
[
|
|
|
|
|
|
|
713 |
);
|
|
|
|
|
714 |
}
|
715 |
}
|
716 |
|
717 |
|
718 |
/**
|
719 |
-
*
|
720 |
*
|
721 |
* @internal
|
722 |
*
|
723 |
-
* @since
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
724 |
*/
|
725 |
-
public function
|
726 |
|
727 |
-
if ( 'yes' === get_option( '
|
728 |
-
'yes' !== get_option( '
|
729 |
|
730 |
facebook_for_woocommerce()->get_admin_notice_handler()->add_admin_notice(
|
731 |
sprintf(
|
732 |
/* 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 */
|
733 |
-
esc_html__( '%1$sHeads up!%2$s Facebook
|
734 |
'<strong>',
|
735 |
'</strong>',
|
736 |
-
'<a href="https://www.facebook.com/
|
737 |
'</a>'
|
738 |
),
|
739 |
-
'wc-' . facebook_for_woocommerce()->get_id_dasherized() . '-
|
740 |
-
[
|
|
|
|
|
|
|
741 |
);
|
742 |
}
|
743 |
}
|
@@ -758,7 +928,7 @@ class Admin {
|
|
758 |
$tabs['fb_commerce_tab'] = [
|
759 |
'label' => __( 'Facebook', 'facebook-for-woocommerce' ),
|
760 |
'target' => 'facebook_options',
|
761 |
-
'class' => [ 'show_if_simple'
|
762 |
];
|
763 |
|
764 |
return $tabs;
|
@@ -777,21 +947,34 @@ class Admin {
|
|
777 |
|
778 |
// all products have sync enabled unless explicitly disabled
|
779 |
$sync_enabled = 'no' !== get_post_meta( $post->ID, Products::SYNC_ENABLED_META_KEY, true );
|
|
|
|
|
780 |
$description = get_post_meta( $post->ID, \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION, true );
|
781 |
$price = get_post_meta( $post->ID, \WC_Facebook_Product::FB_PRODUCT_PRICE, true );
|
782 |
$image_source = get_post_meta( $post->ID, Products::PRODUCT_IMAGE_SOURCE_META_KEY, true );
|
783 |
$image = get_post_meta( $post->ID, \WC_Facebook_Product::FB_PRODUCT_IMAGE, true );
|
784 |
|
|
|
|
|
|
|
|
|
|
|
|
|
785 |
// 'id' attribute needs to match the 'target' parameter set above
|
786 |
?>
|
787 |
<div id='facebook_options' class='panel woocommerce_options_panel'>
|
788 |
<div class='options_group'>
|
789 |
<?php
|
790 |
|
791 |
-
|
792 |
-
'id'
|
793 |
-
'label'
|
794 |
-
'
|
|
|
|
|
|
|
|
|
|
|
795 |
] );
|
796 |
|
797 |
woocommerce_wp_textarea_input( [
|
@@ -802,7 +985,7 @@ class Admin {
|
|
802 |
'cols' => 40,
|
803 |
'rows' => 20,
|
804 |
'value' => $description,
|
805 |
-
'class' => 'enable-if-sync-enabled',
|
806 |
] );
|
807 |
|
808 |
woocommerce_wp_radio( [
|
@@ -873,19 +1056,32 @@ class Admin {
|
|
873 |
return;
|
874 |
}
|
875 |
|
876 |
-
$sync_enabled = $this->get_product_variation_meta( $variation, Products::SYNC_ENABLED_META_KEY, $parent );
|
|
|
|
|
877 |
$description = $this->get_product_variation_meta( $variation, \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION, $parent );
|
878 |
$price = $this->get_product_variation_meta( $variation, \WC_Facebook_Product::FB_PRODUCT_PRICE, $parent );
|
879 |
$image_url = $this->get_product_variation_meta( $variation, \WC_Facebook_Product::FB_PRODUCT_IMAGE, $parent );
|
880 |
$image_source = $variation->get_meta( Products::PRODUCT_IMAGE_SOURCE_META_KEY );
|
881 |
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
889 |
] );
|
890 |
|
891 |
woocommerce_wp_textarea_input( [
|
@@ -898,7 +1094,7 @@ class Admin {
|
|
898 |
'rows' => 5,
|
899 |
'value' => $description,
|
900 |
'class' => 'enable-if-sync-enabled',
|
901 |
-
'wrapper_class' => 'form-row form-row-full
|
902 |
] );
|
903 |
|
904 |
woocommerce_wp_radio( [
|
@@ -914,7 +1110,7 @@ class Admin {
|
|
914 |
],
|
915 |
'value' => $image_source ?: Products::PRODUCT_IMAGE_SOURCE_PRODUCT,
|
916 |
'class' => 'enable-if-sync-enabled js-fb-product-image-source',
|
917 |
-
'wrapper_class' => 'fb-product-image-source-field
|
918 |
] );
|
919 |
|
920 |
woocommerce_wp_text_input( [
|
@@ -923,7 +1119,7 @@ class Admin {
|
|
923 |
'label' => __( 'Custom Image URL', 'facebook-for-woocommerce' ),
|
924 |
'value' => $image_url,
|
925 |
'class' => sprintf( 'enable-if-sync-enabled product-image-source-field show-if-product-image-source-%s', Products::PRODUCT_IMAGE_SOURCE_CUSTOM ),
|
926 |
-
'wrapper_class' => 'form-row form-row-full
|
927 |
] );
|
928 |
|
929 |
woocommerce_wp_text_input( [
|
@@ -938,7 +1134,7 @@ class Admin {
|
|
938 |
'description' => __( '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.', 'facebook-for-woocommerce' ),
|
939 |
'value' => wc_format_decimal( $price ),
|
940 |
'class' => 'enable-if-sync-enabled',
|
941 |
-
'wrapper_class' => 'form-row form-full
|
942 |
] );
|
943 |
}
|
944 |
|
@@ -985,10 +1181,19 @@ class Admin {
|
|
985 |
return;
|
986 |
}
|
987 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
988 |
// phpcs:disable WordPress.Security.NonceVerification.Missing
|
989 |
-
if (
|
990 |
|
991 |
Products::enable_sync_for_products( [ $variation ] );
|
|
|
992 |
|
993 |
$posted_param = 'variable_' . \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION;
|
994 |
$description = isset( $_POST[ $posted_param ][ $index ] ) ? sanitize_text_field( wp_unslash( $_POST[ $posted_param ][ $index ] ) ) : null;
|
@@ -1028,7 +1233,7 @@ class Admin {
|
|
1028 |
global $current_screen;
|
1029 |
|
1030 |
// bail if not on the products, product edit, or settings screen
|
1031 |
-
if ( ! $current_screen || ! in_array( $current_screen->id, [ 'edit-product', 'product', 'woocommerce_page_wc-
|
1032 |
return;
|
1033 |
}
|
1034 |
|
@@ -1118,4 +1323,52 @@ class Admin {
|
|
1118 |
}
|
1119 |
|
1120 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1121 |
}
|
22 |
class Admin {
|
23 |
|
24 |
|
25 |
+
/** @var string the "sync and show" sync mode slug */
|
26 |
+
const SYNC_MODE_SYNC_AND_SHOW = 'sync_and_show';
|
27 |
+
|
28 |
+
/** @var string the "sync and show" sync mode slug */
|
29 |
+
const SYNC_MODE_SYNC_AND_HIDE = 'sync_and_hide';
|
30 |
+
|
31 |
+
/** @var string the "sync disabled" sync mode slug */
|
32 |
+
const SYNC_MODE_SYNC_DISABLED = 'sync_disabled';
|
33 |
+
|
34 |
+
|
35 |
/**
|
36 |
* Admin constructor.
|
37 |
*
|
42 |
// enqueue admin scripts
|
43 |
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
|
44 |
|
45 |
+
$plugin = facebook_for_woocommerce();
|
46 |
|
47 |
// only alter the admin UI if the plugin is connected to Facebook and ready to sync products
|
48 |
+
if ( ! $plugin->get_connection_handler()->is_connected() || ! $plugin->get_integration()->get_product_catalog_id() ) {
|
49 |
return;
|
50 |
}
|
51 |
|
54 |
// may trigger the modal to open to warn the merchant about a conflict with the current product terms
|
55 |
add_action( 'admin_footer', [ $this, 'validate_product_excluded_terms' ] );
|
56 |
|
57 |
+
// add admin notice to inform that disabled products may need to be deleted manually
|
58 |
+
add_action( 'admin_notices', [ $this, 'maybe_show_product_disabled_sync_notice' ] );
|
59 |
|
60 |
+
// add admin notice if the user is enabling sync for virtual products using the bulk action
|
61 |
+
add_action( 'admin_notices', [ $this, 'maybe_add_enabling_virtual_products_sync_notice' ] );
|
62 |
+
add_filter( 'request', [ $this, 'filter_virtual_products_affected_enabling_sync' ] );
|
|
|
|
|
|
|
|
|
|
|
63 |
|
64 |
+
// add admin notice to inform sync mode has been automatically set to Sync and hide for virtual products and variations
|
65 |
+
add_action( 'admin_notices', [ $this, 'add_handled_virtual_products_variations_notice' ] );
|
66 |
|
67 |
// add columns for displaying Facebook sync enabled/disabled and catalog visibility status
|
68 |
add_filter( 'manage_product_posts_columns', [ $this, 'add_product_list_table_columns' ] );
|
125 |
|
126 |
if ( facebook_for_woocommerce()->is_plugin_settings() ) {
|
127 |
|
128 |
+
wp_enqueue_style( 'woocommerce_admin_styles' );
|
129 |
+
wp_enqueue_script( 'wc-enhanced-select' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
}
|
131 |
}
|
132 |
}
|
144 |
*/
|
145 |
public function add_product_list_table_columns( $columns ) {
|
146 |
|
147 |
+
$columns['facebook_sync'] = __( 'Facebook sync', 'facebook-for-woocommerce' );
|
|
|
148 |
|
149 |
return $columns;
|
150 |
}
|
162 |
public function add_product_list_table_columns_content( $column ) {
|
163 |
global $post;
|
164 |
|
165 |
+
if ( 'facebook_sync' !== $column ) {
|
166 |
+
return;
|
167 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
|
169 |
+
$product = wc_get_product( $post );
|
|
|
|
|
170 |
|
171 |
+
if ( $product && Products::product_should_be_synced( $product ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
|
173 |
+
if ( Products::is_product_visible( $product ) ) {
|
174 |
+
esc_html_e( 'Sync and show', 'facebook-for-woocommerce' );
|
175 |
+
} else {
|
176 |
+
esc_html_e( 'Sync and hide', 'facebook-for-woocommerce' );
|
177 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
|
179 |
+
} else {
|
180 |
|
181 |
+
esc_html_e( 'Do not sync', 'facebook-for-woocommerce' );
|
182 |
+
}
|
183 |
}
|
184 |
|
185 |
|
203 |
?>
|
204 |
<select name="fb_sync_enabled">
|
205 |
<option value="" <?php selected( $choice, '' ); ?>><?php esc_html_e( 'Filter by Facebook sync setting', 'facebook-for-woocommerce' ); ?></option>
|
206 |
+
<option value="<?php echo self::SYNC_MODE_SYNC_AND_SHOW; ?>" <?php selected( $choice, self::SYNC_MODE_SYNC_AND_SHOW ); ?>><?php esc_html_e( 'Sync and show', 'facebook-for-woocommerce' ); ?></option>
|
207 |
+
<option value="<?php echo self::SYNC_MODE_SYNC_AND_HIDE; ?>" <?php selected( $choice, self::SYNC_MODE_SYNC_AND_HIDE ); ?>><?php esc_html_e( 'Sync and hide', 'facebook-for-woocommerce' ); ?></option>
|
208 |
+
<option value="<?php echo self::SYNC_MODE_SYNC_DISABLED; ?>" <?php selected( $choice, self::SYNC_MODE_SYNC_DISABLED ); ?>><?php esc_html_e( 'Do not sync', 'facebook-for-woocommerce' ); ?></option>
|
209 |
</select>
|
210 |
<?php
|
211 |
}
|
223 |
*/
|
224 |
public function filter_products_by_sync_enabled( $query_vars ) {
|
225 |
|
226 |
+
$valid_values = [
|
227 |
+
self::SYNC_MODE_SYNC_AND_SHOW,
|
228 |
+
self::SYNC_MODE_SYNC_AND_HIDE,
|
229 |
+
self::SYNC_MODE_SYNC_DISABLED,
|
230 |
+
];
|
231 |
+
|
232 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
233 |
+
if ( isset( $_REQUEST['fb_sync_enabled'] ) && in_array( $_REQUEST['fb_sync_enabled'], $valid_values, true ) ) {
|
234 |
+
|
235 |
+
// store original meta query
|
236 |
+
$original_meta_query = ! empty( $query_vars['meta_query'] ) ? $query_vars['meta_query'] : [];
|
237 |
+
|
238 |
+
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
239 |
+
$filter_value = $_REQUEST['fb_sync_enabled'];
|
240 |
|
241 |
// by default use an "AND" clause if multiple conditions exist for a meta query
|
242 |
if ( ! empty( $query_vars['meta_query'] ) ) {
|
245 |
$query_vars['meta_query'] = [];
|
246 |
}
|
247 |
|
248 |
+
if ( self::SYNC_MODE_SYNC_AND_SHOW === $filter_value ) {
|
|
|
|
|
249 |
|
250 |
+
// when checking for products with sync enabled we need to check both "yes" and meta not set, this requires adding an "OR" clause
|
251 |
$query_vars = $this->add_query_vars_to_find_products_with_sync_enabled( $query_vars );
|
252 |
|
253 |
+
// only get visible products (both "yes" and meta not set)
|
254 |
+
$query_vars = $this->add_query_vars_to_find_visible_products( $query_vars );
|
255 |
+
|
256 |
+
// since we record enabled status and visibility on child variations, we need to query variable products found for their children to exclude them from query results
|
257 |
$exclude_products = [];
|
258 |
$found_ids = get_posts( array_merge( $query_vars, [ 'fields' => 'ids' ] ) );
|
259 |
$found_products = empty( $found_ids ) ? [] : wc_get_products( [
|
265 |
/** @var \WC_Product[] $found_products */
|
266 |
foreach ( $found_products as $product ) {
|
267 |
|
268 |
+
if ( ! Products::is_sync_enabled_for_product( $product )
|
269 |
+
|| ! Products::is_product_visible( $product ) ) {
|
270 |
+
|
271 |
+
$exclude_products[] = $product->get_id();
|
272 |
+
}
|
273 |
+
}
|
274 |
+
|
275 |
+
if ( ! empty( $exclude_products ) ) {
|
276 |
+
if ( ! empty( $query_vars['post__not_in'] ) ) {
|
277 |
+
$query_vars['post__not_in'] = array_merge( $query_vars['post__not_in'], $exclude_products );
|
278 |
+
} else {
|
279 |
+
$query_vars['post__not_in'] = $exclude_products;
|
280 |
+
}
|
281 |
+
}
|
282 |
+
|
283 |
+
} elseif ( self::SYNC_MODE_SYNC_AND_HIDE === $filter_value ) {
|
284 |
+
|
285 |
+
// when checking for products with sync enabled we need to check both "yes" and meta not set, this requires adding an "OR" clause
|
286 |
+
$query_vars = $this->add_query_vars_to_find_products_with_sync_enabled( $query_vars );
|
287 |
+
|
288 |
+
// only get hidden products
|
289 |
+
$query_vars = $this->add_query_vars_to_find_hidden_products( $query_vars );
|
290 |
+
|
291 |
+
// since we record enabled status and visibility on child variations, we need to query variable products found for their children to exclude them from query results
|
292 |
+
$exclude_products = [];
|
293 |
+
$found_ids = get_posts( array_merge( $query_vars, [ 'fields' => 'ids' ] ) );
|
294 |
+
$found_products = empty( $found_ids ) ? [] : wc_get_products( [
|
295 |
+
'limit' => -1,
|
296 |
+
'type' => 'variable',
|
297 |
+
'include' => $found_ids,
|
298 |
+
] );
|
299 |
+
|
300 |
+
/** @var \WC_Product[] $found_products */
|
301 |
+
foreach ( $found_products as $product ) {
|
302 |
+
|
303 |
+
if ( ! Products::is_sync_enabled_for_product( $product )
|
304 |
+
|| Products::is_product_visible( $product ) ) {
|
305 |
+
|
306 |
$exclude_products[] = $product->get_id();
|
307 |
}
|
308 |
}
|
315 |
}
|
316 |
}
|
317 |
|
318 |
+
// for the same reason, we also need to include variable products with hidden children
|
319 |
+
$include_products = [];
|
320 |
+
$hidden_variations = get_posts( [
|
321 |
+
'limit' => -1,
|
322 |
+
'post_type' => 'product_variation',
|
323 |
+
'meta_query' => [
|
324 |
+
'key' => Products::VISIBILITY_META_KEY,
|
325 |
+
'value' => 'no',
|
326 |
+
]
|
327 |
+
] );
|
328 |
+
|
329 |
+
/** @var \WP_Post[] $hidden_variations */
|
330 |
+
foreach ( $hidden_variations as $variation_post ) {
|
331 |
+
|
332 |
+
$variable_product = wc_get_product( $variation_post->post_parent );
|
333 |
+
|
334 |
+
// we need this check because we only want products with ALL variations hidden
|
335 |
+
if ( $variable_product instanceof \WC_Product && Products::is_sync_enabled_for_product( $variable_product )
|
336 |
+
&& ! Products::is_product_visible( $variable_product ) ) {
|
337 |
+
|
338 |
+
$include_products[] = $variable_product->get_id();
|
339 |
+
}
|
340 |
+
}
|
341 |
+
|
342 |
} else {
|
343 |
|
344 |
+
// self::SYNC_MODE_SYNC_DISABLED
|
345 |
+
|
346 |
+
// products to be included in the QUERY, not in the sync
|
347 |
+
$include_products = [];
|
348 |
+
$found_ids = [];
|
349 |
+
|
350 |
$integration = facebook_for_woocommerce()->get_integration();
|
351 |
$excluded_categories_ids = $integration ? $integration->get_excluded_product_category_ids() : [];
|
352 |
$excluded_tags_ids = $integration ? $integration->get_excluded_product_tag_ids() : [];
|
353 |
|
354 |
+
// get the product IDs from all products in excluded taxonomies
|
355 |
if ( $excluded_categories_ids || $excluded_tags_ids ) {
|
356 |
|
357 |
+
$tax_query_vars = $this->maybe_add_tax_query_for_excluded_taxonomies( $query_vars, true );
|
358 |
+
$include_products = array_merge( $include_products, get_posts( array_merge( $tax_query_vars, [ 'fields' => 'ids' ] ) ) );
|
359 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
|
361 |
+
$excluded_products = get_posts( [
|
362 |
+
'fields' => 'ids',
|
363 |
+
'limit' => -1,
|
364 |
+
'post_type' => 'product',
|
365 |
+
'meta_query' => [[
|
366 |
+
'key' => Products::SYNC_ENABLED_META_KEY,
|
367 |
+
'value' => 'no',
|
368 |
+
]]
|
369 |
+
] );
|
370 |
|
371 |
+
$include_products = array_unique( array_merge( $include_products, $excluded_products ));
|
372 |
|
373 |
+
// since we record enabled status and visibility on child variations,
|
374 |
+
// we need to include variable products with excluded children
|
375 |
+
$excluded_variations = get_posts( [
|
376 |
+
'limit' => -1,
|
377 |
+
'post_type' => 'product_variation',
|
378 |
+
'meta_query' => [[
|
379 |
'key' => Products::SYNC_ENABLED_META_KEY,
|
380 |
'value' => 'no',
|
381 |
+
]]
|
382 |
+
] );
|
383 |
+
|
384 |
+
/** @var \WP_Post[] $excluded_variations */
|
385 |
+
foreach ( $excluded_variations as $variation_post ) {
|
386 |
+
|
387 |
+
$variable_product = wc_get_product( $variation_post->post_parent );
|
388 |
+
|
389 |
+
// we need this check because we only want products with ALL variations excluded
|
390 |
+
if ( ! Products::is_sync_enabled_for_product( $variable_product ) ) {
|
391 |
+
|
392 |
+
$include_products[] = $variable_product->get_id();
|
393 |
+
}
|
394 |
}
|
395 |
}
|
396 |
+
|
397 |
+
if ( ! empty( $include_products ) ) {
|
398 |
+
|
399 |
+
// we are going to query by ID, so we want to include all the IDs from before
|
400 |
+
$include_products = array_unique( array_merge( $found_ids, $include_products ) );
|
401 |
+
|
402 |
+
if ( ! empty( $query_vars['post__in'] ) ) {
|
403 |
+
$query_vars['post__in'] = array_merge( $query_vars['post__in'], $include_products );
|
404 |
+
} else {
|
405 |
+
$query_vars['post__in'] = $include_products;
|
406 |
+
}
|
407 |
+
|
408 |
+
// remove sync enabled and visibility meta queries
|
409 |
+
if ( ! empty( $original_meta_query ) ) {
|
410 |
+
$query_vars['meta_query'] = $original_meta_query;
|
411 |
+
} else {
|
412 |
+
unset( $query_vars['meta_query'] );
|
413 |
+
}
|
414 |
+
}
|
415 |
+
}
|
416 |
+
|
417 |
+
if ( isset( $query_vars['meta_query'] ) && empty( $query_vars['meta_query'] ) ) {
|
418 |
+
unset( $query_vars['meta_query'] );
|
419 |
}
|
420 |
|
421 |
return $query_vars;
|
432 |
*/
|
433 |
private function add_query_vars_to_find_products_with_sync_enabled( array $query_vars ) {
|
434 |
|
435 |
+
$meta_query = [
|
436 |
+
'relation' => 'OR',
|
437 |
+
[
|
438 |
+
'key' => Products::SYNC_ENABLED_META_KEY,
|
439 |
+
'value' => 'yes',
|
440 |
+
],
|
441 |
+
[
|
442 |
+
'key' => Products::SYNC_ENABLED_META_KEY,
|
443 |
+
'compare' => 'NOT EXISTS',
|
444 |
+
],
|
445 |
];
|
446 |
|
447 |
+
if ( empty( $query_vars['meta_query'] ) ) {
|
448 |
+
|
449 |
+
$query_vars['meta_query'] = $meta_query;
|
450 |
+
|
451 |
+
} elseif ( is_array( $query_vars['meta_query'] ) ) {
|
452 |
+
|
453 |
+
$original_meta_query = $query_vars['meta_query'];
|
454 |
+
$query_vars['meta_query'] = [
|
455 |
+
'relation' => 'AND',
|
456 |
+
$original_meta_query,
|
457 |
+
$meta_query,
|
458 |
+
];
|
459 |
+
}
|
460 |
+
|
461 |
// check whether the product belongs to an excluded product category or tag
|
462 |
$query_vars = $this->maybe_add_tax_query_for_excluded_taxonomies( $query_vars );
|
463 |
|
466 |
|
467 |
|
468 |
/**
|
469 |
+
* Adds a tax query to filter in/out products in excluded product categories and product tags.
|
470 |
*
|
471 |
* @since 1.10.0
|
472 |
*
|
473 |
* @param array $query_vars product query vars for the edit screen
|
474 |
+
* @param bool $in whether we want to return products in excluded categories and tags or not
|
475 |
* @return array
|
476 |
*/
|
477 |
+
private function maybe_add_tax_query_for_excluded_taxonomies( $query_vars, $in = false ) {
|
478 |
|
479 |
$integration = facebook_for_woocommerce()->get_integration();
|
480 |
|
488 |
'taxonomy' => 'product_cat',
|
489 |
'terms' => $excluded_categories_ids,
|
490 |
'field' => 'term_id',
|
491 |
+
'operator' => $in ? 'IN' : 'NOT IN',
|
492 |
];
|
493 |
}
|
494 |
|
499 |
'taxonomy' => 'product_tag',
|
500 |
'terms' => $excluded_tags_ids,
|
501 |
'field' => 'term_id',
|
502 |
+
'operator' => $in ? 'IN' : 'NOT IN',
|
503 |
];
|
504 |
}
|
505 |
|
506 |
+
if ( count( $tax_query ) > 1 ) {
|
507 |
+
$tax_query['relation'] = $in ? 'OR' : 'AND';
|
508 |
+
}
|
509 |
+
|
510 |
if ( $tax_query && empty( $query_vars['tax_query'] ) ) {
|
511 |
$query_vars['tax_query'] = $tax_query;
|
512 |
} elseif ( $tax_query && is_array( $query_vars ) ) {
|
518 |
}
|
519 |
|
520 |
|
521 |
+
/**
|
522 |
+
* Adds query vars to limit the results to visible products.
|
523 |
+
*
|
524 |
+
* @since 2.0.0
|
525 |
+
*
|
526 |
+
* @param array $query_vars
|
527 |
+
* @return array
|
528 |
+
*/
|
529 |
+
private function add_query_vars_to_find_visible_products( array $query_vars ) {
|
530 |
+
|
531 |
+
$visibility_meta_query = [
|
532 |
+
'relation' => 'OR',
|
533 |
+
[
|
534 |
+
'key' => Products::VISIBILITY_META_KEY,
|
535 |
+
'value' => 'yes',
|
536 |
+
],
|
537 |
+
[
|
538 |
+
'key' => Products::VISIBILITY_META_KEY,
|
539 |
+
'compare' => 'NOT EXISTS',
|
540 |
+
],
|
541 |
+
];
|
542 |
+
|
543 |
+
if ( empty( $query_vars['meta_query'] ) ) {
|
544 |
+
|
545 |
+
$query_vars['meta_query'] = $visibility_meta_query;
|
546 |
+
|
547 |
+
} elseif ( is_array( $query_vars['meta_query'] ) ) {
|
548 |
+
|
549 |
+
$enabled_meta_query = $query_vars['meta_query'];
|
550 |
+
$query_vars['meta_query'] = [
|
551 |
+
'relation' => 'AND',
|
552 |
+
$enabled_meta_query,
|
553 |
+
$visibility_meta_query,
|
554 |
+
];
|
555 |
+
}
|
556 |
+
|
557 |
+
return $query_vars;
|
558 |
+
}
|
559 |
+
|
560 |
+
|
561 |
+
/**
|
562 |
+
* Adds query vars to limit the results to hidden products.
|
563 |
+
*
|
564 |
+
* @since 2.0.0
|
565 |
+
*
|
566 |
+
* @param array $query_vars
|
567 |
+
* @return array
|
568 |
+
*/
|
569 |
+
private function add_query_vars_to_find_hidden_products( array $query_vars ) {
|
570 |
+
|
571 |
+
$visibility_meta_query = [
|
572 |
+
'key' => Products::VISIBILITY_META_KEY,
|
573 |
+
'value' => 'no',
|
574 |
+
];
|
575 |
+
|
576 |
+
if ( empty( $query_vars['meta_query'] ) ) {
|
577 |
+
|
578 |
+
$query_vars['meta_query'] = $visibility_meta_query;
|
579 |
+
|
580 |
+
} elseif ( is_array( $query_vars['meta_query'] ) ) {
|
581 |
+
|
582 |
+
$enabled_meta_query = $query_vars['meta_query'];
|
583 |
+
$query_vars['meta_query'] = [
|
584 |
+
'relation' => 'AND',
|
585 |
+
$enabled_meta_query,
|
586 |
+
$visibility_meta_query,
|
587 |
+
];
|
588 |
+
}
|
589 |
+
|
590 |
+
return $query_vars;
|
591 |
+
}
|
592 |
+
|
593 |
+
|
594 |
/**
|
595 |
* Adds bulk actions in the products edit screen.
|
596 |
*
|
641 |
|
642 |
if ( ! empty( $product_ids ) ) {
|
643 |
|
644 |
+
/** @var \WC_Product[] $enabling_sync_virtual_products virtual products that are being included */
|
645 |
+
$enabling_sync_virtual_products = [];
|
646 |
+
/** @var \WC_Product_Variation[] $enabling_sync_virtual_variations virtual variations that are being included */
|
647 |
+
$enabling_sync_virtual_variations = [];
|
648 |
|
649 |
foreach ( $product_ids as $product_id ) {
|
650 |
|
651 |
if ( $product = wc_get_product( $product_id ) ) {
|
652 |
|
653 |
+
$products[] = $product;
|
654 |
+
|
655 |
if ( 'facebook_include' === $action ) {
|
656 |
|
657 |
+
if ( $product->is_virtual() && ! Products::is_sync_enabled_for_product( $product ) ) {
|
658 |
|
659 |
+
$enabling_sync_virtual_products[ $product->get_id() ] = $product;
|
660 |
|
661 |
} else {
|
662 |
|
|
|
|
|
|
|
|
|
663 |
if ( $product->is_type( 'variable' ) ) {
|
664 |
|
665 |
+
// collect the virtual variations
|
666 |
foreach ( $product->get_children() as $variation_id ) {
|
667 |
|
668 |
$variation = wc_get_product( $variation_id );
|
669 |
|
670 |
+
if ( $variation && $variation->is_virtual() && ! Products::is_sync_enabled_for_product( $variation ) ) {
|
671 |
|
672 |
+
$enabling_sync_virtual_products[ $product->get_id() ] = $product;
|
673 |
+
$enabling_sync_virtual_variations[ $variation->get_id() ] = $variation;
|
674 |
}
|
675 |
}
|
676 |
}
|
677 |
}
|
|
|
|
|
|
|
|
|
678 |
}
|
679 |
}
|
680 |
}
|
681 |
|
682 |
+
if ( ! empty( $enabling_sync_virtual_products ) || ! empty( $enabling_sync_virtual_variations ) ) {
|
683 |
+
|
684 |
+
// display notice if enabling sync for virtual products or variations
|
685 |
+
set_transient( 'wc_' . facebook_for_woocommerce()->get_id() . '_enabling_virtual_products_sync_show_notice_' . get_current_user_id(), true, 15 * MINUTE_IN_SECONDS );
|
686 |
+
set_transient( 'wc_' . facebook_for_woocommerce()->get_id() . '_enabling_virtual_products_sync_affected_products_' . get_current_user_id(), array_keys( $enabling_sync_virtual_products ), 15 * MINUTE_IN_SECONDS );
|
687 |
+
|
688 |
+
// set visibility for virtual products
|
689 |
+
foreach ( $enabling_sync_virtual_products as $product ) {
|
690 |
+
|
691 |
+
// do not set visibility for variable products
|
692 |
+
if ( ! $product->is_type( 'variable' ) ) {
|
693 |
+
Products::set_product_visibility( $product, false );
|
694 |
+
}
|
695 |
+
}
|
696 |
|
697 |
+
// set visibility for virtual variations
|
698 |
+
foreach ( $enabling_sync_virtual_variations as $variation ) {
|
699 |
+
|
700 |
+
Products::set_product_visibility( $variation, false );
|
701 |
+
}
|
702 |
}
|
703 |
|
704 |
if ( 'facebook_include' === $action ) {
|
705 |
|
706 |
Products::enable_sync_for_products( $products );
|
707 |
|
708 |
+
$this->resync_products( $products );
|
|
|
|
|
|
|
709 |
|
710 |
} elseif ( 'facebook_exclude' === $action ) {
|
711 |
|
712 |
Products::disable_sync_for_products( $products );
|
713 |
+
|
714 |
+
self::add_product_disabled_sync_notice( count( $products ) );
|
715 |
}
|
716 |
}
|
717 |
}
|
721 |
|
722 |
|
723 |
/**
|
724 |
+
* Re-syncs the given products.
|
725 |
*
|
726 |
+
* @since 2.0.0
|
|
|
|
|
727 |
*
|
728 |
+
* @param \WC_Product $products
|
729 |
*/
|
730 |
+
private function resync_products( array $products ) {
|
|
|
731 |
|
732 |
+
$integration = facebook_for_woocommerce()->get_integration();
|
733 |
|
734 |
+
// re-sync each product
|
735 |
+
foreach ( $products as $product ) {
|
736 |
|
737 |
+
if ( $product->is_type( 'variable' ) ) {
|
738 |
|
739 |
+
// create product group and schedule product variations to be synced in the background
|
740 |
+
$integration->on_product_publish( $product->get_id() );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
741 |
|
742 |
+
} elseif ( $integration->product_should_be_synced( $product ) ) {
|
743 |
|
744 |
+
// schedule simple products to be updated or deleted from the catalog in the background
|
745 |
+
if ( Products::product_should_be_deleted( $product ) ) {
|
746 |
+
facebook_for_woocommerce()->get_products_sync_handler()->delete_products( [ $product->get_id() ] );
|
747 |
+
} else {
|
748 |
+
facebook_for_woocommerce()->get_products_sync_handler()->create_or_update_products( [ $product->get_id() ] );
|
749 |
+
}
|
750 |
+
}
|
751 |
+
}
|
752 |
}
|
753 |
|
754 |
|
755 |
/**
|
756 |
+
* Prints a notice on products page in case the current cart URL is not the original sync URL.
|
757 |
+
*
|
758 |
+
* TODO remove this deprecated method by version 3.0.0 or by June 2021 {FN 2020-06-09}
|
759 |
*
|
760 |
* @internal
|
761 |
*
|
762 |
+
* @since 1.10.0
|
763 |
+
* @deprecated 2.0.0
|
764 |
*/
|
765 |
+
public function validate_cart_url() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
766 |
|
767 |
+
wc_deprecated_function( __METHOD__, '2.0.0' );
|
|
|
768 |
}
|
769 |
|
770 |
|
771 |
/**
|
772 |
+
* Adds a transient so an informational notice is displayed on the next page load.
|
773 |
*
|
774 |
+
* @since 2.0.0
|
775 |
*
|
776 |
+
* @param int $count number of products
|
|
|
|
|
|
|
777 |
*/
|
778 |
+
public static function add_product_disabled_sync_notice( $count = 1 ) {
|
|
|
|
|
|
|
779 |
|
780 |
+
if ( ! facebook_for_woocommerce()->get_admin_notice_handler()->is_notice_dismissed( 'wc-' . facebook_for_woocommerce()->get_id_dasherized() . '-product-disabled-sync' ) ) {
|
781 |
+
set_transient( 'wc_' . facebook_for_woocommerce()->get_id() . '_show_product_disabled_sync_notice_' . get_current_user_id(), $count, MINUTE_IN_SECONDS );
|
782 |
}
|
783 |
}
|
784 |
|
785 |
|
786 |
/**
|
787 |
+
* Adds a message for after a product or set of products get excluded from sync.
|
788 |
*
|
789 |
+
* @since 2.0.0
|
|
|
|
|
790 |
*/
|
791 |
+
public function maybe_show_product_disabled_sync_notice() {
|
792 |
+
|
793 |
+
$transient_name = 'wc_' . facebook_for_woocommerce()->get_id() . '_show_product_disabled_sync_notice_' . get_current_user_id();
|
794 |
+
$message_id = 'wc-' . facebook_for_woocommerce()->get_id_dasherized() . '-product-disabled-sync';
|
795 |
+
|
796 |
+
if ( ( $count = get_transient( $transient_name ) ) && ( SV_WC_Helper::is_current_screen( 'edit-product' ) || SV_WC_Helper::is_current_screen( 'product' ) ) ) {
|
797 |
|
798 |
+
$message = sprintf(
|
799 |
+
/* translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s - <a> tag, %4$s - <a> tag */
|
800 |
+
_n( '%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.', '%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.', $count, 'facebook-for-woocommerce' ),
|
801 |
+
'<strong>', '</strong>',
|
802 |
+
'<a href="https://facebook.com/products" target="_blank">', '</a>'
|
803 |
+
);
|
804 |
+
|
805 |
+
$message .= '<a class="button js-wc-plugin-framework-notice-dismiss">' . esc_html__( "Don't show this notice again", 'facebook-for-woocommerce' ) . '</a>';
|
806 |
|
807 |
facebook_for_woocommerce()->get_admin_notice_handler()->add_admin_notice(
|
808 |
+
$message,
|
809 |
+
$message_id,
|
810 |
+
[
|
811 |
+
'dismissible' => false, // we add our own dismiss button
|
812 |
+
'notice_class' => 'notice-info',
|
813 |
+
]
|
|
|
|
|
|
|
|
|
814 |
);
|
815 |
+
|
816 |
+
delete_transient( $transient_name );
|
817 |
}
|
818 |
}
|
819 |
|
820 |
|
821 |
/**
|
822 |
+
* Prints a notice on products page to inform users that the virtual products selected for the Include bulk action will have sync enabled, but will be hidden.
|
823 |
*
|
824 |
* @internal
|
825 |
*
|
826 |
* @since 1.11.3-dev.2
|
827 |
*/
|
828 |
+
public function maybe_add_enabling_virtual_products_sync_notice() {
|
829 |
+
|
830 |
+
$show_notice_transient_name = 'wc_' . facebook_for_woocommerce()->get_id() . '_enabling_virtual_products_sync_show_notice_' . get_current_user_id();
|
831 |
+
$affected_products_transient_name = 'wc_' . facebook_for_woocommerce()->get_id() . '_enabling_virtual_products_sync_affected_products_' . get_current_user_id();
|
832 |
+
|
833 |
+
if ( SV_WC_Helper::is_current_screen( 'edit-product' ) && get_transient( $show_notice_transient_name ) && ( $affected_products = get_transient( $affected_products_transient_name ) ) ) {
|
834 |
+
|
835 |
+
$message = sprintf( esc_html(
|
836 |
+
/* 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 */
|
837 |
+
_n( '%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.',
|
838 |
+
'%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.',
|
839 |
+
count( $affected_products ),
|
840 |
+
'facebook-for-woocommerce' ) ),
|
841 |
+
count( $affected_products ),
|
842 |
+
'<a href="' . add_query_arg( [ 'facebook_show_affected_products' => 1 ] ) . '">',
|
843 |
+
'</a>',
|
844 |
+
'<a href="https://www.facebook.com/policies/commerce/prohibited_content/subscriptions_and_digital_products" target="_blank">',
|
845 |
+
'</a>'
|
846 |
+
);
|
847 |
|
848 |
facebook_for_woocommerce()->get_admin_notice_handler()->add_admin_notice(
|
849 |
+
$message,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
850 |
'wc-' . facebook_for_woocommerce()->get_id_dasherized() . '-enabling-virtual-products-sync',
|
851 |
+
[
|
852 |
+
'dismissible' => false,
|
853 |
+
'notice_class' => 'notice-info',
|
854 |
+
]
|
855 |
);
|
856 |
+
|
857 |
+
delete_transient( $show_notice_transient_name );
|
858 |
}
|
859 |
}
|
860 |
|
861 |
|
862 |
/**
|
863 |
+
* Tweaks the query to show a filtered view with the affected products.
|
864 |
*
|
865 |
* @internal
|
866 |
*
|
867 |
+
* @since 2.0.0
|
868 |
+
*
|
869 |
+
* @param array $query_vars product query vars for the edit screen
|
870 |
+
* @return array
|
871 |
+
*/
|
872 |
+
public function filter_virtual_products_affected_enabling_sync( $query_vars ) {
|
873 |
+
|
874 |
+
$transient_name = 'wc_' . facebook_for_woocommerce()->get_id() . '_enabling_virtual_products_sync_affected_products_' . get_current_user_id();
|
875 |
+
|
876 |
+
if ( isset( $_GET['facebook_show_affected_products'] ) && SV_WC_Helper::is_current_screen( 'edit-product' ) && $affected_products = get_transient( $transient_name ) ) {
|
877 |
+
|
878 |
+
$query_vars['post__in'] = $affected_products;
|
879 |
+
}
|
880 |
+
|
881 |
+
return $query_vars;
|
882 |
+
}
|
883 |
+
|
884 |
+
|
885 |
+
/**
|
886 |
+
* Prints a notice to inform sync mode has been automatically set to Sync and hide for virtual products and variations.
|
887 |
+
*
|
888 |
+
* @internal
|
889 |
+
*
|
890 |
+
* @since 2.0.0
|
891 |
*/
|
892 |
+
public function add_handled_virtual_products_variations_notice() {
|
893 |
|
894 |
+
if ( 'yes' === get_option( 'wc_facebook_background_handle_virtual_products_variations_complete', 'no' ) &&
|
895 |
+
'yes' !== get_option( 'wc_facebook_background_handle_virtual_products_variations_skipped', 'no' ) ) {
|
896 |
|
897 |
facebook_for_woocommerce()->get_admin_notice_handler()->add_admin_notice(
|
898 |
sprintf(
|
899 |
/* 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 */
|
900 |
+
esc_html__( '%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.', 'facebook-for-woocommerce' ),
|
901 |
'<strong>',
|
902 |
'</strong>',
|
903 |
+
'<a href="https://www.facebook.com/policies/commerce/prohibited_content/subscriptions_and_digital_products" target="_blank">',
|
904 |
'</a>'
|
905 |
),
|
906 |
+
'wc-' . facebook_for_woocommerce()->get_id_dasherized() . '-updated-virtual-products-sync',
|
907 |
+
[
|
908 |
+
'notice_class' => 'notice-info',
|
909 |
+
'always_show_on_settings' => false,
|
910 |
+
]
|
911 |
);
|
912 |
}
|
913 |
}
|
928 |
$tabs['fb_commerce_tab'] = [
|
929 |
'label' => __( 'Facebook', 'facebook-for-woocommerce' ),
|
930 |
'target' => 'facebook_options',
|
931 |
+
'class' => [ 'show_if_simple' ],
|
932 |
];
|
933 |
|
934 |
return $tabs;
|
947 |
|
948 |
// all products have sync enabled unless explicitly disabled
|
949 |
$sync_enabled = 'no' !== get_post_meta( $post->ID, Products::SYNC_ENABLED_META_KEY, true );
|
950 |
+
$is_visible = ( $visibility = get_post_meta( $post->ID, Products::VISIBILITY_META_KEY, true ) ) ? wc_string_to_bool( $visibility ) : true;
|
951 |
+
|
952 |
$description = get_post_meta( $post->ID, \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION, true );
|
953 |
$price = get_post_meta( $post->ID, \WC_Facebook_Product::FB_PRODUCT_PRICE, true );
|
954 |
$image_source = get_post_meta( $post->ID, Products::PRODUCT_IMAGE_SOURCE_META_KEY, true );
|
955 |
$image = get_post_meta( $post->ID, \WC_Facebook_Product::FB_PRODUCT_IMAGE, true );
|
956 |
|
957 |
+
if ( $sync_enabled ) {
|
958 |
+
$sync_mode = $is_visible ? self::SYNC_MODE_SYNC_AND_SHOW : self::SYNC_MODE_SYNC_AND_HIDE;
|
959 |
+
} else {
|
960 |
+
$sync_mode = self::SYNC_MODE_SYNC_DISABLED;
|
961 |
+
}
|
962 |
+
|
963 |
// 'id' attribute needs to match the 'target' parameter set above
|
964 |
?>
|
965 |
<div id='facebook_options' class='panel woocommerce_options_panel'>
|
966 |
<div class='options_group'>
|
967 |
<?php
|
968 |
|
969 |
+
woocommerce_wp_select( [
|
970 |
+
'id' => 'wc_facebook_sync_mode',
|
971 |
+
'label' => __( 'Facebook sync', 'facebook-for-woocommerce' ),
|
972 |
+
'options' => [
|
973 |
+
self::SYNC_MODE_SYNC_AND_SHOW => __( 'Sync and show in catalog', 'facebook-for-woocommerce' ),
|
974 |
+
self::SYNC_MODE_SYNC_AND_HIDE => __( 'Sync and hide in catalog', 'facebook-for-woocommerce' ),
|
975 |
+
self::SYNC_MODE_SYNC_DISABLED => __( 'Do not sync', 'facebook-for-woocommerce' ),
|
976 |
+
],
|
977 |
+
'value' => $sync_mode,
|
978 |
] );
|
979 |
|
980 |
woocommerce_wp_textarea_input( [
|
985 |
'cols' => 40,
|
986 |
'rows' => 20,
|
987 |
'value' => $description,
|
988 |
+
'class' => 'short enable-if-sync-enabled',
|
989 |
] );
|
990 |
|
991 |
woocommerce_wp_radio( [
|
1056 |
return;
|
1057 |
}
|
1058 |
|
1059 |
+
$sync_enabled = 'no' !== $this->get_product_variation_meta( $variation, Products::SYNC_ENABLED_META_KEY, $parent );
|
1060 |
+
$is_visible = ( $visibility = $this->get_product_variation_meta( $variation, Products::VISIBILITY_META_KEY, $parent ) ) ? wc_string_to_bool( $visibility ) : true;
|
1061 |
+
|
1062 |
$description = $this->get_product_variation_meta( $variation, \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION, $parent );
|
1063 |
$price = $this->get_product_variation_meta( $variation, \WC_Facebook_Product::FB_PRODUCT_PRICE, $parent );
|
1064 |
$image_url = $this->get_product_variation_meta( $variation, \WC_Facebook_Product::FB_PRODUCT_IMAGE, $parent );
|
1065 |
$image_source = $variation->get_meta( Products::PRODUCT_IMAGE_SOURCE_META_KEY );
|
1066 |
|
1067 |
+
if ( $sync_enabled ) {
|
1068 |
+
$sync_mode = $is_visible ? self::SYNC_MODE_SYNC_AND_SHOW : self::SYNC_MODE_SYNC_AND_HIDE;
|
1069 |
+
} else {
|
1070 |
+
$sync_mode = self::SYNC_MODE_SYNC_DISABLED;
|
1071 |
+
}
|
1072 |
+
|
1073 |
+
woocommerce_wp_select( [
|
1074 |
+
'id' => "variable_facebook_sync_mode$index",
|
1075 |
+
'name' => "variable_facebook_sync_mode[$index]",
|
1076 |
+
'label' => __( 'Facebook sync', 'facebook-for-woocommerce' ),
|
1077 |
+
'options' => [
|
1078 |
+
self::SYNC_MODE_SYNC_AND_SHOW => __( 'Sync and show in catalog', 'facebook-for-woocommerce' ),
|
1079 |
+
self::SYNC_MODE_SYNC_AND_HIDE => __( 'Sync and hide in catalog', 'facebook-for-woocommerce' ),
|
1080 |
+
self::SYNC_MODE_SYNC_DISABLED => __( 'Do not sync', 'facebook-for-woocommerce' ),
|
1081 |
+
],
|
1082 |
+
'value' => $sync_mode,
|
1083 |
+
'class' => 'js-variable-fb-sync-toggle',
|
1084 |
+
'wrapper_class' => 'form-row form-row-full',
|
1085 |
] );
|
1086 |
|
1087 |
woocommerce_wp_textarea_input( [
|
1094 |
'rows' => 5,
|
1095 |
'value' => $description,
|
1096 |
'class' => 'enable-if-sync-enabled',
|
1097 |
+
'wrapper_class' => 'form-row form-row-full',
|
1098 |
] );
|
1099 |
|
1100 |
woocommerce_wp_radio( [
|
1110 |
],
|
1111 |
'value' => $image_source ?: Products::PRODUCT_IMAGE_SOURCE_PRODUCT,
|
1112 |
'class' => 'enable-if-sync-enabled js-fb-product-image-source',
|
1113 |
+
'wrapper_class' => 'fb-product-image-source-field',
|
1114 |
] );
|
1115 |
|
1116 |
woocommerce_wp_text_input( [
|
1119 |
'label' => __( 'Custom Image URL', 'facebook-for-woocommerce' ),
|
1120 |
'value' => $image_url,
|
1121 |
'class' => sprintf( 'enable-if-sync-enabled product-image-source-field show-if-product-image-source-%s', Products::PRODUCT_IMAGE_SOURCE_CUSTOM ),
|
1122 |
+
'wrapper_class' => 'form-row form-row-full',
|
1123 |
] );
|
1124 |
|
1125 |
woocommerce_wp_text_input( [
|
1134 |
'description' => __( '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.', 'facebook-for-woocommerce' ),
|
1135 |
'value' => wc_format_decimal( $price ),
|
1136 |
'class' => 'enable-if-sync-enabled',
|
1137 |
+
'wrapper_class' => 'form-row form-full',
|
1138 |
] );
|
1139 |
}
|
1140 |
|
1181 |
return;
|
1182 |
}
|
1183 |
|
1184 |
+
$sync_mode = isset( $_POST['variable_facebook_sync_mode'][ $index ] ) ? $_POST['variable_facebook_sync_mode'][ $index ] : self::SYNC_MODE_SYNC_DISABLED;
|
1185 |
+
$sync_enabled = self::SYNC_MODE_SYNC_DISABLED !== $sync_mode;
|
1186 |
+
|
1187 |
+
if ( self::SYNC_MODE_SYNC_AND_SHOW === $sync_mode && $variation->is_virtual() ) {
|
1188 |
+
// force to Sync and hide
|
1189 |
+
$sync_mode = self::SYNC_MODE_SYNC_AND_HIDE;
|
1190 |
+
}
|
1191 |
+
|
1192 |
// phpcs:disable WordPress.Security.NonceVerification.Missing
|
1193 |
+
if ( $sync_enabled ) {
|
1194 |
|
1195 |
Products::enable_sync_for_products( [ $variation ] );
|
1196 |
+
Products::set_product_visibility( $variation, self::SYNC_MODE_SYNC_AND_HIDE !== $sync_mode );
|
1197 |
|
1198 |
$posted_param = 'variable_' . \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION;
|
1199 |
$description = isset( $_POST[ $posted_param ][ $index ] ) ? sanitize_text_field( wp_unslash( $_POST[ $posted_param ][ $index ] ) ) : null;
|
1233 |
global $current_screen;
|
1234 |
|
1235 |
// bail if not on the products, product edit, or settings screen
|
1236 |
+
if ( ! $current_screen || ! in_array( $current_screen->id, [ 'edit-product', 'product', 'woocommerce_page_wc-facebook' ], true ) ) {
|
1237 |
return;
|
1238 |
}
|
1239 |
|
1323 |
}
|
1324 |
|
1325 |
|
1326 |
+
/** Deprecated methods ********************************************************************************************/
|
1327 |
+
|
1328 |
+
|
1329 |
+
/**
|
1330 |
+
* No-op: Prints a notice on products page to inform users about changes in product sync.
|
1331 |
+
*
|
1332 |
+
* @internal
|
1333 |
+
*
|
1334 |
+
* @since 1.11.0
|
1335 |
+
* @deprecated 2.0.0
|
1336 |
+
*/
|
1337 |
+
public function add_product_sync_delay_notice() {
|
1338 |
+
|
1339 |
+
wc_deprecated_function( __METHOD__, '2.0.0' );
|
1340 |
+
}
|
1341 |
+
|
1342 |
+
|
1343 |
+
/**
|
1344 |
+
* No-op: Handles dismissed notices.
|
1345 |
+
*
|
1346 |
+
* @internal
|
1347 |
+
*
|
1348 |
+
* @since 1.11.0
|
1349 |
+
* @deprecated 2.0.0
|
1350 |
+
*
|
1351 |
+
* @param string $message_id the dismissed notice ID
|
1352 |
+
* @param int $user_id the ID of the user the noticed was dismissed for
|
1353 |
+
*/
|
1354 |
+
public function handle_dismiss_notice( $message_id, $user_id = null ) {
|
1355 |
+
|
1356 |
+
wc_deprecated_function( __METHOD__, '2.0.0' );
|
1357 |
+
}
|
1358 |
+
|
1359 |
+
|
1360 |
+
/**
|
1361 |
+
* No-op: Prints a notice on products page to inform users that catalog visibility settings were removed.
|
1362 |
+
*
|
1363 |
+
* @internal
|
1364 |
+
*
|
1365 |
+
* @since 1.11.0
|
1366 |
+
* @deprecated 2.0.0
|
1367 |
+
*/
|
1368 |
+
public function add_catalog_visibility_settings_removed_notice() {
|
1369 |
+
|
1370 |
+
wc_deprecated_function( __METHOD__, '2.0.0' );
|
1371 |
+
}
|
1372 |
+
|
1373 |
+
|
1374 |
}
|
includes/Admin/Abstract_Settings_Screen.php
ADDED
@@ -0,0 +1,192 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\Admin;
|
12 |
+
|
13 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4\SV_WC_Plugin_Exception;
|
14 |
+
|
15 |
+
defined( 'ABSPATH' ) or exit;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* The base settings screen object.
|
19 |
+
*/
|
20 |
+
abstract class Abstract_Settings_Screen {
|
21 |
+
|
22 |
+
|
23 |
+
/** @var string screen ID */
|
24 |
+
protected $id;
|
25 |
+
|
26 |
+
/** @var string screen label, for display */
|
27 |
+
protected $label;
|
28 |
+
|
29 |
+
/** @var string screen title, for display */
|
30 |
+
protected $title;
|
31 |
+
|
32 |
+
/** @var string screen description, for display */
|
33 |
+
protected $description;
|
34 |
+
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Renders the screen.
|
38 |
+
*
|
39 |
+
* @since 2.0.0
|
40 |
+
*/
|
41 |
+
public function render() {
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Filters the screen settings.
|
45 |
+
*
|
46 |
+
* @since 2.0.0
|
47 |
+
*
|
48 |
+
* @param array $settings settings
|
49 |
+
*/
|
50 |
+
$settings = (array) apply_filters( 'wc_facebook_admin_' . $this->get_id() . '_settings', $this->get_settings(), $this );
|
51 |
+
|
52 |
+
if ( empty( $settings ) ) {
|
53 |
+
return;
|
54 |
+
}
|
55 |
+
|
56 |
+
$connection_handler = facebook_for_woocommerce()->get_connection_handler();
|
57 |
+
$is_connected = $connection_handler->is_connected();
|
58 |
+
|
59 |
+
?>
|
60 |
+
|
61 |
+
<?php if ( ! $is_connected && ! $connection_handler->has_previously_connected_fbe_1() && $this->get_disconnected_message() ) : ?>
|
62 |
+
<div class="notice notice-info"><p><?php echo wp_kses_post( $this->get_disconnected_message() ); ?></p></div>
|
63 |
+
<?php endif; ?>
|
64 |
+
|
65 |
+
<form class="wc-facebook-settings <?php echo $is_connected ? 'connected' : 'disconnected'; ?>" method="post" id="mainform" action="" enctype="multipart/form-data">
|
66 |
+
|
67 |
+
<?php woocommerce_admin_fields( $settings ); ?>
|
68 |
+
|
69 |
+
<?php if ( $is_connected ) : ?>
|
70 |
+
<input type="hidden" name="screen_id" value="<?php echo esc_attr( $this->get_id() ); ?>">
|
71 |
+
<?php wp_nonce_field( 'wc_facebook_admin_save_' . $this->get_id() . '_settings' ); ?>
|
72 |
+
<?php submit_button( __( 'Save changes', 'facebook-for-woocommerce' ), 'primary', 'save_' . $this->get_id() . '_settings' ); ?>
|
73 |
+
<?php endif; ?>
|
74 |
+
|
75 |
+
</form>
|
76 |
+
|
77 |
+
<?php
|
78 |
+
}
|
79 |
+
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Saves the settings.
|
83 |
+
*
|
84 |
+
* @since 2.0.0
|
85 |
+
*
|
86 |
+
* @throws SV_WC_Plugin_Exception
|
87 |
+
*/
|
88 |
+
public function save() {
|
89 |
+
|
90 |
+
woocommerce_update_options( $this->get_settings() );
|
91 |
+
}
|
92 |
+
|
93 |
+
|
94 |
+
/** Getter methods ************************************************************************************************/
|
95 |
+
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Gets the settings.
|
99 |
+
*
|
100 |
+
* Should return a multi-dimensional array of settings in the format expected by \WC_Admin_Settings
|
101 |
+
* @return array
|
102 |
+
*/
|
103 |
+
abstract public function get_settings();
|
104 |
+
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Gets the message to display when the plugin is disconnected.
|
108 |
+
*
|
109 |
+
* @since 2.0.0
|
110 |
+
*
|
111 |
+
* @return string
|
112 |
+
*/
|
113 |
+
public function get_disconnected_message() {
|
114 |
+
|
115 |
+
return '';
|
116 |
+
}
|
117 |
+
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Gets the screen ID.
|
121 |
+
*
|
122 |
+
* @since 2.0.0
|
123 |
+
*
|
124 |
+
* @return string
|
125 |
+
*/
|
126 |
+
public function get_id() {
|
127 |
+
|
128 |
+
return $this->id;
|
129 |
+
}
|
130 |
+
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Gets the screen label.
|
134 |
+
*
|
135 |
+
* @since 2.0.0
|
136 |
+
*
|
137 |
+
* @return string
|
138 |
+
*/
|
139 |
+
public function get_label() {
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Filters the screen label.
|
143 |
+
*
|
144 |
+
* @since 2.0.0
|
145 |
+
*
|
146 |
+
* @param string $label screen label, for display
|
147 |
+
*/
|
148 |
+
return (string) apply_filters( 'wc_facebook_admin_settings_' . $this->get_id() . '_screen_label', $this->label, $this );
|
149 |
+
}
|
150 |
+
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Gets the screen title.
|
154 |
+
*
|
155 |
+
* @since 2.0.0
|
156 |
+
*
|
157 |
+
* @return string
|
158 |
+
*/
|
159 |
+
public function get_title() {
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Filters the screen title.
|
163 |
+
*
|
164 |
+
* @since 2.0.0
|
165 |
+
*
|
166 |
+
* @param string $title screen title, for display
|
167 |
+
*/
|
168 |
+
return (string) apply_filters( 'wc_facebook_admin_settings_' . $this->get_id() . '_screen_title', $this->title, $this );
|
169 |
+
}
|
170 |
+
|
171 |
+
|
172 |
+
/**
|
173 |
+
* Gets the screen description.
|
174 |
+
*
|
175 |
+
* @since 2.0.0
|
176 |
+
*
|
177 |
+
* @return string
|
178 |
+
*/
|
179 |
+
public function get_description() {
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Filters the screen description.
|
183 |
+
*
|
184 |
+
* @since 2.0.0
|
185 |
+
*
|
186 |
+
* @param string $description screen description, for display
|
187 |
+
*/
|
188 |
+
return (string) apply_filters( 'wc_facebook_admin_settings_' . $this->get_id() . '_screen_description', $this->description, $this );
|
189 |
+
}
|
190 |
+
|
191 |
+
|
192 |
+
}
|
includes/Admin/Settings.php
ADDED
@@ -0,0 +1,224 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\Admin;
|
12 |
+
|
13 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4\SV_WC_Helper;
|
14 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4\SV_WC_Plugin_Exception;
|
15 |
+
|
16 |
+
defined( 'ABSPATH' ) or exit;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Admin settings handler.
|
20 |
+
*
|
21 |
+
* @since 2.0.0
|
22 |
+
*/
|
23 |
+
class Settings {
|
24 |
+
|
25 |
+
|
26 |
+
/** @var string base settings page ID */
|
27 |
+
const PAGE_ID = 'wc-facebook';
|
28 |
+
|
29 |
+
|
30 |
+
/** @var Abstract_Settings_Screen[] */
|
31 |
+
private $screens;
|
32 |
+
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Settings constructor.
|
36 |
+
*
|
37 |
+
* @since 2.0.0
|
38 |
+
*/
|
39 |
+
public function __construct() {
|
40 |
+
|
41 |
+
$this->screens = [
|
42 |
+
Settings_Screens\Connection::ID => new Settings_Screens\Connection(),
|
43 |
+
Settings_Screens\Product_Sync::ID => new Settings_Screens\Product_Sync(),
|
44 |
+
Settings_Screens\Messenger::ID => new Settings_Screens\Messenger(),
|
45 |
+
];
|
46 |
+
|
47 |
+
add_action( 'admin_menu', [ $this, 'add_menu_item' ] );
|
48 |
+
|
49 |
+
add_action( 'wp_loaded', [ $this, 'save' ] );
|
50 |
+
}
|
51 |
+
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Adds the Facebook menu item.
|
55 |
+
*
|
56 |
+
* @since 2.0.0
|
57 |
+
*/
|
58 |
+
public function add_menu_item() {
|
59 |
+
|
60 |
+
add_submenu_page( 'woocommerce', __( 'Facebook for WooCommerce', 'facebook-for-woocommerce' ), __( 'Facebook', 'facebook-for-woocommerce' ), 'manage_woocommerce', self::PAGE_ID, [ $this, 'render' ], 5 );
|
61 |
+
}
|
62 |
+
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Renders the settings page.
|
66 |
+
*
|
67 |
+
* @since 2.0.0
|
68 |
+
*/
|
69 |
+
public function render() {
|
70 |
+
|
71 |
+
$tabs = $this->get_tabs();
|
72 |
+
$current_tab = SV_WC_Helper::get_requested_value( 'tab' );
|
73 |
+
|
74 |
+
if ( ! $current_tab ) {
|
75 |
+
$current_tab = current( array_keys( $tabs ) );
|
76 |
+
}
|
77 |
+
|
78 |
+
$screen = $this->get_screen( $current_tab );
|
79 |
+
|
80 |
+
?>
|
81 |
+
|
82 |
+
<div class="wrap woocommerce">
|
83 |
+
|
84 |
+
<nav class="nav-tab-wrapper woo-nav-tab-wrapper">
|
85 |
+
|
86 |
+
<?php foreach ( $tabs as $id => $label ) : ?>
|
87 |
+
<a href="<?php echo esc_html( admin_url( 'admin.php?page=' . self::PAGE_ID . '&tab=' . esc_attr( $id ) ) ); ?>" class="nav-tab <?php echo $current_tab === $id ? 'nav-tab-active' : ''; ?>"><?php echo esc_html( $label ); ?></a>
|
88 |
+
<?php endforeach; ?>
|
89 |
+
|
90 |
+
</nav>
|
91 |
+
|
92 |
+
<?php facebook_for_woocommerce()->get_message_handler()->show_messages(); ?>
|
93 |
+
|
94 |
+
<?php if ( $screen ) : ?>
|
95 |
+
|
96 |
+
<h1 class="screen-reader-text"><?php echo esc_html( $screen->get_title() ); ?></h1>
|
97 |
+
<p><?php echo wp_kses_post( $screen->get_description() ); ?></p>
|
98 |
+
|
99 |
+
<?php $screen->render(); ?>
|
100 |
+
|
101 |
+
<?php endif; ?>
|
102 |
+
|
103 |
+
</div>
|
104 |
+
|
105 |
+
<?php
|
106 |
+
}
|
107 |
+
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Saves the settings page.
|
111 |
+
*
|
112 |
+
* @since 2.0.0
|
113 |
+
*/
|
114 |
+
public function save() {
|
115 |
+
|
116 |
+
if ( ! is_admin() || SV_WC_Helper::get_requested_value( 'page' ) !== self::PAGE_ID ) {
|
117 |
+
return;
|
118 |
+
}
|
119 |
+
|
120 |
+
$screen = $this->get_screen( SV_WC_Helper::get_posted_value( 'screen_id' ) );
|
121 |
+
|
122 |
+
if ( ! $screen ) {
|
123 |
+
return;
|
124 |
+
}
|
125 |
+
|
126 |
+
if ( ! SV_WC_Helper::get_posted_value( 'save_' . $screen->get_id() . '_settings' ) ) {
|
127 |
+
return;
|
128 |
+
}
|
129 |
+
|
130 |
+
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
131 |
+
wp_die( __( 'You do not have permission to save these settings.', 'facebook-for-woocommerce' ) );
|
132 |
+
}
|
133 |
+
|
134 |
+
check_admin_referer( 'wc_facebook_admin_save_' . $screen->get_id() . '_settings' );
|
135 |
+
|
136 |
+
try {
|
137 |
+
|
138 |
+
$screen->save();
|
139 |
+
|
140 |
+
facebook_for_woocommerce()->get_message_handler()->add_message( __( 'Your settings have been saved.', 'facebook-for-woocommerce' ) );
|
141 |
+
|
142 |
+
} catch ( SV_WC_Plugin_Exception $exception ) {
|
143 |
+
|
144 |
+
facebook_for_woocommerce()->get_message_handler()->add_error( sprintf(
|
145 |
+
/* translators: Placeholders: %s - user-friendly error message */
|
146 |
+
__( 'Your settings could not be saved. %s', 'facebook-for-woocommerce' ),
|
147 |
+
$exception->getMessage()
|
148 |
+
) );
|
149 |
+
}
|
150 |
+
}
|
151 |
+
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Gets a settings screen object based on ID.
|
155 |
+
*
|
156 |
+
* @since 2.0.0
|
157 |
+
*
|
158 |
+
* @param string $screen_id desired screen ID
|
159 |
+
* @return Abstract_Settings_Screen|null
|
160 |
+
*/
|
161 |
+
public function get_screen( $screen_id ) {
|
162 |
+
|
163 |
+
$screens = $this->get_screens();
|
164 |
+
|
165 |
+
return ! empty( $screens[ $screen_id ] ) && $screens[ $screen_id ] instanceof Abstract_Settings_Screen ? $screens[ $screen_id ] : null;
|
166 |
+
}
|
167 |
+
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Gets the available screens.
|
171 |
+
*
|
172 |
+
* @since 2.0.0
|
173 |
+
*
|
174 |
+
* @return Abstract_Settings_Screen[]
|
175 |
+
*/
|
176 |
+
public function get_screens() {
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Filters the admin settings screens.
|
180 |
+
*
|
181 |
+
* @since 2.0.0
|
182 |
+
*
|
183 |
+
* @param array $screens available screen objects
|
184 |
+
*/
|
185 |
+
$screens = (array) apply_filters( 'wc_facebook_admin_settings_screens', $this->screens, $this );
|
186 |
+
|
187 |
+
// ensure no bogus values are added via filter
|
188 |
+
$screens = array_filter( $screens, function( $value ) {
|
189 |
+
|
190 |
+
return $value instanceof Abstract_Settings_Screen;
|
191 |
+
|
192 |
+
} );
|
193 |
+
|
194 |
+
return $screens;
|
195 |
+
}
|
196 |
+
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Gets the tabs.
|
200 |
+
*
|
201 |
+
* @since 2.0.0
|
202 |
+
*
|
203 |
+
* @return array
|
204 |
+
*/
|
205 |
+
public function get_tabs() {
|
206 |
+
|
207 |
+
$tabs = [];
|
208 |
+
|
209 |
+
foreach ( $this->get_screens() as $screen_id => $screen ) {
|
210 |
+
$tabs[ $screen_id ] = $screen->get_label();
|
211 |
+
}
|
212 |
+
|
213 |
+
/**
|
214 |
+
* Filters the admin settings tabs.
|
215 |
+
*
|
216 |
+
* @since 2.0.0
|
217 |
+
*
|
218 |
+
* @param array $tabs tab data, as $id => $label
|
219 |
+
*/
|
220 |
+
return (array) apply_filters( 'wc_facebook_admin_settings_tabs', $tabs, $this );
|
221 |
+
}
|
222 |
+
|
223 |
+
|
224 |
+
}
|
includes/Admin/Settings_Screens/Connection.php
ADDED
@@ -0,0 +1,371 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\Admin\Settings_Screens;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\Admin;
|
16 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4\SV_WC_API_Exception;
|
17 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4\SV_WC_Helper;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* The Connection settings screen object.
|
21 |
+
*/
|
22 |
+
class Connection extends Admin\Abstract_Settings_Screen {
|
23 |
+
|
24 |
+
|
25 |
+
/** @var string screen ID */
|
26 |
+
const ID = 'connection';
|
27 |
+
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Connection constructor.
|
31 |
+
*/
|
32 |
+
public function __construct() {
|
33 |
+
|
34 |
+
$this->id = self::ID;
|
35 |
+
$this->label = __( 'Connection', 'facebook-for-woocommerce' );
|
36 |
+
$this->title = __( 'Connection', 'facebook-for-woocommerce' );
|
37 |
+
|
38 |
+
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
|
39 |
+
|
40 |
+
add_action( 'admin_notices', [ $this, 'add_notices' ] );
|
41 |
+
}
|
42 |
+
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Adds admin notices.
|
46 |
+
*
|
47 |
+
* @internal
|
48 |
+
*
|
49 |
+
* @since 2.0.0
|
50 |
+
*/
|
51 |
+
public function add_notices() {
|
52 |
+
|
53 |
+
// display a notice if the connection has previously failed
|
54 |
+
if ( get_transient( 'wc_facebook_connection_failed' ) ) {
|
55 |
+
|
56 |
+
$message = sprintf(
|
57 |
+
/* translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s - <a> tag, %4$s - </a> tag, %5$s - <a> tag, %6$s - </a> tag */
|
58 |
+
__( '%1$sHeads up!%2$s It looks like there was a problem with reconnecting your site to Facebook. Please %3$sclick here%4$s to try again, or %5$sget in touch with our support team%6$s for assistance.', 'facebook-for-woocommerce' ),
|
59 |
+
'<strong>', '</strong>',
|
60 |
+
'<a href="' . esc_url( facebook_for_woocommerce()->get_connection_handler()->get_connect_url() ) . '">', '</a>',
|
61 |
+
'<a href="' . esc_url( facebook_for_woocommerce()->get_support_url() ) . '" target="_blank">', '</a>'
|
62 |
+
);
|
63 |
+
|
64 |
+
facebook_for_woocommerce()->get_admin_notice_handler()->add_admin_notice( $message, 'wc_facebook_connection_failed', [
|
65 |
+
'notice_class' => 'error',
|
66 |
+
] );
|
67 |
+
|
68 |
+
delete_transient( 'wc_facebook_connection_failed' );
|
69 |
+
}
|
70 |
+
}
|
71 |
+
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Enqueue the assets.
|
75 |
+
*
|
76 |
+
* @internal
|
77 |
+
*
|
78 |
+
* @since 2.0.0
|
79 |
+
*/
|
80 |
+
public function enqueue_assets() {
|
81 |
+
|
82 |
+
$tab = SV_WC_Helper::get_requested_value( 'tab' );
|
83 |
+
|
84 |
+
if ( Admin\Settings::PAGE_ID !== SV_WC_Helper::get_requested_value( 'page' ) || ( $tab && $this->get_id() !== SV_WC_Helper::get_requested_value( 'tab' ) ) ) {
|
85 |
+
return;
|
86 |
+
}
|
87 |
+
|
88 |
+
wp_enqueue_style( 'wc-facebook-admin-connection-settings', facebook_for_woocommerce()->get_plugin_url() . '/assets/css/admin/facebook-for-woocommerce-connection.css', [], \WC_Facebookcommerce::VERSION );
|
89 |
+
}
|
90 |
+
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Renders the screen.
|
94 |
+
*
|
95 |
+
* @since 2.0.0
|
96 |
+
*/
|
97 |
+
public function render() {
|
98 |
+
|
99 |
+
$is_connected = facebook_for_woocommerce()->get_connection_handler()->is_connected();
|
100 |
+
|
101 |
+
// always render the CTA box
|
102 |
+
$this->render_facebook_box( $is_connected );
|
103 |
+
|
104 |
+
// don't proceed further if not connected
|
105 |
+
if ( ! $is_connected ) {
|
106 |
+
return;
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Build the basic static elements.
|
111 |
+
*
|
112 |
+
* At a minimum, we display their raw ID. If they have an API resource, we replace that ID with whatever data
|
113 |
+
* we can get our hands on, with an external link if possible. Current abilities:
|
114 |
+
*
|
115 |
+
* + Page: just the ID
|
116 |
+
* + Pixel: just the ID
|
117 |
+
* + Catalog: name, full URL
|
118 |
+
* + Business manager: name, full URL
|
119 |
+
* + Ad account: not currently available
|
120 |
+
*
|
121 |
+
* TODO: add pixel & ad account API retrieval when we gain the ads_management permission
|
122 |
+
* TODO: add the page name and link when we gain the manage_pages permission
|
123 |
+
*/
|
124 |
+
$static_items = [
|
125 |
+
'page' => [
|
126 |
+
'label' => __( 'Page', 'facebook-for-woocommerce' ),
|
127 |
+
'value' => facebook_for_woocommerce()->get_integration()->get_facebook_page_id(),
|
128 |
+
],
|
129 |
+
'pixel' => [
|
130 |
+
'label' => __( 'Pixel', 'facebook-for-woocommerce' ),
|
131 |
+
'value' => facebook_for_woocommerce()->get_integration()->get_facebook_pixel_id(),
|
132 |
+
],
|
133 |
+
'catalog' => [
|
134 |
+
'label' => __( 'Catalog', 'facebook-for-woocommerce' ),
|
135 |
+
'value' => facebook_for_woocommerce()->get_integration()->get_product_catalog_id(),
|
136 |
+
'url' => 'https://facebook.com/products',
|
137 |
+
],
|
138 |
+
'business-manager' => [
|
139 |
+
'label' => __( 'Business Manager account', 'facebook-for-woocommerce' ),
|
140 |
+
'value' => facebook_for_woocommerce()->get_connection_handler()->get_business_manager_id(),
|
141 |
+
],
|
142 |
+
'ad-account' => [
|
143 |
+
'label' => __( 'Ad Manager account', 'facebook-for-woocommerce' ),
|
144 |
+
'value' => facebook_for_woocommerce()->get_connection_handler()->get_ad_account_id(),
|
145 |
+
],
|
146 |
+
];
|
147 |
+
|
148 |
+
// if the catalog ID is set, update the URL and try to get its name for display
|
149 |
+
if ( $catalog_id = $static_items['catalog']['value'] ) {
|
150 |
+
|
151 |
+
$static_items['catalog']['url'] = "https://facebook.com/products/catalogs/{$catalog_id}";
|
152 |
+
|
153 |
+
try {
|
154 |
+
|
155 |
+
$response = facebook_for_woocommerce()->get_api()->get_catalog( $catalog_id );
|
156 |
+
|
157 |
+
if ( $name = $response->get_name() ) {
|
158 |
+
$static_items['catalog']['value'] = $name;
|
159 |
+
}
|
160 |
+
|
161 |
+
} catch ( SV_WC_API_Exception $exception ) {}
|
162 |
+
}
|
163 |
+
|
164 |
+
// if the business manager ID is set, try and get its name for display
|
165 |
+
if ( $static_items['business-manager']['value'] ) {
|
166 |
+
|
167 |
+
try {
|
168 |
+
|
169 |
+
$response = facebook_for_woocommerce()->get_api()->get_business_manager( $static_items['business-manager']['value'] );
|
170 |
+
|
171 |
+
if ( $name = $response->get_name() ) {
|
172 |
+
$static_items['business-manager']['value'] = $name;
|
173 |
+
}
|
174 |
+
|
175 |
+
if ( $url = $response->get_url() ) {
|
176 |
+
$static_items['business-manager']['url'] = $url;
|
177 |
+
}
|
178 |
+
|
179 |
+
} catch ( SV_WC_API_Exception $exception ) {}
|
180 |
+
}
|
181 |
+
|
182 |
+
?>
|
183 |
+
|
184 |
+
<table class="form-table">
|
185 |
+
<tbody>
|
186 |
+
|
187 |
+
<?php foreach ( $static_items as $id => $item ) :
|
188 |
+
|
189 |
+
$item = wp_parse_args( $item, [
|
190 |
+
'label' => '',
|
191 |
+
'value' => '',
|
192 |
+
'url' => '',
|
193 |
+
] );
|
194 |
+
|
195 |
+
?>
|
196 |
+
|
197 |
+
<tr valign="top" class="wc-facebook-connected-<?php echo esc_attr( $id ); ?>">
|
198 |
+
|
199 |
+
<th scope="row" class="titledesc">
|
200 |
+
<?php echo esc_html( $item['label'] ); ?>
|
201 |
+
</th>
|
202 |
+
|
203 |
+
<td class="forminp">
|
204 |
+
|
205 |
+
<?php if ( $item['url'] ) : ?>
|
206 |
+
|
207 |
+
<a href="<?php echo esc_url( $item['url'] ); ?>" target="_blank">
|
208 |
+
|
209 |
+
<?php echo esc_html( $item['value'] ); ?>
|
210 |
+
|
211 |
+
<span
|
212 |
+
class="dashicons dashicons-external"
|
213 |
+
style="margin-right: 8px; vertical-align: bottom; text-decoration: none;"
|
214 |
+
></span>
|
215 |
+
|
216 |
+
</a>
|
217 |
+
|
218 |
+
<?php elseif ( is_numeric( $item['value'] ) ) : ?>
|
219 |
+
|
220 |
+
<code><?php echo esc_html( $item['value'] ); ?></code>
|
221 |
+
|
222 |
+
<?php elseif ( ! empty( $item['value'] ) ) : ?>
|
223 |
+
|
224 |
+
<?php echo esc_html( $item['value'] ); ?>
|
225 |
+
|
226 |
+
<?php else : ?>
|
227 |
+
|
228 |
+
<?php echo '-' ?>
|
229 |
+
|
230 |
+
<?php endif; ?>
|
231 |
+
|
232 |
+
</td>
|
233 |
+
</tr>
|
234 |
+
|
235 |
+
<?php endforeach; ?>
|
236 |
+
|
237 |
+
</tbody>
|
238 |
+
</table>
|
239 |
+
|
240 |
+
<?php
|
241 |
+
|
242 |
+
parent::render();
|
243 |
+
}
|
244 |
+
|
245 |
+
|
246 |
+
/**
|
247 |
+
* Renders the Facebook CTA box.
|
248 |
+
*
|
249 |
+
* @since 2.0.0
|
250 |
+
*
|
251 |
+
* @param bool $is_connected whether the plugin is connected
|
252 |
+
*/
|
253 |
+
private function render_facebook_box( $is_connected ) {
|
254 |
+
|
255 |
+
if ( $is_connected ) {
|
256 |
+
$title = __( 'Reach the Right People and Sell More Online', 'facebook-for-woocommerce' );
|
257 |
+
} else {
|
258 |
+
$title = __( 'Grow your business on Facebook', 'facebook-for-woocommerce' );
|
259 |
+
}
|
260 |
+
|
261 |
+
$subtitle = __( 'Use this WooCommerce and Facebook integration to:', 'facebook-for-woocommerce' );
|
262 |
+
|
263 |
+
$benefits = [
|
264 |
+
__( 'Create an ad in a few steps', 'facebook-for-woocommerce'),
|
265 |
+
__( 'Use built-in best practices for online sales', 'facebook-for-woocommerce'),
|
266 |
+
__( 'Get reporting on sales and revenue', 'facebook-for-woocommerce'),
|
267 |
+
];
|
268 |
+
|
269 |
+
if ( $is_connected ) {
|
270 |
+
|
271 |
+
$actions = [
|
272 |
+
'create-ad' => [
|
273 |
+
'label' => __( 'Create Ad', 'facebook-for-woocommerce' ),
|
274 |
+
'type' => 'primary',
|
275 |
+
'url' => 'https://www.facebook.com/ad_center/create/ad/?entry_point=facebook_ads_extension&page_id=' . facebook_for_woocommerce()->get_integration()->get_facebook_page_id(),
|
276 |
+
],
|
277 |
+
'manage' => [
|
278 |
+
'label' => __( 'Manage Connection', 'facebook-for-woocommerce' ),
|
279 |
+
'type' => 'secondary',
|
280 |
+
'url' => facebook_for_woocommerce()->get_connection_handler()->get_manage_url(),
|
281 |
+
],
|
282 |
+
];
|
283 |
+
|
284 |
+
} else {
|
285 |
+
|
286 |
+
$actions = [
|
287 |
+
'get-started' => [
|
288 |
+
'label' => __( 'Get Started', 'facebook-for-woocommerce' ),
|
289 |
+
'type' => 'primary',
|
290 |
+
'url' => facebook_for_woocommerce()->get_connection_handler()->get_connect_url(),
|
291 |
+
],
|
292 |
+
];
|
293 |
+
}
|
294 |
+
|
295 |
+
?>
|
296 |
+
|
297 |
+
<div id="wc-facebook-connection-box">
|
298 |
+
|
299 |
+
<div class="logo"></div>
|
300 |
+
|
301 |
+
<h1><?php echo esc_html( $title ); ?></h1>
|
302 |
+
<h2><?php echo esc_html( $subtitle ); ?></h2>
|
303 |
+
|
304 |
+
<ul class="benefits">
|
305 |
+
<?php foreach ( $benefits as $key => $benefit ) : ?>
|
306 |
+
<li class="benefit benefit-<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $benefit ); ?></li>
|
307 |
+
<?php endforeach; ?>
|
308 |
+
</ul>
|
309 |
+
|
310 |
+
<div class="actions">
|
311 |
+
|
312 |
+
<?php foreach ( $actions as $action_id => $action ) : ?>
|
313 |
+
|
314 |
+
<a
|
315 |
+
href="<?php echo esc_url( $action['url'] ); ?>"
|
316 |
+
class="button button-<?php echo esc_attr( $action['type'] ); ?>"
|
317 |
+
<?php echo ( 'get-started' !== $action_id ) ? 'target="_blank"' : ''; ?>
|
318 |
+
>
|
319 |
+
<?php echo esc_html( $action['label'] ); ?>
|
320 |
+
</a>
|
321 |
+
|
322 |
+
<?php endforeach; ?>
|
323 |
+
|
324 |
+
<?php if ( $is_connected ) : ?>
|
325 |
+
|
326 |
+
<a href="<?php echo esc_url( facebook_for_woocommerce()->get_connection_handler()->get_disconnect_url() ); ?>" class="uninstall">
|
327 |
+
<?php esc_html_e( 'Uninstall', 'facebook-for-woocommerce' ); ?>
|
328 |
+
</a>
|
329 |
+
|
330 |
+
<?php endif; ?>
|
331 |
+
|
332 |
+
</div>
|
333 |
+
|
334 |
+
</div>
|
335 |
+
|
336 |
+
<?php
|
337 |
+
}
|
338 |
+
|
339 |
+
|
340 |
+
/**
|
341 |
+
* Gets the screen settings.
|
342 |
+
*
|
343 |
+
* @since 2.0.0
|
344 |
+
*
|
345 |
+
* @return array
|
346 |
+
*/
|
347 |
+
public function get_settings() {
|
348 |
+
|
349 |
+
return [
|
350 |
+
|
351 |
+
[
|
352 |
+
'title' => __( 'Debug', 'facebook-for-woocommerce' ),
|
353 |
+
'type' => 'title',
|
354 |
+
],
|
355 |
+
|
356 |
+
[
|
357 |
+
'id' => \WC_Facebookcommerce_Integration::SETTING_ENABLE_DEBUG_MODE,
|
358 |
+
'title' => __( 'Enable debug mode', 'facebook-for-woocommerce' ),
|
359 |
+
'type' => 'checkbox',
|
360 |
+
'desc' => __( 'Log plugin events for debugging', 'facebook-for-woocommerce' ),
|
361 |
+
'desc_tip' => __( 'Only enable this if you are experiencing problems with the plugin.', 'facebook-for-woocommerce' ),
|
362 |
+
'default' => 'no',
|
363 |
+
],
|
364 |
+
|
365 |
+
[ 'type' => 'sectionend' ],
|
366 |
+
|
367 |
+
];
|
368 |
+
}
|
369 |
+
|
370 |
+
|
371 |
+
}
|
includes/Admin/Settings_Screens/Messenger.php
ADDED
@@ -0,0 +1,314 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\Admin\Settings_Screens;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\Admin;
|
16 |
+
use SkyVerge\WooCommerce\Facebook\API\FBE\Configuration;
|
17 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* The Messenger settings screen object.
|
21 |
+
*/
|
22 |
+
class Messenger extends Admin\Abstract_Settings_Screen {
|
23 |
+
|
24 |
+
|
25 |
+
/** @var string screen ID */
|
26 |
+
const ID = 'messenger';
|
27 |
+
|
28 |
+
|
29 |
+
/** @var null|Configuration\Messenger */
|
30 |
+
private $remote_configuration;
|
31 |
+
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Connection constructor.
|
35 |
+
*/
|
36 |
+
public function __construct() {
|
37 |
+
|
38 |
+
$this->id = self::ID;
|
39 |
+
$this->label = __( 'Messenger', 'facebook-for-woocommerce' );
|
40 |
+
$this->title = __( 'Messenger', 'facebook-for-woocommerce' );
|
41 |
+
|
42 |
+
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
|
43 |
+
|
44 |
+
add_action( 'woocommerce_admin_field_messenger_locale', [ $this, 'render_locale_field' ] );
|
45 |
+
add_action( 'woocommerce_admin_field_messenger_greeting', [ $this, 'render_greeting_field' ] );
|
46 |
+
}
|
47 |
+
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Enqueues the assets.
|
51 |
+
*
|
52 |
+
* @internal
|
53 |
+
*
|
54 |
+
* @since 2.0.0
|
55 |
+
*/
|
56 |
+
public function enqueue_assets() {
|
57 |
+
|
58 |
+
// TODO: empty for now, until we add more robust Messenger settings {CW 2020-06-17}
|
59 |
+
}
|
60 |
+
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Renders the custom locale field.
|
64 |
+
*
|
65 |
+
* @internal
|
66 |
+
*
|
67 |
+
* @since 2.0.0
|
68 |
+
*
|
69 |
+
* @param array $field field data
|
70 |
+
*/
|
71 |
+
public function render_locale_field( $field ) {
|
72 |
+
|
73 |
+
if ( ! $this->remote_configuration ) {
|
74 |
+
return;
|
75 |
+
}
|
76 |
+
|
77 |
+
$configured_locale = $this->remote_configuration->get_default_locale();
|
78 |
+
$supported_locales = \WC_Facebookcommerce_MessengerChat::get_supported_locales();
|
79 |
+
|
80 |
+
if ( ! empty( $supported_locales[ $configured_locale ] ) ) {
|
81 |
+
$configured_locale = $supported_locales[ $configured_locale ];
|
82 |
+
}
|
83 |
+
|
84 |
+
?>
|
85 |
+
<tr valign="top">
|
86 |
+
<th scope="row" class="titledesc">
|
87 |
+
<label for="<?php echo esc_attr( $field['id'] ); ?>"><?php echo esc_html( $field['title'] ); ?></label>
|
88 |
+
</th>
|
89 |
+
<td class="forminp forminp-<?php echo esc_attr( sanitize_title( $field['type'] ) ); ?>">
|
90 |
+
<p>
|
91 |
+
<?php echo esc_html( $configured_locale ); ?>
|
92 |
+
</p>
|
93 |
+
</td>
|
94 |
+
</tr>
|
95 |
+
<?php
|
96 |
+
}
|
97 |
+
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Renders the custom greeting field.
|
101 |
+
*
|
102 |
+
* @internal
|
103 |
+
*
|
104 |
+
* @since 2.0.0
|
105 |
+
*
|
106 |
+
* @param array $field field data
|
107 |
+
*/
|
108 |
+
public function render_greeting_field( $field ) {
|
109 |
+
|
110 |
+
?>
|
111 |
+
<tr valign="top">
|
112 |
+
<th scope="row" class="titledesc">
|
113 |
+
<label for="<?php echo esc_attr( $field['id'] ); ?>"><?php echo esc_html( $field['title'] ); ?></label>
|
114 |
+
</th>
|
115 |
+
<td class="forminp forminp-<?php echo esc_attr( sanitize_title( $field['type'] ) ); ?>">
|
116 |
+
<p>
|
117 |
+
<?php printf(
|
118 |
+
/* translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag */
|
119 |
+
esc_html__( '%1$sClick here%2$s to manage your Messenger greeting and colors.', 'facebook-for-woocommerce' ),
|
120 |
+
'<a href="' . esc_url( facebook_for_woocommerce()->get_connection_handler()->get_manage_url() ) . '" target="_blank">', '</a>'
|
121 |
+
); ?>
|
122 |
+
</p>
|
123 |
+
</td>
|
124 |
+
</tr>
|
125 |
+
<?php
|
126 |
+
}
|
127 |
+
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Gets the screen settings.
|
131 |
+
*
|
132 |
+
* @since 2.0.0
|
133 |
+
*
|
134 |
+
* @return array
|
135 |
+
*/
|
136 |
+
public function get_settings() {
|
137 |
+
|
138 |
+
$is_enabled = $this->remote_configuration && $this->remote_configuration->is_enabled();
|
139 |
+
|
140 |
+
$settings = [
|
141 |
+
|
142 |
+
[
|
143 |
+
'title' => __( 'Messenger', 'facebook-for-woocommerce' ),
|
144 |
+
'type' => 'title',
|
145 |
+
],
|
146 |
+
|
147 |
+
[
|
148 |
+
'id' => \WC_Facebookcommerce_Integration::SETTING_ENABLE_MESSENGER,
|
149 |
+
'title' => __( 'Enable Messenger', 'facebook-for-woocommerce' ),
|
150 |
+
'type' => 'checkbox',
|
151 |
+
'desc' => __( 'Enable and customize Facebook Messenger on your store', 'facebook-for-woocommerce' ),
|
152 |
+
'default' => 'no',
|
153 |
+
'value' => $is_enabled ? 'yes' : 'no',
|
154 |
+
],
|
155 |
+
];
|
156 |
+
|
157 |
+
// only add the static configuration display if messenger is enabled
|
158 |
+
if ( $is_enabled ) {
|
159 |
+
|
160 |
+
$settings[] = [
|
161 |
+
'title' => __( 'Language', 'facebook-for-woocommerce' ),
|
162 |
+
'type' => 'messenger_locale',
|
163 |
+
];
|
164 |
+
|
165 |
+
$settings[] = [
|
166 |
+
'title' => __( 'Greeting & Colors', 'facebook-for-woocommerce' ),
|
167 |
+
'type' => 'messenger_greeting',
|
168 |
+
];
|
169 |
+
}
|
170 |
+
|
171 |
+
$settings[] = [ 'type' => 'sectionend' ];
|
172 |
+
|
173 |
+
return $settings;
|
174 |
+
}
|
175 |
+
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Gets the "disconnected" message.
|
179 |
+
*
|
180 |
+
* @since 2.0.0
|
181 |
+
*
|
182 |
+
* @return string
|
183 |
+
*/
|
184 |
+
public function get_disconnected_message() {
|
185 |
+
|
186 |
+
return sprintf(
|
187 |
+
/* translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag */
|
188 |
+
__( 'Please %1$sconnect to Facebook%2$s to enable and manage Facebook Messenger.', 'facebook-for-woocommerce' ),
|
189 |
+
'<a href="' . esc_url( facebook_for_woocommerce()->get_connection_handler()->get_connect_url() ) . '">', '</a>'
|
190 |
+
);
|
191 |
+
}
|
192 |
+
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Renders the settings page.
|
196 |
+
*
|
197 |
+
* This is overridden to pull the latest FBE configuration so the settings can be populated correctly.
|
198 |
+
*
|
199 |
+
* @since 2.0.0
|
200 |
+
*/
|
201 |
+
public function render() {
|
202 |
+
|
203 |
+
// if not connected, don't try and retrieve any settings and just fall back to standard display
|
204 |
+
if ( ! facebook_for_woocommerce()->get_connection_handler()->is_connected() ) {
|
205 |
+
parent::render();
|
206 |
+
return;
|
207 |
+
}
|
208 |
+
|
209 |
+
$plugin = facebook_for_woocommerce();
|
210 |
+
|
211 |
+
try {
|
212 |
+
|
213 |
+
$response = $plugin->get_api()->get_business_configuration( $plugin->get_connection_handler()->get_external_business_id() );
|
214 |
+
|
215 |
+
$configuration = $response->get_messenger_configuration();
|
216 |
+
|
217 |
+
if ( ! $configuration ) {
|
218 |
+
throw new Framework\SV_WC_API_Exception( 'Could not retrieve latest messenger configuration' );
|
219 |
+
}
|
220 |
+
|
221 |
+
update_option( \WC_Facebookcommerce_Integration::SETTING_ENABLE_MESSENGER, wc_bool_to_string( $configuration->is_enabled() ) );
|
222 |
+
|
223 |
+
if ( $default_locale = $configuration->get_default_locale() ) {
|
224 |
+
update_option( \WC_Facebookcommerce_Integration::SETTING_MESSENGER_LOCALE, $default_locale );
|
225 |
+
}
|
226 |
+
|
227 |
+
// set the remote configuration so other methods can use its values
|
228 |
+
$this->remote_configuration = $configuration;
|
229 |
+
|
230 |
+
parent::render();
|
231 |
+
|
232 |
+
} catch ( Framework\SV_WC_API_Exception $exception ) {
|
233 |
+
|
234 |
+
?>
|
235 |
+
<div class="notice notice-error">
|
236 |
+
<p>
|
237 |
+
<?php printf(
|
238 |
+
/* translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag */
|
239 |
+
esc_html__( 'There was an error communicating with the Facebook Business Extension. %1$sClick here%2$s to manage your Messenger settings.', 'facebook-for-woocommerce' ),
|
240 |
+
'<a href="' . esc_url( $plugin->get_connection_handler()->get_manage_url() ) . '" target="_blank">', '</a>'
|
241 |
+
); ?>
|
242 |
+
</p>
|
243 |
+
</div>
|
244 |
+
<?php
|
245 |
+
|
246 |
+
// always log this error, regardless of debug setting
|
247 |
+
$plugin->log( 'Could not display messenger settings. ' . $exception->getMessage() );
|
248 |
+
}
|
249 |
+
}
|
250 |
+
|
251 |
+
|
252 |
+
/**
|
253 |
+
* Saves the settings.
|
254 |
+
*
|
255 |
+
* This is overridden to pull the latest from FBE and update that remotely via API
|
256 |
+
*
|
257 |
+
* @since 2.0.0
|
258 |
+
*
|
259 |
+
* @throws Framework\SV_WC_Plugin_Exception
|
260 |
+
*/
|
261 |
+
public function save() {
|
262 |
+
|
263 |
+
$plugin = facebook_for_woocommerce();
|
264 |
+
$external_business_id = $plugin->get_connection_handler()->get_external_business_id();
|
265 |
+
|
266 |
+
try {
|
267 |
+
|
268 |
+
// first get the latest configuration details
|
269 |
+
$response = $plugin->get_api()->get_business_configuration( $external_business_id );
|
270 |
+
|
271 |
+
$configuration = $response->get_messenger_configuration();
|
272 |
+
|
273 |
+
if ( ! $configuration ) {
|
274 |
+
throw new Framework\SV_WC_API_Exception( 'Could not retrieve latest messenger configuration' );
|
275 |
+
}
|
276 |
+
|
277 |
+
$update = false;
|
278 |
+
$setting_enabled = wc_string_to_bool( Framework\SV_WC_Helper::get_posted_value( \WC_Facebookcommerce_Integration::SETTING_ENABLE_MESSENGER ) );
|
279 |
+
|
280 |
+
// only consider updating if the setting has changed
|
281 |
+
if ( $setting_enabled !== $configuration->is_enabled() ) {
|
282 |
+
$update = true;
|
283 |
+
}
|
284 |
+
|
285 |
+
// also consider updating if the site's URL was removed from approved URLs
|
286 |
+
if ( ! in_array( home_url( '/' ), $configuration->get_domains(), true ) ) {
|
287 |
+
$update = true;
|
288 |
+
}
|
289 |
+
|
290 |
+
// make the API call if settings have changed
|
291 |
+
if ( $update ) {
|
292 |
+
|
293 |
+
$configuration->set_enabled( $setting_enabled );
|
294 |
+
$configuration->add_domain( home_url( '/' ) );
|
295 |
+
|
296 |
+
$plugin->get_api()->update_messenger_configuration( $external_business_id, $configuration );
|
297 |
+
|
298 |
+
delete_transient( 'wc_facebook_business_configuration_refresh' );
|
299 |
+
}
|
300 |
+
|
301 |
+
// save any real settings
|
302 |
+
parent::save();
|
303 |
+
|
304 |
+
} catch ( Framework\SV_WC_API_Exception $exception ) {
|
305 |
+
|
306 |
+
// always log this error, regardless of debug setting
|
307 |
+
$plugin->log( 'Could not update remote messenger settings. ' . $exception->getMessage() );
|
308 |
+
|
309 |
+
throw new Framework\SV_WC_Plugin_Exception( __( 'Please try again.', 'facebook-for-woocommerce' ) );
|
310 |
+
}
|
311 |
+
}
|
312 |
+
|
313 |
+
|
314 |
+
}
|
includes/Admin/Settings_Screens/Product_Sync.php
ADDED
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\Admin\Settings_Screens;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\Admin;
|
16 |
+
use SkyVerge\WooCommerce\Facebook\Products;
|
17 |
+
use SkyVerge\WooCommerce\Facebook\Products\Sync;
|
18 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4\SV_WC_Helper;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* The Messenger settings screen object.
|
22 |
+
*/
|
23 |
+
class Product_Sync extends Admin\Abstract_Settings_Screen {
|
24 |
+
|
25 |
+
|
26 |
+
/** @var string screen ID */
|
27 |
+
const ID = 'product_sync';
|
28 |
+
|
29 |
+
/** @var string the sync products action */
|
30 |
+
const ACTION_SYNC_PRODUCTS = 'wc_facebook_sync_products';
|
31 |
+
|
32 |
+
/** @var string the get sync status action */
|
33 |
+
const ACTION_GET_SYNC_STATUS = 'wc_facebook_get_sync_status';
|
34 |
+
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Connection constructor.
|
38 |
+
*/
|
39 |
+
public function __construct() {
|
40 |
+
|
41 |
+
$this->id = self::ID;
|
42 |
+
$this->label = __( 'Product sync', 'facebook-for-woocommerce' );
|
43 |
+
$this->title = __( 'Product sync', 'facebook-for-woocommerce' );
|
44 |
+
|
45 |
+
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
|
46 |
+
|
47 |
+
add_action( 'woocommerce_admin_field_product_sync_title', [ $this, 'render_title' ] );
|
48 |
+
}
|
49 |
+
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Enqueues the assets.
|
53 |
+
*
|
54 |
+
* @internal
|
55 |
+
*
|
56 |
+
* @since 2.0.0
|
57 |
+
*/
|
58 |
+
public function enqueue_assets() {
|
59 |
+
|
60 |
+
$tab = SV_WC_Helper::get_requested_value( 'tab' );
|
61 |
+
|
62 |
+
if ( Admin\Settings::PAGE_ID !== SV_WC_Helper::get_requested_value( 'page' ) || ( $tab && self::ID !== $tab ) ) {
|
63 |
+
return;
|
64 |
+
}
|
65 |
+
|
66 |
+
wp_enqueue_script( 'wc-backbone-modal', null, [ 'backbone' ] );
|
67 |
+
wp_enqueue_script( 'facebook-for-woocommerce-modal', plugins_url( '/facebook-for-woocommerce/assets/js/facebook-for-woocommerce-modal.min.js' ), [ 'jquery', 'wc-backbone-modal', 'jquery-blockui' ], \WC_Facebookcommerce::PLUGIN_VERSION );
|
68 |
+
wp_enqueue_script( 'facebook-for-woocommerce-settings-sync', plugins_url( '/facebook-for-woocommerce/assets/js/admin/facebook-for-woocommerce-settings-sync.min.js' ), [ 'jquery', 'wc-backbone-modal', 'jquery-blockui', 'jquery-tiptip', 'facebook-for-woocommerce-modal', 'wc-enhanced-select' ], \WC_Facebookcommerce::PLUGIN_VERSION );
|
69 |
+
|
70 |
+
/* translators: Placeholders: {count} number of remaining items */
|
71 |
+
$sync_remaining_items_string = _n_noop( '{count} item remaining.', '{count} items remaining.', 'facebook-for-woocommerce' );
|
72 |
+
|
73 |
+
wp_localize_script( 'facebook-for-woocommerce-settings-sync', 'facebook_for_woocommerce_settings_sync', [
|
74 |
+
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
75 |
+
'set_excluded_terms_prompt_nonce' => wp_create_nonce( 'set-excluded-terms-prompt' ),
|
76 |
+
'sync_products_nonce' => wp_create_nonce( self::ACTION_SYNC_PRODUCTS ),
|
77 |
+
'sync_status_nonce' => wp_create_nonce( self::ACTION_GET_SYNC_STATUS ),
|
78 |
+
'sync_in_progress' => Sync::is_sync_in_progress(),
|
79 |
+
'excluded_category_ids' => facebook_for_woocommerce()->get_integration()->get_excluded_product_category_ids(),
|
80 |
+
'excluded_tag_ids' => facebook_for_woocommerce()->get_integration()->get_excluded_product_tag_ids(),
|
81 |
+
'i18n' => [
|
82 |
+
/* translators: Placeholders %s - html code for a spinner icon */
|
83 |
+
'confirm_resync' => esc_html__( 'Your products will now be resynced to Facebook, this may take some time.', 'facebook-for-woocommerce' ),
|
84 |
+
'confirm_sync' => esc_html__( "Facebook for WooCommerce automatically syncs your products on create/update. Are you sure you want to force product resync?\n\nThis will query all published products and may take some time. You only need to do this if your products are out of sync or some of your products did not sync.", 'facebook-for-woocommerce' ),
|
85 |
+
'sync_in_progress' => sprintf( esc_html__( 'Your products are syncing - you may safely leave this page %s', 'facebook-for-woocommerce' ), '<span class="spinner is-active"></span>' ),
|
86 |
+
'sync_remaining_items_singular' => sprintf( esc_html( translate_nooped_plural( $sync_remaining_items_string, 1 ) ), '<strong>', '</strong>', '<span class="spinner is-active"></span>' ),
|
87 |
+
'sync_remaining_items_plural' => sprintf( esc_html( translate_nooped_plural( $sync_remaining_items_string, 2 ) ), '<strong>', '</strong>', '<span class="spinner is-active"></span>' ),
|
88 |
+
'general_error' => esc_html__( 'There was an error trying to sync the products to Facebook.', 'facebook-for-woocommerce' ),
|
89 |
+
'feed_upload_error' => esc_html__( 'Something went wrong while uploading the product information, please try again.', 'facebook-for-woocommerce' ),
|
90 |
+
],
|
91 |
+
] );
|
92 |
+
}
|
93 |
+
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Renders the custom title.
|
97 |
+
*
|
98 |
+
* @internal
|
99 |
+
*
|
100 |
+
* @since 2.0.0
|
101 |
+
*
|
102 |
+
* @param array $field field data
|
103 |
+
*/
|
104 |
+
public function render_title( $field ) {
|
105 |
+
|
106 |
+
?>
|
107 |
+
|
108 |
+
<h2>
|
109 |
+
|
110 |
+
<?php esc_html_e( 'Product sync', 'facebook-for-woocommerce' ); ?>
|
111 |
+
|
112 |
+
<?php if ( facebook_for_woocommerce()->get_connection_handler()->is_connected() ) : ?>
|
113 |
+
<a
|
114 |
+
id="woocommerce-facebook-settings-sync-products"
|
115 |
+
class="button product-sync-field"
|
116 |
+
href="#"
|
117 |
+
style="vertical-align: middle; margin-left: 20px;"
|
118 |
+
><?php esc_html_e( 'Sync products', 'facebook-for-woocommerce' ); ?></a>
|
119 |
+
<?php endif; ?>
|
120 |
+
|
121 |
+
</h2>
|
122 |
+
<div><p id="sync_progress" style="display: none"></p></div>
|
123 |
+
<table class="form-table">
|
124 |
+
|
125 |
+
<?php
|
126 |
+
}
|
127 |
+
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Saves the Product Sync settings.
|
131 |
+
*
|
132 |
+
* @since 2.0.0
|
133 |
+
*/
|
134 |
+
public function save() {
|
135 |
+
|
136 |
+
$integration = facebook_for_woocommerce()->get_integration();
|
137 |
+
|
138 |
+
$previous_product_cat_ids = $integration->get_excluded_product_category_ids();
|
139 |
+
$previous_product_tag_ids = $integration->get_excluded_product_tag_ids();
|
140 |
+
|
141 |
+
parent::save();
|
142 |
+
|
143 |
+
// when settings are saved, if there are new excluded categories/terms we should exclude corresponding products from sync
|
144 |
+
$new_product_cat_ids = array_diff( $integration->get_excluded_product_category_ids(), $previous_product_cat_ids );
|
145 |
+
$new_product_tag_ids = array_diff( $integration->get_excluded_product_tag_ids(), $previous_product_tag_ids );
|
146 |
+
|
147 |
+
$this->disable_sync_for_excluded_products( $new_product_cat_ids, $new_product_tag_ids );
|
148 |
+
}
|
149 |
+
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Disables sync for products that belong to any of the given categories or tags.
|
153 |
+
*
|
154 |
+
* @since 2.0.0
|
155 |
+
*
|
156 |
+
* @param array $product_cat_ids IDs of excluded categories
|
157 |
+
* @param array $product_tag_ids IDs of excluded tags
|
158 |
+
*/
|
159 |
+
private function disable_sync_for_excluded_products( $product_cat_ids, $product_tag_ids ) {
|
160 |
+
|
161 |
+
// disable sync for all products belonging to excluded categories
|
162 |
+
Products::disable_sync_for_products_with_terms( [
|
163 |
+
'taxonomy' => 'product_cat',
|
164 |
+
'include' => $product_cat_ids,
|
165 |
+
] );
|
166 |
+
|
167 |
+
// disable sync for all products belonging to excluded tags
|
168 |
+
Products::disable_sync_for_products_with_terms( [
|
169 |
+
'taxonomy' => 'product_tag',
|
170 |
+
'include' => $product_tag_ids,
|
171 |
+
] );
|
172 |
+
}
|
173 |
+
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Gets the screen settings.
|
177 |
+
*
|
178 |
+
* @since 2.0.0
|
179 |
+
*
|
180 |
+
* @return array
|
181 |
+
*/
|
182 |
+
public function get_settings() {
|
183 |
+
|
184 |
+
$term_query = new \WP_Term_Query( [
|
185 |
+
'taxonomy' => 'product_cat',
|
186 |
+
'hide_empty' => false,
|
187 |
+
'fields' => 'id=>name',
|
188 |
+
] );
|
189 |
+
|
190 |
+
$product_categories = $term_query->get_terms();
|
191 |
+
|
192 |
+
$term_query = new \WP_Term_Query( [
|
193 |
+
'taxonomy' => 'product_tag',
|
194 |
+
'hide_empty' => false,
|
195 |
+
'hierarchical' => false,
|
196 |
+
'fields' => 'id=>name',
|
197 |
+
] );
|
198 |
+
|
199 |
+
$product_tags = $term_query->get_terms();
|
200 |
+
|
201 |
+
return [
|
202 |
+
|
203 |
+
[
|
204 |
+
'type' => 'product_sync_title',
|
205 |
+
'title' => __( 'Product sync', 'facebook-for-woocommerce' ),
|
206 |
+
],
|
207 |
+
|
208 |
+
[
|
209 |
+
'id' => \WC_Facebookcommerce_Integration::SETTING_ENABLE_PRODUCT_SYNC,
|
210 |
+
'title' => __( 'Enable product sync', 'facebook-for-woocommerce' ),
|
211 |
+
'type' => 'checkbox',
|
212 |
+
'label' => ' ',
|
213 |
+
'default' => 'yes',
|
214 |
+
],
|
215 |
+
|
216 |
+
[
|
217 |
+
'id' => \WC_Facebookcommerce_Integration::SETTING_EXCLUDED_PRODUCT_CATEGORY_IDS,
|
218 |
+
'title' => __( 'Exclude categories from sync', 'facebook-for-woocommerce' ),
|
219 |
+
'type' => 'multiselect',
|
220 |
+
'class' => 'wc-enhanced-select product-sync-field',
|
221 |
+
'css' => 'min-width: 300px;',
|
222 |
+
'desc_tip' => __( 'Products in one or more of these categories will not sync to Facebook.', 'facebook-for-woocommerce' ),
|
223 |
+
'default' => [],
|
224 |
+
'options' => is_array( $product_categories ) ? $product_categories : [],
|
225 |
+
'custom_attributes' => [
|
226 |
+
'data-placeholder' => __( 'Search for a product category…', 'facebook-for-woocommerce' ),
|
227 |
+
],
|
228 |
+
],
|
229 |
+
|
230 |
+
[
|
231 |
+
'id' => \WC_Facebookcommerce_Integration::SETTING_EXCLUDED_PRODUCT_TAG_IDS,
|
232 |
+
'title' => __( 'Exclude tags from sync', 'facebook-for-woocommerce' ),
|
233 |
+
'type' => 'multiselect',
|
234 |
+
'class' => 'wc-enhanced-select product-sync-field',
|
235 |
+
'css' => 'min-width: 300px;',
|
236 |
+
'desc_tip' => __( 'Products with one or more of these tags will not sync to Facebook.', 'facebook-for-woocommerce' ),
|
237 |
+
'default' => [],
|
238 |
+
'options' => is_array( $product_tags ) ? $product_tags : [],
|
239 |
+
'custom_attributes' => [
|
240 |
+
'data-placeholder' => __( 'Search for a product tag…', 'facebook-for-woocommerce' ),
|
241 |
+
],
|
242 |
+
],
|
243 |
+
|
244 |
+
[
|
245 |
+
'id' => \WC_Facebookcommerce_Integration::SETTING_PRODUCT_DESCRIPTION_MODE,
|
246 |
+
'title' => __( 'Product description sync', 'facebook-for-woocommerce' ),
|
247 |
+
'type' => 'select',
|
248 |
+
'class' => 'product-sync-field',
|
249 |
+
'desc_tip' => __( 'Choose which product description to display in the Facebook catalog.', 'facebook-for-woocommerce' ),
|
250 |
+
'default' => \WC_Facebookcommerce_Integration::PRODUCT_DESCRIPTION_MODE_STANDARD,
|
251 |
+
'options' => [
|
252 |
+
\WC_Facebookcommerce_Integration::PRODUCT_DESCRIPTION_MODE_STANDARD => __( 'Standard description', 'facebook-for-woocommerce' ),
|
253 |
+
\WC_Facebookcommerce_Integration::PRODUCT_DESCRIPTION_MODE_SHORT => __( 'Short description', 'facebook-for-woocommerce' ),
|
254 |
+
],
|
255 |
+
],
|
256 |
+
|
257 |
+
[ 'type' => 'sectionend' ],
|
258 |
+
|
259 |
+
];
|
260 |
+
}
|
261 |
+
|
262 |
+
|
263 |
+
/**
|
264 |
+
* Gets the "disconnected" message.
|
265 |
+
*
|
266 |
+
* @since 2.0.0
|
267 |
+
*
|
268 |
+
* @return string
|
269 |
+
*/
|
270 |
+
public function get_disconnected_message() {
|
271 |
+
|
272 |
+
return sprintf(
|
273 |
+
/* translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag */
|
274 |
+
__( 'Please %1$sconnect to Facebook%2$s to enable and manage product sync.', 'facebook-for-woocommerce' ),
|
275 |
+
'<a href="' . esc_url( facebook_for_woocommerce()->get_connection_handler()->get_connect_url() ) . '">', '</a>'
|
276 |
+
);
|
277 |
+
}
|
278 |
+
|
279 |
+
|
280 |
+
}
|
includes/Events/Event.php
ADDED
@@ -0,0 +1,332 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\Events;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Event object.
|
17 |
+
*
|
18 |
+
* @since 2.0.0
|
19 |
+
*/
|
20 |
+
class Event {
|
21 |
+
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @var array data specific to this event instance with the same structure as the event’s payload
|
25 |
+
*
|
26 |
+
* @see https://developers.facebook.com/docs/marketing-api/server-side-api/payload-helper
|
27 |
+
*/
|
28 |
+
protected $data = [];
|
29 |
+
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Gets version information for pixel events.
|
33 |
+
*
|
34 |
+
* @return array {
|
35 |
+
* @type string source 'woocommerce'
|
36 |
+
* @type string version WooCommerce's version
|
37 |
+
* @type string pluginVersion Facebook for WooCommerce's version
|
38 |
+
* }
|
39 |
+
*/
|
40 |
+
public static function get_version_info() {
|
41 |
+
|
42 |
+
return [
|
43 |
+
'source' => 'woocommerce',
|
44 |
+
'version' => WC()->version,
|
45 |
+
'pluginVersion' => facebook_for_woocommerce()->get_version(),
|
46 |
+
];
|
47 |
+
}
|
48 |
+
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Gets the agent string for pixel events.
|
52 |
+
*
|
53 |
+
* @return string
|
54 |
+
*/
|
55 |
+
public static function get_platform_identifier() {
|
56 |
+
|
57 |
+
$info = self::get_version_info();
|
58 |
+
|
59 |
+
return "{$info['source']}-{$info['version']}-{$info['pluginVersion']}";
|
60 |
+
}
|
61 |
+
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Constructor.
|
65 |
+
*
|
66 |
+
* @see https://developers.facebook.com/docs/marketing-api/server-side-api/parameters
|
67 |
+
*
|
68 |
+
* @since 2.0.0
|
69 |
+
*
|
70 |
+
* @param array $data event data
|
71 |
+
*/
|
72 |
+
public function __construct( $data = [] ) {
|
73 |
+
|
74 |
+
$this->prepare_data( $data );
|
75 |
+
}
|
76 |
+
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Provides defaults for properties if not already defined.
|
80 |
+
*
|
81 |
+
* @see https://developers.facebook.com/docs/marketing-api/server-side-api/parameters/server-event
|
82 |
+
* @see https://developers.facebook.com/docs/marketing-api/server-side-api/parameters/custom-data
|
83 |
+
*
|
84 |
+
* @since 2.0.0
|
85 |
+
*
|
86 |
+
* @param array $data event data
|
87 |
+
*/
|
88 |
+
protected function prepare_data( $data ) {
|
89 |
+
|
90 |
+
$this->data = wp_parse_args( $data, [
|
91 |
+
'event_time' => time(),
|
92 |
+
'event_id' => $this->generate_event_id(),
|
93 |
+
'event_source_url' => $this->get_current_url(),
|
94 |
+
'custom_data' => [],
|
95 |
+
'user_data' => [],
|
96 |
+
] );
|
97 |
+
|
98 |
+
$this->prepare_user_data( $this->data['user_data'] );
|
99 |
+
}
|
100 |
+
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Provides defaults for user properties if not already defined.
|
104 |
+
*
|
105 |
+
* @see https://developers.facebook.com/docs/marketing-api/server-side-api/parameters/user-data
|
106 |
+
*
|
107 |
+
* @since 2.0.0
|
108 |
+
*
|
109 |
+
* @param array $data user data
|
110 |
+
*/
|
111 |
+
protected function prepare_user_data( $data ) {
|
112 |
+
|
113 |
+
$this->data['user_data'] = wp_parse_args( $data, [
|
114 |
+
'client_ip_address' => $this->get_client_ip(),
|
115 |
+
'client_user_agent' => $this->get_client_user_agent(),
|
116 |
+
'click_id' => $this->get_click_id(),
|
117 |
+
'browser_id' => $this->get_browser_id(),
|
118 |
+
] );
|
119 |
+
}
|
120 |
+
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Generates a UUIDv4 unique ID for the event.
|
124 |
+
*
|
125 |
+
* @see https://stackoverflow.com/a/15875555
|
126 |
+
*
|
127 |
+
* @since 2.0.0
|
128 |
+
*
|
129 |
+
* @return string
|
130 |
+
*/
|
131 |
+
protected function generate_event_id() {
|
132 |
+
|
133 |
+
try {
|
134 |
+
$data = random_bytes( 16 );
|
135 |
+
|
136 |
+
$data[6] = chr( ord( $data[6] ) & 0x0f | 0x40 ); // set version to 0100
|
137 |
+
$data[8] = chr( ord( $data[8] ) & 0x3f | 0x80 ); // set bits 6-7 to 10
|
138 |
+
|
139 |
+
return vsprintf( '%s%s-%s-%s-%s-%s%s%s', str_split( bin2hex( $data ), 4 ) );
|
140 |
+
|
141 |
+
} catch ( \Exception $e ) {
|
142 |
+
|
143 |
+
// fall back to mt_rand if random_bytes is unavailable
|
144 |
+
return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
145 |
+
|
146 |
+
// 32 bits for "time_low"
|
147 |
+
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
|
148 |
+
|
149 |
+
// 16 bits for "time_mid"
|
150 |
+
mt_rand( 0, 0xffff ),
|
151 |
+
|
152 |
+
// 16 bits for "time_hi_and_version",
|
153 |
+
// four most significant bits holds version number 4
|
154 |
+
mt_rand( 0, 0x0fff ) | 0x4000,
|
155 |
+
|
156 |
+
// 16 bits, 8 bits for "clk_seq_hi_res",
|
157 |
+
// 8 bits for "clk_seq_low",
|
158 |
+
// two most significant bits holds zero and one for variant DCE1.1
|
159 |
+
mt_rand( 0, 0x3fff ) | 0x8000,
|
160 |
+
|
161 |
+
// 48 bits for "node"
|
162 |
+
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
|
163 |
+
);
|
164 |
+
}
|
165 |
+
}
|
166 |
+
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Gets the current URL.
|
170 |
+
*
|
171 |
+
* @since 2.0.0
|
172 |
+
*
|
173 |
+
* @return string
|
174 |
+
*/
|
175 |
+
protected function get_current_url() {
|
176 |
+
|
177 |
+
if ( wp_doing_ajax() ) {
|
178 |
+
|
179 |
+
$url = $_SERVER['HTTP_REFERER'];
|
180 |
+
|
181 |
+
} else {
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Instead of relying on the HTTP_HOST server var, we use home_url(),
|
185 |
+
* so that we get the host configured in site options.
|
186 |
+
* Additionally, this automatically uses the correct domain when
|
187 |
+
* using Forward with the WooCommerce Dev Helper plugin.
|
188 |
+
*/
|
189 |
+
$url = home_url() . $_SERVER['REQUEST_URI'];
|
190 |
+
}
|
191 |
+
|
192 |
+
return $url;
|
193 |
+
}
|
194 |
+
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Gets the client IP address.
|
198 |
+
*
|
199 |
+
* @since 2.0.0
|
200 |
+
*
|
201 |
+
* @return string
|
202 |
+
*/
|
203 |
+
protected function get_client_ip() {
|
204 |
+
|
205 |
+
return \WC_Geolocation::get_ip_address();
|
206 |
+
}
|
207 |
+
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Gets the client user agent.
|
211 |
+
*
|
212 |
+
* @since 2.0.0
|
213 |
+
*
|
214 |
+
* @return string
|
215 |
+
*/
|
216 |
+
protected function get_client_user_agent() {
|
217 |
+
|
218 |
+
return ! empty( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '';
|
219 |
+
}
|
220 |
+
|
221 |
+
|
222 |
+
/**
|
223 |
+
* Gets the click ID from the cookie or the query parameter.
|
224 |
+
*
|
225 |
+
* @see https://developers.facebook.com/docs/marketing-api/server-side-api/parameters/fbp-and-fbc#fbp-and-fbc-parameters
|
226 |
+
*
|
227 |
+
* @since 2.0.0
|
228 |
+
*
|
229 |
+
* @return string
|
230 |
+
*/
|
231 |
+
protected function get_click_id() {
|
232 |
+
|
233 |
+
$click_id = '';
|
234 |
+
|
235 |
+
if ( ! empty( $_COOKIE['_fbc'] ) ) {
|
236 |
+
|
237 |
+
$click_id = $_COOKIE['_fbc'];
|
238 |
+
|
239 |
+
} elseif ( ! empty( $_REQUEST['fbclid'] ) ) {
|
240 |
+
|
241 |
+
// generate the click ID based on the query parameter
|
242 |
+
$version = 'fb';
|
243 |
+
$subdomain_index = 1;
|
244 |
+
$creation_time = time();
|
245 |
+
$fbclid = $_REQUEST['fbclid'];
|
246 |
+
|
247 |
+
$click_id = "{$version}.{$subdomain_index}.{$creation_time}.{$fbclid}";
|
248 |
+
}
|
249 |
+
|
250 |
+
return $click_id;
|
251 |
+
}
|
252 |
+
|
253 |
+
|
254 |
+
/**
|
255 |
+
* Gets the browser ID from the cookie.
|
256 |
+
*
|
257 |
+
* @since 2.0.0
|
258 |
+
*
|
259 |
+
* @return string
|
260 |
+
*/
|
261 |
+
protected function get_browser_id() {
|
262 |
+
|
263 |
+
return ! empty( $_COOKIE['_fbp'] ) ? $_COOKIE['_fbp'] : '';
|
264 |
+
}
|
265 |
+
|
266 |
+
|
267 |
+
/**
|
268 |
+
* Gets the data.
|
269 |
+
*
|
270 |
+
* @since 2.0.0
|
271 |
+
*
|
272 |
+
* @return array
|
273 |
+
*/
|
274 |
+
public function get_data() {
|
275 |
+
|
276 |
+
return $this->data;
|
277 |
+
}
|
278 |
+
|
279 |
+
|
280 |
+
/**
|
281 |
+
* Gets the event ID.
|
282 |
+
*
|
283 |
+
* @since 2.0.0
|
284 |
+
*
|
285 |
+
* @return string
|
286 |
+
*/
|
287 |
+
public function get_id() {
|
288 |
+
|
289 |
+
return ! empty( $this->data['event_id'] ) ? $this->data['event_id'] : '';
|
290 |
+
}
|
291 |
+
|
292 |
+
|
293 |
+
/**
|
294 |
+
* Gets the event name.
|
295 |
+
*
|
296 |
+
* @since 2.0.0
|
297 |
+
*
|
298 |
+
* @return string
|
299 |
+
*/
|
300 |
+
public function get_name() {
|
301 |
+
|
302 |
+
return ! empty( $this->data['event_name'] ) ? $this->data['event_name'] : '';
|
303 |
+
}
|
304 |
+
|
305 |
+
|
306 |
+
/**
|
307 |
+
* Gets the user data.
|
308 |
+
*
|
309 |
+
* @since 2.0.0
|
310 |
+
*
|
311 |
+
* @return array
|
312 |
+
*/
|
313 |
+
public function get_user_data() {
|
314 |
+
|
315 |
+
return ! empty( $this->data['user_data'] ) ? $this->data['user_data'] : [];
|
316 |
+
}
|
317 |
+
|
318 |
+
|
319 |
+
/**
|
320 |
+
* Gets the event custom data.
|
321 |
+
*
|
322 |
+
* @since 2.0.0
|
323 |
+
*
|
324 |
+
* @return array
|
325 |
+
*/
|
326 |
+
public function get_custom_data() {
|
327 |
+
|
328 |
+
return ! empty( $this->data['custom_data'] ) ? $this->data['custom_data'] : [];
|
329 |
+
}
|
330 |
+
|
331 |
+
|
332 |
+
}
|
includes/Handlers/Connection.php
ADDED
@@ -0,0 +1,820 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\Handlers;
|
12 |
+
|
13 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4\SV_WC_API_Exception;
|
14 |
+
|
15 |
+
defined( 'ABSPATH' ) or exit;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* The connection handler.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Connection {
|
23 |
+
|
24 |
+
|
25 |
+
/** @var string Facebook client identifier */
|
26 |
+
const CLIENT_ID = '474166926521348';
|
27 |
+
|
28 |
+
/** @var string Facebook OAuth URL */
|
29 |
+
const OAUTH_URL = 'https://facebook.com/dialog/oauth';
|
30 |
+
|
31 |
+
/** @var string WooCommerce connection proxy URL */
|
32 |
+
const PROXY_URL = 'https://connect.woocommerce.com/auth/facebook/';
|
33 |
+
|
34 |
+
/** @var string the action callback for the connection */
|
35 |
+
const ACTION_CONNECT = 'wc_facebook_connect';
|
36 |
+
|
37 |
+
/** @var string the action callback for the disconnection */
|
38 |
+
const ACTION_DISCONNECT = 'wc_facebook_disconnect';
|
39 |
+
|
40 |
+
/** @var string the WordPress option name where the external business ID is stored */
|
41 |
+
const OPTION_EXTERNAL_BUSINESS_ID = 'wc_facebook_external_business_id';
|
42 |
+
|
43 |
+
/** @var string the business manager ID option name */
|
44 |
+
const OPTION_BUSINESS_MANAGER_ID = 'wc_facebook_business_manager_id';
|
45 |
+
|
46 |
+
/** @var string the ad account ID option name */
|
47 |
+
const OPTION_AD_ACCOUNT_ID = 'wc_facebook_ad_account_id';
|
48 |
+
|
49 |
+
/** @var string the system user ID option name */
|
50 |
+
const OPTION_SYSTEM_USER_ID = 'wc_facebook_system_user_id';
|
51 |
+
|
52 |
+
/** @var string the system user access token option name */
|
53 |
+
const OPTION_ACCESS_TOKEN = 'wc_facebook_access_token';
|
54 |
+
|
55 |
+
/** @var string the merchant access token option name */
|
56 |
+
const OPTION_MERCHANT_ACCESS_TOKEN = 'wc_facebook_merchant_access_token';
|
57 |
+
|
58 |
+
/** @var string|null the generated external merchant settings ID */
|
59 |
+
private $external_business_id;
|
60 |
+
|
61 |
+
/** @var \WC_Facebookcommerce */
|
62 |
+
private $plugin;
|
63 |
+
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Constructs a new Connection.
|
67 |
+
*
|
68 |
+
* @since 2.0.0
|
69 |
+
*/
|
70 |
+
public function __construct( \WC_Facebookcommerce $plugin ) {
|
71 |
+
|
72 |
+
$this->plugin = $plugin;
|
73 |
+
|
74 |
+
add_action( 'init', [ $this, 'refresh_business_configuration' ] );
|
75 |
+
|
76 |
+
add_action( 'admin_init', [ $this, 'refresh_installation_data' ] );
|
77 |
+
|
78 |
+
add_action( 'woocommerce_api_' . self::ACTION_CONNECT, [ $this, 'handle_connect' ] );
|
79 |
+
|
80 |
+
add_action( 'admin_action_' . self::ACTION_DISCONNECT, [ $this, 'handle_disconnect' ] );
|
81 |
+
}
|
82 |
+
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Refreshes the local business configuration data with the latest from Facebook.
|
86 |
+
*
|
87 |
+
* @internal
|
88 |
+
*
|
89 |
+
* @since 2.0.0
|
90 |
+
*/
|
91 |
+
public function refresh_business_configuration() {
|
92 |
+
|
93 |
+
// only refresh once an hour
|
94 |
+
if ( get_transient( 'wc_facebook_business_configuration_refresh' ) ) {
|
95 |
+
return;
|
96 |
+
}
|
97 |
+
|
98 |
+
// bail if not connected
|
99 |
+
if ( ! $this->is_connected() ) {
|
100 |
+
return;
|
101 |
+
}
|
102 |
+
|
103 |
+
try {
|
104 |
+
|
105 |
+
$response = $this->get_plugin()->get_api()->get_business_configuration( $this->get_external_business_id() );
|
106 |
+
|
107 |
+
// update the messenger settings
|
108 |
+
if ( $messenger_configuration = $response->get_messenger_configuration() ) {
|
109 |
+
|
110 |
+
// store the local "enabled" setting
|
111 |
+
update_option( \WC_Facebookcommerce_Integration::SETTING_ENABLE_MESSENGER, wc_bool_to_string( $messenger_configuration->is_enabled() ) );
|
112 |
+
|
113 |
+
if ( $default_locale = $messenger_configuration->get_default_locale() ) {
|
114 |
+
update_option( \WC_Facebookcommerce_Integration::SETTING_MESSENGER_LOCALE, sanitize_text_field( $default_locale ) );
|
115 |
+
}
|
116 |
+
|
117 |
+
// if the site's domain is somehow missing from the allowed domains, re-add it
|
118 |
+
if ( $messenger_configuration->is_enabled() && ! in_array( home_url( '/' ), $messenger_configuration->get_domains(), true ) ) {
|
119 |
+
|
120 |
+
$messenger_configuration->add_domain( home_url( '/' ) );
|
121 |
+
|
122 |
+
$this->get_plugin()->get_api()->update_messenger_configuration( $this->get_external_business_id(), $messenger_configuration );
|
123 |
+
}
|
124 |
+
}
|
125 |
+
|
126 |
+
} catch ( SV_WC_API_Exception $exception ) {
|
127 |
+
|
128 |
+
if ( $this->get_plugin()->get_integration()->is_debug_mode_enabled() ) {
|
129 |
+
$this->get_plugin()->log( 'Could not refresh business configuration. ' . $exception->getMessage() );
|
130 |
+
}
|
131 |
+
}
|
132 |
+
|
133 |
+
set_transient( 'wc_facebook_business_configuration_refresh', time(), HOUR_IN_SECONDS );
|
134 |
+
}
|
135 |
+
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Refreshes the connected installation data.
|
139 |
+
*
|
140 |
+
* @since 2.0.0
|
141 |
+
*/
|
142 |
+
public function refresh_installation_data() {
|
143 |
+
|
144 |
+
// bail if not connected
|
145 |
+
if ( ! $this->is_connected() ) {
|
146 |
+
return;
|
147 |
+
}
|
148 |
+
|
149 |
+
// only refresh once a day
|
150 |
+
if ( get_transient( 'wc_facebook_connection_refresh' ) ) {
|
151 |
+
return;
|
152 |
+
}
|
153 |
+
|
154 |
+
try {
|
155 |
+
|
156 |
+
$this->update_installation_data();
|
157 |
+
|
158 |
+
} catch ( SV_WC_API_Exception $exception ) {
|
159 |
+
|
160 |
+
if ( $this->get_plugin()->get_integration()->is_debug_mode_enabled() ) {
|
161 |
+
$this->get_plugin()->log( 'Could not refresh installation data. ' . $exception->getMessage() );
|
162 |
+
}
|
163 |
+
}
|
164 |
+
|
165 |
+
set_transient( 'wc_facebook_connection_refresh', time(), DAY_IN_SECONDS );
|
166 |
+
}
|
167 |
+
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Retrieves and stores the connected installation data.
|
171 |
+
*
|
172 |
+
* @since 2.0.0
|
173 |
+
*
|
174 |
+
* @throws SV_WC_API_Exception
|
175 |
+
*/
|
176 |
+
private function update_installation_data() {
|
177 |
+
|
178 |
+
$response = $this->get_plugin()->get_api()->get_installation_ids( $this->get_external_business_id() );
|
179 |
+
|
180 |
+
if ( $response->get_page_id() ) {
|
181 |
+
update_option( \WC_Facebookcommerce_Integration::SETTING_FACEBOOK_PAGE_ID, sanitize_text_field( $response->get_page_id() ) );
|
182 |
+
}
|
183 |
+
|
184 |
+
if ( $response->get_pixel_id() ) {
|
185 |
+
update_option( \WC_Facebookcommerce_Integration::SETTING_FACEBOOK_PIXEL_ID, sanitize_text_field( $response->get_pixel_id() ) );
|
186 |
+
}
|
187 |
+
|
188 |
+
if ( $response->get_catalog_id() ) {
|
189 |
+
update_option( \WC_Facebookcommerce_Integration::OPTION_PRODUCT_CATALOG_ID, sanitize_text_field( $response->get_catalog_id() ) );
|
190 |
+
}
|
191 |
+
|
192 |
+
if ( $response->get_business_manager_id() ) {
|
193 |
+
$this->update_business_manager_id( sanitize_text_field( $response->get_business_manager_id() ) );
|
194 |
+
}
|
195 |
+
|
196 |
+
if ( $response->get_ad_account_id() ) {
|
197 |
+
$this->update_ad_account_id( sanitize_text_field( $response->get_ad_account_id() ) );
|
198 |
+
}
|
199 |
+
}
|
200 |
+
|
201 |
+
|
202 |
+
/**
|
203 |
+
* Processes the returned connection.
|
204 |
+
*
|
205 |
+
* @internal
|
206 |
+
*
|
207 |
+
* @since 2.0.0
|
208 |
+
*/
|
209 |
+
public function handle_connect() {
|
210 |
+
|
211 |
+
// don't handle anything unless the user can manage WooCommerce settings
|
212 |
+
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
213 |
+
return;
|
214 |
+
}
|
215 |
+
|
216 |
+
try {
|
217 |
+
|
218 |
+
if ( empty( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'], self::ACTION_CONNECT ) ) {
|
219 |
+
throw new SV_WC_API_Exception( 'Invalid nonce' );
|
220 |
+
}
|
221 |
+
|
222 |
+
$merchant_access_token = ! empty( $_GET['merchant_access_token'] ) ? sanitize_text_field( $_GET['merchant_access_token'] ) : '';
|
223 |
+
|
224 |
+
if ( ! $merchant_access_token ) {
|
225 |
+
throw new SV_WC_API_Exception( 'Access token is missing' );
|
226 |
+
}
|
227 |
+
|
228 |
+
$system_user_access_token = ! empty( $_GET['system_user_access_token'] ) ? sanitize_text_field( $_GET['system_user_access_token'] ) : '';
|
229 |
+
|
230 |
+
if ( ! $system_user_access_token ) {
|
231 |
+
throw new SV_WC_API_Exception( 'System User access token is missing' );
|
232 |
+
}
|
233 |
+
|
234 |
+
$system_user_id = ! empty( $_GET['system_user_id'] ) ? sanitize_text_field( $_GET['system_user_id'] ) : '';
|
235 |
+
|
236 |
+
if ( ! $system_user_id ) {
|
237 |
+
throw new SV_WC_API_Exception( 'System User ID is missing' );
|
238 |
+
}
|
239 |
+
|
240 |
+
$this->update_access_token( $system_user_access_token );
|
241 |
+
$this->update_merchant_access_token( $merchant_access_token );
|
242 |
+
$this->update_system_user_id( $system_user_id );
|
243 |
+
$this->update_installation_data();
|
244 |
+
|
245 |
+
facebook_for_woocommerce()->get_products_sync_handler()->create_or_update_all_products();
|
246 |
+
|
247 |
+
update_option( 'wc_facebook_has_connected_fbe_2', 'yes' );
|
248 |
+
|
249 |
+
facebook_for_woocommerce()->get_message_handler()->add_message( __( 'Connection complete! Thanks for using Facebook for WooCommerce.', 'facebook-for-woocommerce' ) );
|
250 |
+
|
251 |
+
} catch ( SV_WC_API_Exception $exception ) {
|
252 |
+
|
253 |
+
facebook_for_woocommerce()->log( sprintf( 'Connection failed: %s', $exception->getMessage() ) );
|
254 |
+
|
255 |
+
set_transient( 'wc_facebook_connection_failed', time(), 30 );
|
256 |
+
}
|
257 |
+
|
258 |
+
wp_safe_redirect( facebook_for_woocommerce()->get_settings_url() );
|
259 |
+
exit;
|
260 |
+
}
|
261 |
+
|
262 |
+
|
263 |
+
/**
|
264 |
+
* Disconnects the integration using the Graph API.
|
265 |
+
*
|
266 |
+
* @internal
|
267 |
+
*
|
268 |
+
* @since 2.0.0
|
269 |
+
*/
|
270 |
+
public function handle_disconnect() {
|
271 |
+
|
272 |
+
check_admin_referer( self::ACTION_DISCONNECT );
|
273 |
+
|
274 |
+
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
275 |
+
wp_die( __( 'You do not have permission to uninstall Facebook Business Extension.', 'facebook-for-woocommerce' ) );
|
276 |
+
}
|
277 |
+
|
278 |
+
try {
|
279 |
+
|
280 |
+
$response = facebook_for_woocommerce()->get_api()->get_user();
|
281 |
+
$response = facebook_for_woocommerce()->get_api()->delete_user_permission( $response->get_id(), 'manage_business_extension' );
|
282 |
+
|
283 |
+
$this->disconnect();
|
284 |
+
|
285 |
+
facebook_for_woocommerce()->get_message_handler()->add_message( __( 'Uninstall successful', 'facebook-for-woocommerce' ) );
|
286 |
+
|
287 |
+
} catch ( SV_WC_API_Exception $exception ) {
|
288 |
+
|
289 |
+
facebook_for_woocommerce()->log( sprintf( 'Uninstall failed: %s', $exception->getMessage() ) );
|
290 |
+
|
291 |
+
facebook_for_woocommerce()->get_message_handler()->add_error( __( 'Uninstall unsuccessful. Please try again.', 'facebook-for-woocommerce' ) );
|
292 |
+
}
|
293 |
+
|
294 |
+
wp_safe_redirect( facebook_for_woocommerce()->get_settings_url() );
|
295 |
+
exit;
|
296 |
+
}
|
297 |
+
|
298 |
+
|
299 |
+
/**
|
300 |
+
* Disconnects the plugin.
|
301 |
+
*
|
302 |
+
* Deletes local asset data.
|
303 |
+
*
|
304 |
+
* @since 2.0.0
|
305 |
+
*/
|
306 |
+
private function disconnect() {
|
307 |
+
|
308 |
+
$this->update_access_token( '' );
|
309 |
+
$this->update_merchant_access_token( '' );
|
310 |
+
$this->update_system_user_id( '' );
|
311 |
+
$this->update_business_manager_id( '' );
|
312 |
+
$this->update_ad_account_id( '' );
|
313 |
+
|
314 |
+
update_option( \WC_Facebookcommerce_Integration::SETTING_FACEBOOK_PAGE_ID, '' );
|
315 |
+
update_option( \WC_Facebookcommerce_Integration::SETTING_FACEBOOK_PIXEL_ID, '' );
|
316 |
+
facebook_for_woocommerce()->get_integration()->update_product_catalog_id( '' );
|
317 |
+
|
318 |
+
delete_transient( 'wc_facebook_business_configuration_refresh' );
|
319 |
+
}
|
320 |
+
|
321 |
+
|
322 |
+
/**
|
323 |
+
* Gets the API access token.
|
324 |
+
*
|
325 |
+
* @since 2.0.0
|
326 |
+
*
|
327 |
+
* @return string
|
328 |
+
*/
|
329 |
+
public function get_access_token() {
|
330 |
+
|
331 |
+
$access_token = get_option( self::OPTION_ACCESS_TOKEN, '' );
|
332 |
+
|
333 |
+
/**
|
334 |
+
* Filters the API access token.
|
335 |
+
*
|
336 |
+
* @since 2.0.0
|
337 |
+
*
|
338 |
+
* @param string $access_token access token
|
339 |
+
* @param Connection $connection connection handler instance
|
340 |
+
*/
|
341 |
+
return apply_filters( 'wc_facebook_connection_access_token', $access_token, $this );
|
342 |
+
}
|
343 |
+
|
344 |
+
|
345 |
+
/**
|
346 |
+
* Gets the merchant access token.
|
347 |
+
*
|
348 |
+
* @since 2.0.0
|
349 |
+
*
|
350 |
+
* @return string
|
351 |
+
*/
|
352 |
+
public function get_merchant_access_token() {
|
353 |
+
|
354 |
+
$access_token = get_option( self::OPTION_MERCHANT_ACCESS_TOKEN, '' );
|
355 |
+
|
356 |
+
/**
|
357 |
+
* Filters the merchant access token.
|
358 |
+
*
|
359 |
+
* @since 2.0.0
|
360 |
+
*
|
361 |
+
* @param string $access_token access token
|
362 |
+
* @param Connection $connection connection handler instance
|
363 |
+
*/
|
364 |
+
return apply_filters( 'wc_facebook_connection_merchant_access_token', $access_token, $this );
|
365 |
+
}
|
366 |
+
|
367 |
+
|
368 |
+
/**
|
369 |
+
* Gets the URL to start the connection flow.
|
370 |
+
*
|
371 |
+
* @since 2.0.0
|
372 |
+
*
|
373 |
+
* @return string
|
374 |
+
*/
|
375 |
+
public function get_connect_url() {
|
376 |
+
|
377 |
+
return add_query_arg( rawurlencode_deep( $this->get_connect_parameters() ), self::OAUTH_URL );
|
378 |
+
}
|
379 |
+
|
380 |
+
|
381 |
+
/**
|
382 |
+
* Gets the URL to manage the connection.
|
383 |
+
*
|
384 |
+
* @since 2.0.0
|
385 |
+
*
|
386 |
+
* @return string
|
387 |
+
*/
|
388 |
+
public function get_manage_url() {
|
389 |
+
|
390 |
+
$app_id = $this->get_client_id();
|
391 |
+
$business_id = $this->get_external_business_id();
|
392 |
+
|
393 |
+
return "https://www.facebook.com/facebook_business_extension?app_id={$app_id}&external_business_id={$business_id}";
|
394 |
+
}
|
395 |
+
|
396 |
+
|
397 |
+
/**
|
398 |
+
* Gets the URL for disconnecting.
|
399 |
+
*
|
400 |
+
* @since 2.0.0
|
401 |
+
*
|
402 |
+
* @return string
|
403 |
+
*/
|
404 |
+
public function get_disconnect_url() {
|
405 |
+
|
406 |
+
return wp_nonce_url( add_query_arg( 'action', self::ACTION_DISCONNECT, admin_url( 'admin.php' ) ), self::ACTION_DISCONNECT );
|
407 |
+
}
|
408 |
+
|
409 |
+
|
410 |
+
/**
|
411 |
+
* Gets the scopes that will be requested during the connection flow.
|
412 |
+
*
|
413 |
+
* @since 2.0.0
|
414 |
+
*
|
415 |
+
* @link https://developers.facebook.com/docs/marketing-api/access/#access_token
|
416 |
+
*
|
417 |
+
* @return string[]
|
418 |
+
*/
|
419 |
+
public function get_scopes() {
|
420 |
+
|
421 |
+
$scopes = [
|
422 |
+
'manage_business_extension',
|
423 |
+
'catalog_management',
|
424 |
+
'business_management',
|
425 |
+
'ads_management',
|
426 |
+
'ads_read',
|
427 |
+
];
|
428 |
+
|
429 |
+
/**
|
430 |
+
* Filters the scopes that will be requested during the connection flow.
|
431 |
+
*
|
432 |
+
* @since 2.0.0
|
433 |
+
*
|
434 |
+
* @param string[] $scopes connection scopes
|
435 |
+
* @param Connection $connection connection handler instance
|
436 |
+
*/
|
437 |
+
return (array) apply_filters( 'wc_facebook_connection_scopes', $scopes, $this );
|
438 |
+
}
|
439 |
+
|
440 |
+
|
441 |
+
/**
|
442 |
+
* Gets the stored external business ID.
|
443 |
+
*
|
444 |
+
* @since 2.0.0
|
445 |
+
*
|
446 |
+
* @return string
|
447 |
+
*/
|
448 |
+
public function get_external_business_id() {
|
449 |
+
|
450 |
+
if ( ! is_string( $this->external_business_id ) ) {
|
451 |
+
|
452 |
+
$value = get_option( self::OPTION_EXTERNAL_BUSINESS_ID );
|
453 |
+
|
454 |
+
if ( ! is_string( $value ) ) {
|
455 |
+
|
456 |
+
$value = sanitize_title( get_bloginfo( 'name' ) ) . '-' . uniqid();
|
457 |
+
|
458 |
+
update_option( self::OPTION_EXTERNAL_BUSINESS_ID, $value );
|
459 |
+
}
|
460 |
+
|
461 |
+
$this->external_business_id = $value;
|
462 |
+
}
|
463 |
+
|
464 |
+
/**
|
465 |
+
* Filters the external business ID.
|
466 |
+
*
|
467 |
+
* @since 2.0.0
|
468 |
+
*
|
469 |
+
* @param string $external_business_id stored external business ID
|
470 |
+
* @param Connection $connection connection handler instance
|
471 |
+
*/
|
472 |
+
return (string) apply_filters( 'wc_facebook_external_business_id', $this->external_business_id, $this );
|
473 |
+
}
|
474 |
+
|
475 |
+
|
476 |
+
/**
|
477 |
+
* Gets the site's business name.
|
478 |
+
*
|
479 |
+
* @since 2.0.0
|
480 |
+
*
|
481 |
+
* @return string
|
482 |
+
*/
|
483 |
+
public function get_business_name() {
|
484 |
+
|
485 |
+
$business_name = html_entity_decode( get_bloginfo( 'name' ), ENT_QUOTES, 'UTF-8' );
|
486 |
+
|
487 |
+
/**
|
488 |
+
* Filters the shop's business name.
|
489 |
+
*
|
490 |
+
* This is passed to Facebook when connecting. Defaults to the site name.
|
491 |
+
*
|
492 |
+
* @since 2.0.0
|
493 |
+
*
|
494 |
+
* @param string $business_name the shop's business name
|
495 |
+
*/
|
496 |
+
return apply_filters( 'wc_facebook_connection_business_name', $business_name );
|
497 |
+
}
|
498 |
+
|
499 |
+
|
500 |
+
/**
|
501 |
+
* Gets the business manager ID value.
|
502 |
+
*
|
503 |
+
* @since 2.0.0
|
504 |
+
*
|
505 |
+
* @return string
|
506 |
+
*/
|
507 |
+
public function get_business_manager_id() {
|
508 |
+
|
509 |
+
return get_option( self::OPTION_BUSINESS_MANAGER_ID, '' );
|
510 |
+
}
|
511 |
+
|
512 |
+
|
513 |
+
/**
|
514 |
+
* Gets the ad account ID value.
|
515 |
+
*
|
516 |
+
* @since 2.0.0
|
517 |
+
*
|
518 |
+
* @return string
|
519 |
+
*/
|
520 |
+
public function get_ad_account_id() {
|
521 |
+
|
522 |
+
return get_option( self::OPTION_AD_ACCOUNT_ID, '' );
|
523 |
+
}
|
524 |
+
|
525 |
+
|
526 |
+
/**
|
527 |
+
* Gets the System User ID value.
|
528 |
+
*
|
529 |
+
* @since 2.0.0
|
530 |
+
*
|
531 |
+
* @return string
|
532 |
+
*/
|
533 |
+
public function get_system_user_id() {
|
534 |
+
|
535 |
+
return get_option( self::OPTION_SYSTEM_USER_ID, '' );
|
536 |
+
}
|
537 |
+
|
538 |
+
|
539 |
+
/**
|
540 |
+
* Gets the proxy URL.
|
541 |
+
*
|
542 |
+
* @since 2.0.0
|
543 |
+
*
|
544 |
+
* @return string URL
|
545 |
+
*/
|
546 |
+
public function get_proxy_url() {
|
547 |
+
|
548 |
+
/**
|
549 |
+
* Filters the proxy URL.
|
550 |
+
*
|
551 |
+
* @since 2.0.0
|
552 |
+
*
|
553 |
+
* @param string $proxy_url the connection proxy URL
|
554 |
+
*/
|
555 |
+
return (string) apply_filters( 'wc_facebook_connection_proxy_url', self::PROXY_URL );
|
556 |
+
}
|
557 |
+
|
558 |
+
|
559 |
+
/**
|
560 |
+
* Gets the full redirect URL where the user will return to after OAuth.
|
561 |
+
*
|
562 |
+
* @since 2.0.0
|
563 |
+
*
|
564 |
+
* @return string
|
565 |
+
*/
|
566 |
+
public function get_redirect_url() {
|
567 |
+
|
568 |
+
$redirect_url = add_query_arg( [
|
569 |
+
'wc-api' => self::ACTION_CONNECT,
|
570 |
+
'external_business_id' => $this->get_external_business_id(),
|
571 |
+
'nonce' => wp_create_nonce( self::ACTION_CONNECT ),
|
572 |
+
], home_url( '/' ) );
|
573 |
+
|
574 |
+
/**
|
575 |
+
* Filters the redirect URL where the user will return to after OAuth.
|
576 |
+
*
|
577 |
+
* @since 2.0.0
|
578 |
+
*
|
579 |
+
* @param string $redirect_url redirect URL
|
580 |
+
* @param Connection $connection connection handler instance
|
581 |
+
*/
|
582 |
+
return (string) apply_filters( 'wc_facebook_connection_redirect_url', $redirect_url, $this );
|
583 |
+
}
|
584 |
+
|
585 |
+
|
586 |
+
/**
|
587 |
+
* Gets the full set of connection parameters for starting OAuth.
|
588 |
+
*
|
589 |
+
* @since 2.0.0
|
590 |
+
*
|
591 |
+
* @return array
|
592 |
+
*/
|
593 |
+
public function get_connect_parameters() {
|
594 |
+
|
595 |
+
/**
|
596 |
+
* Filters the connection parameters.
|
597 |
+
*
|
598 |
+
* @since 2.0.0
|
599 |
+
*
|
600 |
+
* @param array $parameters connection parameters
|
601 |
+
*/
|
602 |
+
return apply_filters( 'wc_facebook_connection_parameters', [
|
603 |
+
'client_id' => $this->get_client_id(),
|
604 |
+
'redirect_uri' => $this->get_proxy_url(),
|
605 |
+
'state' => $this->get_redirect_url(),
|
606 |
+
'display' => 'page',
|
607 |
+
'response_type' => 'code',
|
608 |
+
'scope' => implode( ',', $this->get_scopes() ),
|
609 |
+
'extras' => json_encode( $this->get_connect_parameters_extras() ),
|
610 |
+
] );
|
611 |
+
}
|
612 |
+
|
613 |
+
|
614 |
+
/**
|
615 |
+
* Gets connection parameters extras.
|
616 |
+
*
|
617 |
+
* @see Connection::get_connect_parameters()
|
618 |
+
*
|
619 |
+
* @since 2.0.0
|
620 |
+
*
|
621 |
+
* @return array associative array (to be converted to JSON encoded for connection purposes)
|
622 |
+
*/
|
623 |
+
private function get_connect_parameters_extras() {
|
624 |
+
|
625 |
+
$parameters = [
|
626 |
+
'setup' => [
|
627 |
+
'external_business_id' => $this->get_external_business_id(),
|
628 |
+
'timezone' => $this->get_timezone_string(),
|
629 |
+
'currency' => get_woocommerce_currency(),
|
630 |
+
'business_vertical' => 'ECOMMERCE',
|
631 |
+
],
|
632 |
+
'business_config' => [
|
633 |
+
'business' => [
|
634 |
+
'name' => $this->get_business_name(),
|
635 |
+
],
|
636 |
+
],
|
637 |
+
'repeat' => false,
|
638 |
+
];
|
639 |
+
|
640 |
+
if ( $external_merchant_settings_id = facebook_for_woocommerce()->get_integration()->get_external_merchant_settings_id() ) {
|
641 |
+
$parameters['setup']['merchant_settings_id'] = $external_merchant_settings_id;
|
642 |
+
}
|
643 |
+
|
644 |
+
// if messenger was previously enabled
|
645 |
+
if ( facebook_for_woocommerce()->get_integration()->is_messenger_enabled() ) {
|
646 |
+
|
647 |
+
$parameters['business_config']['messenger_chat'] = [
|
648 |
+
'enabled' => true,
|
649 |
+
'domains' => home_url( '/' ),
|
650 |
+
];
|
651 |
+
}
|
652 |
+
|
653 |
+
return $parameters;
|
654 |
+
}
|
655 |
+
|
656 |
+
|
657 |
+
/**
|
658 |
+
* Gets the configured timezone string using values accepted by Facebook
|
659 |
+
*
|
660 |
+
* @since 2.0.0
|
661 |
+
*
|
662 |
+
* @return string
|
663 |
+
*/
|
664 |
+
private function get_timezone_string() {
|
665 |
+
|
666 |
+
$timezone = wc_timezone_string();
|
667 |
+
|
668 |
+
// convert +05:30 and +05:00 into Etc/GMT+5 - we ignore the minutes because Facebook does not allow minute offsets
|
669 |
+
if ( preg_match( '/([+-])(\d{2}):\d{2}/', $timezone, $matches ) ) {
|
670 |
+
|
671 |
+
$hours = (int) $matches[2];
|
672 |
+
$timezone = "Etc/GMT{$matches[1]}{$hours}";
|
673 |
+
}
|
674 |
+
|
675 |
+
return $timezone;
|
676 |
+
}
|
677 |
+
|
678 |
+
|
679 |
+
/**
|
680 |
+
* Stores the given ID value.
|
681 |
+
*
|
682 |
+
* @since 2.0.0
|
683 |
+
*
|
684 |
+
* @param string $value the business manager ID
|
685 |
+
*/
|
686 |
+
public function update_business_manager_id( $value ) {
|
687 |
+
|
688 |
+
update_option( self::OPTION_BUSINESS_MANAGER_ID, $value );
|
689 |
+
}
|
690 |
+
|
691 |
+
|
692 |
+
/**
|
693 |
+
* Stores the given ID value.
|
694 |
+
*
|
695 |
+
* @since 2.0.0
|
696 |
+
*
|
697 |
+
* @param string $value the ad account ID
|
698 |
+
*/
|
699 |
+
public function update_ad_account_id( $value ) {
|
700 |
+
|
701 |
+
update_option( self::OPTION_AD_ACCOUNT_ID, $value );
|
702 |
+
}
|
703 |
+
|
704 |
+
|
705 |
+
/**
|
706 |
+
* Stores the given system user ID.
|
707 |
+
*
|
708 |
+
* @since 2.0.0
|
709 |
+
*
|
710 |
+
* @param string $value the ID
|
711 |
+
*/
|
712 |
+
public function update_system_user_id( $value ) {
|
713 |
+
|
714 |
+
update_option( self::OPTION_SYSTEM_USER_ID, $value );
|
715 |
+
}
|
716 |
+
|
717 |
+
|
718 |
+
/**
|
719 |
+
* Stores the given token value.
|
720 |
+
*
|
721 |
+
* @since 2.0.0
|
722 |
+
*
|
723 |
+
* @param string $value the access token
|
724 |
+
*/
|
725 |
+
public function update_access_token( $value ) {
|
726 |
+
|
727 |
+
update_option( self::OPTION_ACCESS_TOKEN, $value );
|
728 |
+
}
|
729 |
+
|
730 |
+
|
731 |
+
/**
|
732 |
+
* Stores the given merchant access token.
|
733 |
+
*
|
734 |
+
* @since 2.0.0
|
735 |
+
*
|
736 |
+
* @param string $value the access token
|
737 |
+
*/
|
738 |
+
public function update_merchant_access_token( $value ) {
|
739 |
+
|
740 |
+
update_option( self::OPTION_MERCHANT_ACCESS_TOKEN, $value );
|
741 |
+
}
|
742 |
+
|
743 |
+
|
744 |
+
/**
|
745 |
+
* Determines whether the site is connected.
|
746 |
+
*
|
747 |
+
* A site is connected if there is an access token stored.
|
748 |
+
*
|
749 |
+
* @since 2.0.0
|
750 |
+
*
|
751 |
+
* @return bool
|
752 |
+
*/
|
753 |
+
public function is_connected() {
|
754 |
+
|
755 |
+
return (bool) $this->get_access_token();
|
756 |
+
}
|
757 |
+
|
758 |
+
|
759 |
+
/**
|
760 |
+
* Determines whether the site has previously connected to FBE 2.
|
761 |
+
*
|
762 |
+
* @since 2.0.0
|
763 |
+
*
|
764 |
+
* @return bool
|
765 |
+
*/
|
766 |
+
public function has_previously_connected_fbe_2() {
|
767 |
+
|
768 |
+
return 'yes' === get_option( 'wc_facebook_has_connected_fbe_2' );
|
769 |
+
}
|
770 |
+
|
771 |
+
|
772 |
+
/**
|
773 |
+
* Determines whether the site has previously connected to FBE 1.x.
|
774 |
+
*
|
775 |
+
* @since 2.0.0
|
776 |
+
*
|
777 |
+
* @return bool
|
778 |
+
*/
|
779 |
+
public function has_previously_connected_fbe_1() {
|
780 |
+
|
781 |
+
$integration = $this->get_plugin()->get_integration();
|
782 |
+
|
783 |
+
return $integration && $integration->get_external_merchant_settings_id();
|
784 |
+
}
|
785 |
+
|
786 |
+
|
787 |
+
/**
|
788 |
+
* Gets the client ID for connection.
|
789 |
+
*
|
790 |
+
* @since 2.0.0
|
791 |
+
*
|
792 |
+
* @return string
|
793 |
+
*/
|
794 |
+
private function get_client_id() {
|
795 |
+
|
796 |
+
/**
|
797 |
+
* Filters the client ID.
|
798 |
+
*
|
799 |
+
* @since 2.0.0
|
800 |
+
*
|
801 |
+
* @param string $client_id the client ID
|
802 |
+
*/
|
803 |
+
return apply_filters( 'wc_facebook_connection_client_id', self::CLIENT_ID );
|
804 |
+
}
|
805 |
+
|
806 |
+
|
807 |
+
/**
|
808 |
+
* Gets the plugin instance.
|
809 |
+
*
|
810 |
+
* @since 2.0.0
|
811 |
+
*
|
812 |
+
* @return \WC_Facebookcommerce
|
813 |
+
*/
|
814 |
+
public function get_plugin() {
|
815 |
+
|
816 |
+
return $this->plugin;
|
817 |
+
}
|
818 |
+
|
819 |
+
|
820 |
+
}
|
includes/Lifecycle.php
CHANGED
@@ -39,7 +39,7 @@ class Lifecycle extends Framework\Plugin\Lifecycle {
|
|
39 |
'1.10.0',
|
40 |
'1.10.1',
|
41 |
'1.11.0',
|
42 |
-
'
|
43 |
];
|
44 |
}
|
45 |
|
@@ -219,18 +219,50 @@ class Lifecycle extends Framework\Plugin\Lifecycle {
|
|
219 |
|
220 |
|
221 |
/**
|
222 |
-
* Upgrades to version
|
223 |
*
|
224 |
-
* @since
|
225 |
*/
|
226 |
-
protected function
|
227 |
|
228 |
-
|
|
|
229 |
|
230 |
// create_job() expects an non-empty array of attributes
|
231 |
$handler->create_job( [ 'created_at' => current_time( 'mysql' ) ] );
|
232 |
$handler->dispatch();
|
233 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
234 |
}
|
235 |
|
236 |
|
39 |
'1.10.0',
|
40 |
'1.10.1',
|
41 |
'1.11.0',
|
42 |
+
'2.0.0',
|
43 |
];
|
44 |
}
|
45 |
|
219 |
|
220 |
|
221 |
/**
|
222 |
+
* Upgrades to version 2.0.0
|
223 |
*
|
224 |
+
* @since 2.0.0
|
225 |
*/
|
226 |
+
protected function upgrade_to_2_0_0() {
|
227 |
|
228 |
+
// handle sync enabled and visible virtual products and variations
|
229 |
+
if ( $handler = $this->get_plugin()->get_background_handle_virtual_products_variations_instance() ) {
|
230 |
|
231 |
// create_job() expects an non-empty array of attributes
|
232 |
$handler->create_job( [ 'created_at' => current_time( 'mysql' ) ] );
|
233 |
$handler->dispatch();
|
234 |
}
|
235 |
+
|
236 |
+
update_option( 'wc_facebook_has_connected_fbe_2', 'no' );
|
237 |
+
|
238 |
+
$settings = get_option( 'woocommerce_facebookcommerce_settings' );
|
239 |
+
|
240 |
+
if ( is_array( $settings ) ) {
|
241 |
+
|
242 |
+
$settings_map = [
|
243 |
+
'facebook_pixel_id' => \WC_Facebookcommerce_Integration::SETTING_FACEBOOK_PIXEL_ID,
|
244 |
+
'facebook_page_id' => \WC_Facebookcommerce_Integration::SETTING_FACEBOOK_PAGE_ID,
|
245 |
+
'enable_product_sync' => \WC_Facebookcommerce_Integration::SETTING_ENABLE_PRODUCT_SYNC,
|
246 |
+
'excluded_product_category_ids' => \WC_Facebookcommerce_Integration::SETTING_EXCLUDED_PRODUCT_CATEGORY_IDS,
|
247 |
+
'excluded_product_tag_ids' => \WC_Facebookcommerce_Integration::SETTING_EXCLUDED_PRODUCT_TAG_IDS,
|
248 |
+
'product_description_mode' => \WC_Facebookcommerce_Integration::SETTING_PRODUCT_DESCRIPTION_MODE,
|
249 |
+
'enable_messenger' => \WC_Facebookcommerce_Integration::SETTING_ENABLE_MESSENGER,
|
250 |
+
'messenger_locale' => \WC_Facebookcommerce_Integration::SETTING_MESSENGER_LOCALE,
|
251 |
+
'messenger_greeting' => \WC_Facebookcommerce_Integration::SETTING_MESSENGER_GREETING,
|
252 |
+
'messenger_color_hex' => \WC_Facebookcommerce_Integration::SETTING_MESSENGER_COLOR_HEX,
|
253 |
+
'enable_debug_mode' => \WC_Facebookcommerce_Integration::SETTING_ENABLE_DEBUG_MODE,
|
254 |
+
];
|
255 |
+
|
256 |
+
foreach ( $settings_map as $old_name => $new_name ) {
|
257 |
+
|
258 |
+
if ( ! empty( $settings[ $old_name ] ) ) {
|
259 |
+
update_option( $new_name, $settings[ $old_name ] );
|
260 |
+
}
|
261 |
+
}
|
262 |
+
}
|
263 |
+
|
264 |
+
// deletes an option that is not longer used to generate an admin notice
|
265 |
+
delete_option( 'fb_cart_url' );
|
266 |
}
|
267 |
|
268 |
|
includes/Products.php
CHANGED
@@ -73,12 +73,6 @@ class Products {
|
|
73 |
|
74 |
if ( $product_variation instanceof \WC_Product ) {
|
75 |
|
76 |
-
if ( $enabled && $product_variation->is_virtual() ) {
|
77 |
-
|
78 |
-
// never enable sync for virtual variations
|
79 |
-
continue;
|
80 |
-
}
|
81 |
-
|
82 |
$product_variation->update_meta_data( self::SYNC_ENABLED_META_KEY, $enabled );
|
83 |
$product_variation->save_meta_data();
|
84 |
}
|
@@ -120,6 +114,51 @@ class Products {
|
|
120 |
}
|
121 |
|
122 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
123 |
/**
|
124 |
* Determines whether the given product should be synced.
|
125 |
*
|
@@ -141,6 +180,22 @@ class Products {
|
|
141 |
}
|
142 |
|
143 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
144 |
/**
|
145 |
* Determines whether a product is enabled to be synced in Facebook.
|
146 |
*
|
@@ -250,7 +305,33 @@ class Products {
|
|
250 |
|
251 |
// accounts for a legacy bool value, current should be (string) 'yes' or (string) 'no'
|
252 |
if ( ! isset( self::$products_visibility[ $product->get_id() ] ) ) {
|
253 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
254 |
}
|
255 |
|
256 |
return self::$products_visibility[ $product->get_id() ];
|
73 |
|
74 |
if ( $product_variation instanceof \WC_Product ) {
|
75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
$product_variation->update_meta_data( self::SYNC_ENABLED_META_KEY, $enabled );
|
77 |
$product_variation->save_meta_data();
|
78 |
}
|
114 |
}
|
115 |
|
116 |
|
117 |
+
/**
|
118 |
+
* Disables sync for products that belong to the given category or tag.
|
119 |
+
*
|
120 |
+
* @since 2.0.0
|
121 |
+
*
|
122 |
+
* @param array $args {
|
123 |
+
* @type string|array $taxonomy product_cat or product_tag
|
124 |
+
* @type string|array $include array or comma/space-separated string of term IDs to include
|
125 |
+
* }
|
126 |
+
*/
|
127 |
+
public static function disable_sync_for_products_with_terms( array $args ) {
|
128 |
+
|
129 |
+
$args = wp_parse_args( $args, [
|
130 |
+
'taxonomy' => 'product_cat',
|
131 |
+
'include' => [],
|
132 |
+
] );
|
133 |
+
|
134 |
+
$products = [];
|
135 |
+
|
136 |
+
// get all products belonging to the given terms
|
137 |
+
if ( is_array( $args['include'] ) && ! empty( $args['include'] ) ) {
|
138 |
+
|
139 |
+
$terms = get_terms( [
|
140 |
+
'taxonomy' => $args['taxonomy'],
|
141 |
+
'fields' => 'slugs',
|
142 |
+
'include' => array_map( 'intval', $args['include'] ),
|
143 |
+
] );
|
144 |
+
|
145 |
+
if ( ! is_wp_error( $terms ) && ! empty( $terms ) ) {
|
146 |
+
|
147 |
+
$taxonomy = $args['taxonomy'] === 'product_tag' ? 'tag' : 'category';
|
148 |
+
|
149 |
+
$products = wc_get_products( [
|
150 |
+
$taxonomy => $terms,
|
151 |
+
'limit' => -1,
|
152 |
+
] );
|
153 |
+
}
|
154 |
+
}
|
155 |
+
|
156 |
+
if ( ! empty( $products ) ) {
|
157 |
+
Products::disable_sync_for_products( $products );
|
158 |
+
}
|
159 |
+
}
|
160 |
+
|
161 |
+
|
162 |
/**
|
163 |
* Determines whether the given product should be synced.
|
164 |
*
|
180 |
}
|
181 |
|
182 |
|
183 |
+
/**
|
184 |
+
* Determines whether the given product should be removed from the catalog.
|
185 |
+
*
|
186 |
+
* A product should be removed if it is no longer in stock and the user has opted-in to hide products that are out of stock.
|
187 |
+
*
|
188 |
+
* @since 2.0.0
|
189 |
+
*
|
190 |
+
* @param \WC_Product $product
|
191 |
+
* @return bool
|
192 |
+
*/
|
193 |
+
public static function product_should_be_deleted( \WC_Product $product ) {
|
194 |
+
|
195 |
+
return 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) && ! $product->is_in_stock();
|
196 |
+
}
|
197 |
+
|
198 |
+
|
199 |
/**
|
200 |
* Determines whether a product is enabled to be synced in Facebook.
|
201 |
*
|
305 |
|
306 |
// accounts for a legacy bool value, current should be (string) 'yes' or (string) 'no'
|
307 |
if ( ! isset( self::$products_visibility[ $product->get_id() ] ) ) {
|
308 |
+
|
309 |
+
if ( $product->is_type( 'variable' ) ) {
|
310 |
+
|
311 |
+
// assume variable products are not visible until a visible child is found
|
312 |
+
$is_visible = false;
|
313 |
+
|
314 |
+
foreach ( $product->get_children() as $child_id ) {
|
315 |
+
|
316 |
+
$child_product = wc_get_product( $child_id );
|
317 |
+
|
318 |
+
if ( $child_product && self::is_product_visible( $child_product ) ) {
|
319 |
+
|
320 |
+
$is_visible = true;
|
321 |
+
break;
|
322 |
+
}
|
323 |
+
}
|
324 |
+
|
325 |
+
} elseif ( $meta = $product->get_meta( self::VISIBILITY_META_KEY ) ) {
|
326 |
+
|
327 |
+
$is_visible = wc_string_to_bool( $product->get_meta( self::VISIBILITY_META_KEY ) );
|
328 |
+
|
329 |
+
} else {
|
330 |
+
|
331 |
+
$is_visible = true;
|
332 |
+
}
|
333 |
+
|
334 |
+
self::$products_visibility[ $product->get_id() ] = $is_visible;
|
335 |
}
|
336 |
|
337 |
return self::$products_visibility[ $product->get_id() ];
|
includes/Products/Sync.php
ADDED
@@ -0,0 +1,211 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\Products;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\Products;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* The product sync handler.
|
19 |
+
*
|
20 |
+
* @since 2.0.0
|
21 |
+
*/
|
22 |
+
class Sync {
|
23 |
+
|
24 |
+
|
25 |
+
/** @var string the prefix used in the array indexes */
|
26 |
+
const PRODUCT_INDEX_PREFIX = 'p-';
|
27 |
+
|
28 |
+
/** @var string the update action */
|
29 |
+
const ACTION_UPDATE = 'UPDATE';
|
30 |
+
|
31 |
+
/** @var string the delete action */
|
32 |
+
const ACTION_DELETE = 'DELETE';
|
33 |
+
|
34 |
+
/** @var array the array of requests to schedule for sync */
|
35 |
+
protected $requests = [];
|
36 |
+
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Sync constructor.
|
40 |
+
*
|
41 |
+
* @since 2.0.0
|
42 |
+
*/
|
43 |
+
public function __construct() {
|
44 |
+
|
45 |
+
$this->add_hooks();
|
46 |
+
}
|
47 |
+
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Adds needed hooks to support product sync.
|
51 |
+
*
|
52 |
+
* @since 2.0.0
|
53 |
+
*/
|
54 |
+
public function add_hooks() {
|
55 |
+
|
56 |
+
add_action( 'shutdown', [ $this, 'schedule_sync' ] );
|
57 |
+
}
|
58 |
+
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Adds all eligible product IDs to the requests array to be created or updated.
|
62 |
+
*
|
63 |
+
* Uses the same logic that the feed handler uses to get a list of product IDs to sync.
|
64 |
+
*
|
65 |
+
* TODO: consolidate the logic to decide whether a product should be synced in one or a couple of helper methods - right now we have slightly different versions of the same code in different places {WV 2020-05-25}
|
66 |
+
*
|
67 |
+
* @see \WC_Facebook_Product_Feed::get_product_ids()
|
68 |
+
* @see \WC_Facebook_Product_Feed::write_product_feed_file()
|
69 |
+
*
|
70 |
+
* @since 2.0.0
|
71 |
+
*/
|
72 |
+
public function create_or_update_all_products() {
|
73 |
+
|
74 |
+
$product_ids = [];
|
75 |
+
$parent_product_ids = [];
|
76 |
+
|
77 |
+
// loop through all published products and product variations to get their IDs
|
78 |
+
$args = [
|
79 |
+
'fields' => 'id=>parent',
|
80 |
+
'post_status' => 'publish',
|
81 |
+
'post_type' => [ 'product', 'product_variation' ],
|
82 |
+
'posts_per_page' => -1,
|
83 |
+
];
|
84 |
+
|
85 |
+
foreach ( get_posts( $args ) as $post_id => $parent_id ) {
|
86 |
+
|
87 |
+
if ( 'product_variation' === get_post_type( $post_id ) ) {
|
88 |
+
|
89 |
+
// keep track of all parents to remove them from the list of products to sync
|
90 |
+
$parent_product_ids[] = $parent_id;
|
91 |
+
|
92 |
+
// include variations with published parents only
|
93 |
+
if ( 'publish' === get_post_status( $parent_id ) ) {
|
94 |
+
$product_ids[] = $post_id;
|
95 |
+
}
|
96 |
+
|
97 |
+
} else {
|
98 |
+
|
99 |
+
$product_ids[] = $post_id;
|
100 |
+
}
|
101 |
+
}
|
102 |
+
|
103 |
+
// remove parent products because those can't be represented as Product Items
|
104 |
+
$product_ids = array_diff( $product_ids, $parent_product_ids );
|
105 |
+
|
106 |
+
// make sure the product should be synced and add it to the sync queue
|
107 |
+
foreach ( $product_ids as $product_id ) {
|
108 |
+
|
109 |
+
$woo_product = new \WC_Facebook_Product( $product_id );
|
110 |
+
|
111 |
+
if ( $woo_product->is_hidden() ) {
|
112 |
+
continue;
|
113 |
+
}
|
114 |
+
|
115 |
+
if ( get_option( 'woocommerce_hide_out_of_stock_items' ) === 'yes' && ! $woo_product->is_in_stock() ) {
|
116 |
+
continue;
|
117 |
+
}
|
118 |
+
|
119 |
+
// skip if not enabled for sync
|
120 |
+
if ( $woo_product->woo_product instanceof \WC_Product && ! Products::product_should_be_synced( $woo_product->woo_product ) ) {
|
121 |
+
continue;
|
122 |
+
}
|
123 |
+
|
124 |
+
$this->create_or_update_products( [ $product_id ] );
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Adds the given product IDs to the requests array to be updated.
|
131 |
+
*
|
132 |
+
* @since 2.0.0
|
133 |
+
*
|
134 |
+
* @param int[] $product_ids
|
135 |
+
*/
|
136 |
+
public function create_or_update_products( array $product_ids ) {
|
137 |
+
|
138 |
+
foreach ( $product_ids as $product_id ) {
|
139 |
+
$this->requests[ $this->get_product_index( $product_id ) ] = self::ACTION_UPDATE;
|
140 |
+
}
|
141 |
+
}
|
142 |
+
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Adds the given retailer IDs to the requests array to be deleted.
|
146 |
+
*
|
147 |
+
* @since 2.0.0
|
148 |
+
*
|
149 |
+
* @param int[] $retailer retailer IDs to delete
|
150 |
+
*/
|
151 |
+
public function delete_products( array $retailer_ids ) {
|
152 |
+
|
153 |
+
foreach ( $retailer_ids as $retailer_id ) {
|
154 |
+
$this->requests[ $retailer_id ] = self::ACTION_DELETE;
|
155 |
+
}
|
156 |
+
}
|
157 |
+
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Creates a background job to sync the products in the requests array.
|
161 |
+
*
|
162 |
+
* @since 2.0.0
|
163 |
+
*
|
164 |
+
* @return \stdClass|object|null
|
165 |
+
*/
|
166 |
+
public function schedule_sync() {
|
167 |
+
|
168 |
+
if ( ! empty( $this->requests ) ) {
|
169 |
+
|
170 |
+
$job_handler = facebook_for_woocommerce()->get_products_sync_background_handler();
|
171 |
+
$job = $job_handler->create_job( [ 'requests' => $this->requests ] );
|
172 |
+
|
173 |
+
$job_handler->dispatch();
|
174 |
+
|
175 |
+
return $job;
|
176 |
+
}
|
177 |
+
}
|
178 |
+
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Gets the prefixed product ID used as the array index.
|
182 |
+
*
|
183 |
+
* @since 2.0.0
|
184 |
+
*
|
185 |
+
* @param $product_id
|
186 |
+
* @return string
|
187 |
+
*/
|
188 |
+
private function get_product_index( $product_id ) {
|
189 |
+
|
190 |
+
return self::PRODUCT_INDEX_PREFIX . $product_id;
|
191 |
+
}
|
192 |
+
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Determines whether a sync is currently in progress.
|
196 |
+
*
|
197 |
+
* @since 2.0.0
|
198 |
+
*
|
199 |
+
* @return bool
|
200 |
+
*/
|
201 |
+
public static function is_sync_in_progress() {
|
202 |
+
|
203 |
+
$jobs = facebook_for_woocommerce()->get_products_sync_background_handler()->get_jobs( [
|
204 |
+
'status' => 'processing',
|
205 |
+
] );
|
206 |
+
|
207 |
+
return ! empty( $jobs );
|
208 |
+
}
|
209 |
+
|
210 |
+
|
211 |
+
}
|
includes/Products/Sync/Background.php
ADDED
@@ -0,0 +1,354 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
|
4 |
+
*
|
5 |
+
* This source code is licensed under the license found in the
|
6 |
+
* LICENSE file in the root directory of this source tree.
|
7 |
+
*
|
8 |
+
* @package FacebookCommerce
|
9 |
+
*/
|
10 |
+
|
11 |
+
namespace SkyVerge\WooCommerce\Facebook\Products\Sync;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
use SkyVerge\WooCommerce\Facebook\Products\Sync;
|
16 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* The background sync handler.
|
20 |
+
*
|
21 |
+
* @since 2.0.0
|
22 |
+
*/
|
23 |
+
class Background extends Framework\SV_WP_Background_Job_Handler {
|
24 |
+
|
25 |
+
|
26 |
+
/** @var string async request prefix */
|
27 |
+
protected $prefix = 'wc_facebook';
|
28 |
+
|
29 |
+
/** @var string async request action */
|
30 |
+
protected $action = 'background_product_sync';
|
31 |
+
|
32 |
+
/** @var string data key */
|
33 |
+
protected $data_key = 'requests';
|
34 |
+
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Processes a job.
|
38 |
+
*
|
39 |
+
* @since 2.0.0
|
40 |
+
*
|
41 |
+
* @param \stdClass|object $job
|
42 |
+
* @param int|null $items_per_batch number of items to process in a single request (defaults to null for unlimited)
|
43 |
+
* @throws \Exception when job data is incorrect
|
44 |
+
* @return \stdClass $job
|
45 |
+
*/
|
46 |
+
public function process_job( $job, $items_per_batch = null ) {
|
47 |
+
|
48 |
+
if ( ! $this->start_time ) {
|
49 |
+
$this->start_time = time();
|
50 |
+
}
|
51 |
+
|
52 |
+
// Indicate that the job has started processing
|
53 |
+
if ( 'processing' !== $job->status ) {
|
54 |
+
|
55 |
+
$job->status = 'processing';
|
56 |
+
$job->started_processing_at = current_time( 'mysql' );
|
57 |
+
|
58 |
+
$job = $this->update_job( $job );
|
59 |
+
}
|
60 |
+
|
61 |
+
$data_key = $this->data_key;
|
62 |
+
|
63 |
+
if ( ! isset( $job->{$data_key} ) ) {
|
64 |
+
throw new \Exception( sprintf( __( 'Job data key "%s" not set', 'woocommerce-plugin-framework' ), $data_key ) );
|
65 |
+
}
|
66 |
+
|
67 |
+
if ( ! is_array( $job->{$data_key} ) ) {
|
68 |
+
throw new \Exception( sprintf( __( 'Job data key "%s" is not an array', 'woocommerce-plugin-framework' ), $data_key ) );
|
69 |
+
}
|
70 |
+
|
71 |
+
$data = $job->{$data_key};
|
72 |
+
|
73 |
+
$job->total = count( $data );
|
74 |
+
|
75 |
+
// progress indicates how many items have been processed, it
|
76 |
+
// does NOT indicate the processed item key in any way
|
77 |
+
if ( ! isset( $job->progress ) ) {
|
78 |
+
$job->progress = 0;
|
79 |
+
}
|
80 |
+
|
81 |
+
// skip already processed items
|
82 |
+
if ( $job->progress && ! empty( $data ) ) {
|
83 |
+
$data = array_slice( $data, $job->progress, null, true );
|
84 |
+
}
|
85 |
+
|
86 |
+
// loop over unprocessed items and process them
|
87 |
+
if ( ! empty( $data ) ) {
|
88 |
+
$this->process_items( $job, $data, (int) $items_per_batch );
|
89 |
+
}
|
90 |
+
|
91 |
+
// complete current job
|
92 |
+
if ( $job->progress >= count( $job->{$data_key} ) ) {
|
93 |
+
$job = $this->complete_job( $job );
|
94 |
+
}
|
95 |
+
|
96 |
+
return $job;
|
97 |
+
}
|
98 |
+
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Processes multiple items.
|
102 |
+
*
|
103 |
+
* @since 2.0.0
|
104 |
+
*
|
105 |
+
* @param \stdClass|object $job
|
106 |
+
* @param array $data
|
107 |
+
* @param int|null $items_per_batch number of items to process in a single request (defaults to null for unlimited)
|
108 |
+
*/
|
109 |
+
public function process_items( $job, $data, $items_per_batch = null ) {
|
110 |
+
|
111 |
+
$processed = 0;
|
112 |
+
$requests = [];
|
113 |
+
|
114 |
+
foreach ( $data as $item_id => $method ) {
|
115 |
+
|
116 |
+
try {
|
117 |
+
|
118 |
+
$requests[] = $this->process_item( [ $item_id, $method ], $job );
|
119 |
+
|
120 |
+
} catch ( Framework\SV_WC_Plugin_Exception $e ) {
|
121 |
+
|
122 |
+
facebook_for_woocommerce()->log( "Background sync error: {$e->getMessage()}" );
|
123 |
+
}
|
124 |
+
|
125 |
+
$processed++;
|
126 |
+
$job->progress++;
|
127 |
+
|
128 |
+
// update job progress
|
129 |
+
$job = $this->update_job( $job );
|
130 |
+
|
131 |
+
// job limits reached
|
132 |
+
if ( ( $items_per_batch && $processed >= $items_per_batch ) || $this->time_exceeded() || $this->memory_exceeded() ) {
|
133 |
+
break;
|
134 |
+
}
|
135 |
+
}
|
136 |
+
|
137 |
+
// send item updates to Facebook and update the job with the returned array of batch handles
|
138 |
+
if ( ! empty( $requests ) ) {
|
139 |
+
|
140 |
+
try {
|
141 |
+
|
142 |
+
$handles = $this->send_item_updates( $requests );
|
143 |
+
|
144 |
+
$job->handles = ! isset( $job->handles ) || ! is_array( $job->handles ) ? $handles : array_merge( $job->handles, $handles );
|
145 |
+
|
146 |
+
$job = $this->update_job( $job );
|
147 |
+
|
148 |
+
} catch ( Framework\SV_WC_API_Exception $e ) {
|
149 |
+
|
150 |
+
$message = sprintf( __( 'There was an error trying sync products using the Catalog Batch API for job %s: %s' ), $job->id, $e->getMessage() );
|
151 |
+
|
152 |
+
facebook_for_woocommerce()->log( $message );
|
153 |
+
}
|
154 |
+
}
|
155 |
+
}
|
156 |
+
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Processes a single item.
|
160 |
+
*
|
161 |
+
* @since 2.0.0
|
162 |
+
*
|
163 |
+
* @param mixed $item
|
164 |
+
* @param object|\stdClass $job
|
165 |
+
* @return array
|
166 |
+
* @throws Framework\SV_WC_Plugin_Exception
|
167 |
+
*/
|
168 |
+
public function process_item( $item, $job ) {
|
169 |
+
|
170 |
+
list( $item_id, $method ) = $item;
|
171 |
+
|
172 |
+
if ( ! in_array( $method, [ Sync::ACTION_UPDATE, Sync::ACTION_DELETE ], true ) ) {
|
173 |
+
throw new Framework\SV_WC_Plugin_Exception( "Invalid sync request method: {$method}." );
|
174 |
+
}
|
175 |
+
|
176 |
+
if ( Sync::ACTION_UPDATE === $method ) {
|
177 |
+
$request = $this->process_item_update( $item_id );
|
178 |
+
} else {
|
179 |
+
$request = $this->process_item_delete( $item_id );
|
180 |
+
}
|
181 |
+
|
182 |
+
return $request;
|
183 |
+
}
|
184 |
+
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Processes an UPDATE sync request for the given product.
|
188 |
+
*
|
189 |
+
* @since 2.0.0
|
190 |
+
*
|
191 |
+
* @param string $prefixed_product_id prefixed product ID
|
192 |
+
* @return array
|
193 |
+
* @throws Framework\SV_WC_Plugin_Exception
|
194 |
+
*/
|
195 |
+
private function process_item_update( $prefixed_product_id ) {
|
196 |
+
|
197 |
+
$product_id = (int) str_replace( Sync::PRODUCT_INDEX_PREFIX, '', $prefixed_product_id );
|
198 |
+
$product = wc_get_product( $product_id );
|
199 |
+
|
200 |
+
if ( ! $product instanceof \WC_Product ) {
|
201 |
+
throw new Framework\SV_WC_Plugin_Exception( "No product found with ID equal to {$product_id}." );
|
202 |
+
}
|
203 |
+
|
204 |
+
if ( $product->is_type( 'variation' ) ) {
|
205 |
+
$product_data = $this->prepare_product_variation_data( $product );
|
206 |
+
} else {
|
207 |
+
$product_data = $this->prepare_product_data( $product );
|
208 |
+
}
|
209 |
+
|
210 |
+
// extract the retailer_id
|
211 |
+
$retailer_id = $product_data['retailer_id'];
|
212 |
+
|
213 |
+
// retailer_id cannot be included in the data object
|
214 |
+
unset( $product_data['retailer_id'] );
|
215 |
+
|
216 |
+
$request = [
|
217 |
+
'retailer_id' => $retailer_id,
|
218 |
+
'method' => Sync::ACTION_UPDATE,
|
219 |
+
'data' => $product_data,
|
220 |
+
];
|
221 |
+
|
222 |
+
/**
|
223 |
+
* Filters the data that will be included in a UPDATE sync request.
|
224 |
+
*
|
225 |
+
* @since 2.0.0
|
226 |
+
*
|
227 |
+
* @param array $request request data
|
228 |
+
* @param \WC_Product $product product object
|
229 |
+
*/
|
230 |
+
return apply_filters( 'wc_facebook_sync_background_item_update_request', $request, $product );
|
231 |
+
}
|
232 |
+
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Prepares the data for a product variation to be included in a sync request.
|
236 |
+
*
|
237 |
+
* @since 2.0.0
|
238 |
+
*
|
239 |
+
* @param \WC_Product $product product object
|
240 |
+
* @return array
|
241 |
+
* @throws Framework\SV_WC_Plugin_Exception
|
242 |
+
*/
|
243 |
+
private function prepare_product_variation_data( $product ) {
|
244 |
+
|
245 |
+
$parent_product = wc_get_product( $product->get_parent_id() );
|
246 |
+
|
247 |
+
if ( ! $parent_product instanceof \WC_Product ) {
|
248 |
+
throw new Framework\SV_WC_Plugin_Exception( "No parent product found with ID equal to {$product->get_parent_id()}." );
|
249 |
+
}
|
250 |
+
|
251 |
+
$fb_parent_product = new \WC_Facebook_Product( $parent_product->get_id() );
|
252 |
+
$fb_product = new \WC_Facebook_Product( $product->get_id(), $fb_parent_product );
|
253 |
+
|
254 |
+
$data = $fb_product->prepare_product();
|
255 |
+
|
256 |
+
// product variations use the parent product's retailer ID as the retailer product group ID
|
257 |
+
$data['retailer_product_group_id'] = \WC_Facebookcommerce_Utils::get_fb_retailer_id( $parent_product );
|
258 |
+
|
259 |
+
return $this->normalize_product_data( $data );
|
260 |
+
}
|
261 |
+
|
262 |
+
|
263 |
+
/**
|
264 |
+
* Normalizes product data to be included in a sync request.
|
265 |
+
*
|
266 |
+
* @since 2.0.0
|
267 |
+
*
|
268 |
+
* @param \WC_Product $product product object
|
269 |
+
* @return array
|
270 |
+
*/
|
271 |
+
private function normalize_product_data( $data ) {
|
272 |
+
|
273 |
+
// allowed values are 'refurbished', 'used', and 'new', but the plugin has always used the latter
|
274 |
+
$data['condition'] = 'new';
|
275 |
+
|
276 |
+
$data['product_type'] = $data['category'];
|
277 |
+
|
278 |
+
// attributes other than size, color, pattern, or gender need to be included in the additional_variant_attributes field
|
279 |
+
if ( isset( $data['custom_data'] ) && is_array( $data['custom_data'] ) ) {
|
280 |
+
|
281 |
+
$data['additional_variant_attributes'] = $data['custom_data'];
|
282 |
+
unset( $data['custom_data'] );
|
283 |
+
}
|
284 |
+
|
285 |
+
return $data;
|
286 |
+
}
|
287 |
+
|
288 |
+
|
289 |
+
/**
|
290 |
+
* Prepares the product data to be included in a sync request.
|
291 |
+
*
|
292 |
+
* @since 2.0.0
|
293 |
+
*
|
294 |
+
* @param \WC_Product $product product object
|
295 |
+
* @return array
|
296 |
+
*/
|
297 |
+
private function prepare_product_data( $product ) {
|
298 |
+
|
299 |
+
$fb_product = new \WC_Facebook_Product( $product->get_id() );
|
300 |
+
|
301 |
+
$data = $fb_product->prepare_product();
|
302 |
+
|
303 |
+
// products that are not variations use their retailer retailer ID as the retailer product group ID
|
304 |
+
$data['retailer_product_group_id'] = $data['retailer_id'];
|
305 |
+
|
306 |
+
return $this->normalize_product_data( $data );
|
307 |
+
}
|
308 |
+
|
309 |
+
|
310 |
+
/**
|
311 |
+
* Processes a DELETE sync request for the given product.
|
312 |
+
*
|
313 |
+
* @since 2.0.0
|
314 |
+
*
|
315 |
+
* @param string $retailer product retailer ID
|
316 |
+
*/
|
317 |
+
private function process_item_delete( $retailer_id ) {
|
318 |
+
|
319 |
+
$request = [
|
320 |
+
'retailer_id' => $retailer_id,
|
321 |
+
'method' => Sync::ACTION_DELETE,
|
322 |
+
];
|
323 |
+
|
324 |
+
/**
|
325 |
+
* Filters the data that will be included in a DELETE sync request.
|
326 |
+
*
|
327 |
+
* @since 2.0.0
|
328 |
+
*
|
329 |
+
* @param array $request request data
|
330 |
+
* @param string $retailer product retailer ID
|
331 |
+
*/
|
332 |
+
return apply_filters( 'wc_facebook_sync_background_item_delete_request', $request, $retailer_id );
|
333 |
+
}
|
334 |
+
|
335 |
+
|
336 |
+
/**
|
337 |
+
* Sends item updates to Facebook.
|
338 |
+
*
|
339 |
+
* @since 2.0.0
|
340 |
+
*
|
341 |
+
* @param array $requests sync requests
|
342 |
+
* @return array
|
343 |
+
* @throws Framework\SV_WC_API_Exception
|
344 |
+
*/
|
345 |
+
private function send_item_updates( array $requests ) {
|
346 |
+
|
347 |
+
$catalog_id = facebook_for_woocommerce()->get_integration()->get_product_catalog_id();
|
348 |
+
$response = facebook_for_woocommerce()->get_api()->send_item_updates( $catalog_id, $requests, true );
|
349 |
+
|
350 |
+
return $response->get_handles();
|
351 |
+
}
|
352 |
+
|
353 |
+
|
354 |
+
}
|
includes/Utilities/{Background_Disable_Virtual_Products_Sync.php → Background_Handle_Virtual_Products_Variations.php}
RENAMED
@@ -16,22 +16,22 @@ use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
|
16 |
|
17 |
|
18 |
/**
|
19 |
-
* Background job handler to
|
20 |
*
|
21 |
-
* @since
|
22 |
*/
|
23 |
-
class
|
24 |
|
25 |
|
26 |
/**
|
27 |
* Background job constructor.
|
28 |
*
|
29 |
-
* @since
|
30 |
*/
|
31 |
public function __construct() {
|
32 |
|
33 |
$this->prefix = 'wc_facebook';
|
34 |
-
$this->action = '
|
35 |
|
36 |
parent::__construct();
|
37 |
}
|
@@ -43,7 +43,7 @@ class Background_Disable_Virtual_Products_Sync extends Framework\SV_WP_Backgroun
|
|
43 |
* This job continues to update products and product variations meta data until we run out of memory
|
44 |
* or exceed the time limit. There is no list of items to loop over.
|
45 |
*
|
46 |
-
* @since
|
47 |
*
|
48 |
* @param object $job
|
49 |
* @param int $items_per_batch number of items to process in a single request. Defaults to unlimited.
|
@@ -56,8 +56,8 @@ class Background_Disable_Virtual_Products_Sync extends Framework\SV_WP_Backgroun
|
|
56 |
|
57 |
if ( empty( $job->total ) ) {
|
58 |
|
59 |
-
// no products or variations need to be
|
60 |
-
update_option( '
|
61 |
}
|
62 |
}
|
63 |
|
@@ -68,10 +68,10 @@ class Background_Disable_Virtual_Products_Sync extends Framework\SV_WP_Backgroun
|
|
68 |
$remaining_products = $job->total;
|
69 |
$processed_products = 0;
|
70 |
|
71 |
-
//
|
72 |
while ( $processed_products < $remaining_products ) {
|
73 |
|
74 |
-
$rows_updated = $this->
|
75 |
|
76 |
$processed_products += $rows_updated;
|
77 |
$job->progress += $rows_updated;
|
@@ -88,7 +88,7 @@ class Background_Disable_Virtual_Products_Sync extends Framework\SV_WP_Backgroun
|
|
88 |
// job complete! :)
|
89 |
if ( $this->count_remaining_products() === 0 ) {
|
90 |
|
91 |
-
update_option( '
|
92 |
|
93 |
$this->complete_job( $job );
|
94 |
}
|
@@ -98,9 +98,9 @@ class Background_Disable_Virtual_Products_Sync extends Framework\SV_WP_Backgroun
|
|
98 |
|
99 |
|
100 |
/**
|
101 |
-
* Counts the number of virtual products or product variations with sync enabled.
|
102 |
*
|
103 |
-
* @since
|
104 |
*
|
105 |
* @return bool
|
106 |
*/
|
@@ -112,8 +112,10 @@ class Background_Disable_Virtual_Products_Sync extends Framework\SV_WP_Backgroun
|
|
112 |
FROM {$wpdb->posts} AS posts
|
113 |
INNER JOIN {$wpdb->postmeta} AS virtual_meta ON ( posts.ID = virtual_meta.post_id AND virtual_meta.meta_key = '_virtual' AND virtual_meta.meta_value = 'yes' )
|
114 |
LEFT JOIN {$wpdb->postmeta} AS sync_meta ON ( posts.ID = sync_meta.post_id AND sync_meta.meta_key = '_wc_facebook_sync_enabled' )
|
|
|
115 |
WHERE posts.post_type IN ( 'product', 'product_variation' )
|
116 |
AND ( sync_meta.meta_value IS NULL OR sync_meta.meta_value = 'yes' )
|
|
|
117 |
";
|
118 |
|
119 |
return (int) $wpdb->get_var( $sql );
|
@@ -121,13 +123,13 @@ class Background_Disable_Virtual_Products_Sync extends Framework\SV_WP_Backgroun
|
|
121 |
|
122 |
|
123 |
/**
|
124 |
-
* Update rows
|
125 |
*
|
126 |
-
* @since
|
127 |
*
|
128 |
* @return int
|
129 |
*/
|
130 |
-
private function
|
131 |
global $wpdb;
|
132 |
|
133 |
$rows_inserted = 0;
|
@@ -138,8 +140,10 @@ class Background_Disable_Virtual_Products_Sync extends Framework\SV_WP_Backgroun
|
|
138 |
FROM {$wpdb->posts} AS posts
|
139 |
INNER JOIN {$wpdb->postmeta} AS virtual_meta ON ( posts.ID = virtual_meta.post_id AND virtual_meta.meta_key = '_virtual' AND virtual_meta.meta_value = 'yes' )
|
140 |
LEFT JOIN {$wpdb->postmeta} AS sync_meta ON ( posts.ID = sync_meta.post_id AND sync_meta.meta_key = '_wc_facebook_sync_enabled' )
|
|
|
141 |
WHERE posts.post_type IN ( 'product', 'product_variation' )
|
142 |
AND ( sync_meta.meta_value IS NULL OR sync_meta.meta_value = 'yes' )
|
|
|
143 |
LIMIT 1000
|
144 |
";
|
145 |
|
@@ -151,27 +155,16 @@ class Background_Disable_Virtual_Products_Sync extends Framework\SV_WP_Backgroun
|
|
151 |
|
152 |
} else {
|
153 |
|
154 |
-
$post_ids_str = implode( "','", $post_ids );
|
155 |
-
|
156 |
-
// delete the metadata so we can insert it without creating duplicates
|
157 |
-
$sql = "
|
158 |
-
DELETE FROM {$wpdb->postmeta}
|
159 |
-
WHERE meta_key = '_wc_facebook_sync_enabled'
|
160 |
-
AND post_id IN ( '{$post_ids_str}' )
|
161 |
-
";
|
162 |
-
|
163 |
-
$wpdb->query( $sql );
|
164 |
-
|
165 |
$values = [];
|
166 |
|
167 |
foreach ( $post_ids as $post_id ) {
|
168 |
|
169 |
-
$values[] = "('$post_id', '
|
170 |
}
|
171 |
|
172 |
$values_str = implode( ',', $values );
|
173 |
|
174 |
-
// we need to explicitly insert the metadata and set it to no, because not having it means
|
175 |
$sql = "
|
176 |
INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value )
|
177 |
VALUES {$values_str}
|
@@ -194,7 +187,7 @@ class Background_Disable_Virtual_Products_Sync extends Framework\SV_WP_Backgroun
|
|
194 |
/**
|
195 |
* No-op
|
196 |
*
|
197 |
-
* @since
|
198 |
*/
|
199 |
protected function process_item( $item, $job ) {
|
200 |
// void
|
16 |
|
17 |
|
18 |
/**
|
19 |
+
* Background job handler to change all sync enabled and visible virtual products and virtual product variations to Sync and hide.
|
20 |
*
|
21 |
+
* @since 2.0.0
|
22 |
*/
|
23 |
+
class Background_Handle_Virtual_Products_Variations extends Framework\SV_WP_Background_Job_Handler {
|
24 |
|
25 |
|
26 |
/**
|
27 |
* Background job constructor.
|
28 |
*
|
29 |
+
* @since 2.0.0
|
30 |
*/
|
31 |
public function __construct() {
|
32 |
|
33 |
$this->prefix = 'wc_facebook';
|
34 |
+
$this->action = 'background_handle_virtual_products_variations';
|
35 |
|
36 |
parent::__construct();
|
37 |
}
|
43 |
* This job continues to update products and product variations meta data until we run out of memory
|
44 |
* or exceed the time limit. There is no list of items to loop over.
|
45 |
*
|
46 |
+
* @since 2.0.0
|
47 |
*
|
48 |
* @param object $job
|
49 |
* @param int $items_per_batch number of items to process in a single request. Defaults to unlimited.
|
56 |
|
57 |
if ( empty( $job->total ) ) {
|
58 |
|
59 |
+
// no products or variations need to be set to Sync and hide, do not display admin notice
|
60 |
+
update_option( 'wc_facebook_background_handle_virtual_products_variations_skipped', 'yes' );
|
61 |
}
|
62 |
}
|
63 |
|
68 |
$remaining_products = $job->total;
|
69 |
$processed_products = 0;
|
70 |
|
71 |
+
// set to Sync and hide until memory or time limit is exceeded
|
72 |
while ( $processed_products < $remaining_products ) {
|
73 |
|
74 |
+
$rows_updated = $this->sync_and_hide();
|
75 |
|
76 |
$processed_products += $rows_updated;
|
77 |
$job->progress += $rows_updated;
|
88 |
// job complete! :)
|
89 |
if ( $this->count_remaining_products() === 0 ) {
|
90 |
|
91 |
+
update_option( 'wc_facebook_background_handle_virtual_products_variations_complete', 'yes' );
|
92 |
|
93 |
$this->complete_job( $job );
|
94 |
}
|
98 |
|
99 |
|
100 |
/**
|
101 |
+
* Counts the number of virtual products or product variations with sync enabled and visible.
|
102 |
*
|
103 |
+
* @since 2.0.0
|
104 |
*
|
105 |
* @return bool
|
106 |
*/
|
112 |
FROM {$wpdb->posts} AS posts
|
113 |
INNER JOIN {$wpdb->postmeta} AS virtual_meta ON ( posts.ID = virtual_meta.post_id AND virtual_meta.meta_key = '_virtual' AND virtual_meta.meta_value = 'yes' )
|
114 |
LEFT JOIN {$wpdb->postmeta} AS sync_meta ON ( posts.ID = sync_meta.post_id AND sync_meta.meta_key = '_wc_facebook_sync_enabled' )
|
115 |
+
LEFT JOIN {$wpdb->postmeta} AS visibility_meta ON ( posts.ID = visibility_meta.post_id AND visibility_meta.meta_key = 'fb_visibility' )
|
116 |
WHERE posts.post_type IN ( 'product', 'product_variation' )
|
117 |
AND ( sync_meta.meta_value IS NULL OR sync_meta.meta_value = 'yes' )
|
118 |
+
AND ( visibility_meta.meta_value IS NULL OR visibility_meta.meta_value = 'yes' )
|
119 |
";
|
120 |
|
121 |
return (int) $wpdb->get_var( $sql );
|
123 |
|
124 |
|
125 |
/**
|
126 |
+
* Update rows in the postmeta table to hide in Catalog.
|
127 |
*
|
128 |
+
* @since 2.0.0
|
129 |
*
|
130 |
* @return int
|
131 |
*/
|
132 |
+
private function sync_and_hide() {
|
133 |
global $wpdb;
|
134 |
|
135 |
$rows_inserted = 0;
|
140 |
FROM {$wpdb->posts} AS posts
|
141 |
INNER JOIN {$wpdb->postmeta} AS virtual_meta ON ( posts.ID = virtual_meta.post_id AND virtual_meta.meta_key = '_virtual' AND virtual_meta.meta_value = 'yes' )
|
142 |
LEFT JOIN {$wpdb->postmeta} AS sync_meta ON ( posts.ID = sync_meta.post_id AND sync_meta.meta_key = '_wc_facebook_sync_enabled' )
|
143 |
+
LEFT JOIN {$wpdb->postmeta} AS visibility_meta ON ( posts.ID = visibility_meta.post_id AND visibility_meta.meta_key = 'fb_visibility' )
|
144 |
WHERE posts.post_type IN ( 'product', 'product_variation' )
|
145 |
AND ( sync_meta.meta_value IS NULL OR sync_meta.meta_value = 'yes' )
|
146 |
+
AND ( visibility_meta.meta_value IS NULL OR visibility_meta.meta_value = 'yes' )
|
147 |
LIMIT 1000
|
148 |
";
|
149 |
|
155 |
|
156 |
} else {
|
157 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
$values = [];
|
159 |
|
160 |
foreach ( $post_ids as $post_id ) {
|
161 |
|
162 |
+
$values[] = "('$post_id', 'fb_visibility', 'no')";
|
163 |
}
|
164 |
|
165 |
$values_str = implode( ',', $values );
|
166 |
|
167 |
+
// we need to explicitly insert the metadata and set it to no, because not having it means it is visible
|
168 |
$sql = "
|
169 |
INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value )
|
170 |
VALUES {$values_str}
|
187 |
/**
|
188 |
* No-op
|
189 |
*
|
190 |
+
* @since 2.0.0
|
191 |
*/
|
192 |
protected function process_item( $item, $job ) {
|
193 |
// void
|
includes/fbgraph.php
CHANGED
@@ -527,6 +527,42 @@ if ( ! class_exists( 'WC_Facebookcommerce_Graph_API' ) ) :
|
|
527 |
return self::_get( $url );
|
528 |
}
|
529 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
530 |
public function set_default_variant( $product_group_id, $data ) {
|
531 |
$url = $this->build_url( $product_group_id );
|
532 |
return self::_post( $url, $data );
|
527 |
return self::_get( $url );
|
528 |
}
|
529 |
|
530 |
+
|
531 |
+
/**
|
532 |
+
* Gets the connected asset IDs.
|
533 |
+
*
|
534 |
+
* These will be things like pixel & page ID.
|
535 |
+
*
|
536 |
+
* @since 2.0.0
|
537 |
+
*
|
538 |
+
* @param string $external_business_id the connected external business ID
|
539 |
+
* @return array
|
540 |
+
* @throws Framework\SV_WC_API_Exception
|
541 |
+
*/
|
542 |
+
public function get_asset_ids( $external_business_id ) {
|
543 |
+
|
544 |
+
$url = $this->build_url( 'fbe_business/fbe_installs?fbe_external_business_id=', $external_business_id );
|
545 |
+
|
546 |
+
$response = $this->perform_request( $url );
|
547 |
+
|
548 |
+
$data = wp_remote_retrieve_body( $response );
|
549 |
+
$data = json_decode( $data, true );
|
550 |
+
|
551 |
+
if ( ! is_array( $data ) || empty( $data['data'][0] ) ) {
|
552 |
+
throw new Framework\SV_WC_API_Exception( 'Data is missing' );
|
553 |
+
}
|
554 |
+
|
555 |
+
$ids = $data['data'][0];
|
556 |
+
|
557 |
+
// normalize the page ID to match the others
|
558 |
+
if ( ! empty( $ids['profiles'] ) && is_array( $ids['profiles'] ) ) {
|
559 |
+
$ids['page_id'] = current( $ids['profiles'] );
|
560 |
+
}
|
561 |
+
|
562 |
+
return $ids;
|
563 |
+
}
|
564 |
+
|
565 |
+
|
566 |
public function set_default_variant( $product_group_id, $data ) {
|
567 |
$url = $this->build_url( $product_group_id );
|
568 |
return self::_post( $url, $data );
|
includes/fbproduct.php
CHANGED
@@ -9,6 +9,7 @@
|
|
9 |
*/
|
10 |
|
11 |
use SkyVerge\WooCommerce\Facebook\Products;
|
|
|
12 |
|
13 |
if ( ! defined( 'ABSPATH' ) ) {
|
14 |
exit;
|
@@ -152,11 +153,10 @@ if ( ! class_exists( 'WC_Facebook_Product' ) ) :
|
|
152 |
$regular_price = floatval( $this->get_regular_price() );
|
153 |
|
154 |
// If it's a bookable product, the normal price is null/0.
|
155 |
-
if ( ! $regular_price &&
|
156 |
-
|
157 |
-
is_wc_booking_product( $this ) ) {
|
158 |
$product = new WC_Product_Booking( $this->woo_product );
|
159 |
-
$regular_price = $product->get_display_cost();
|
160 |
}
|
161 |
|
162 |
// Get regular price plus tax, if it's set to display and taxable
|
@@ -167,6 +167,21 @@ if ( ! class_exists( 'WC_Facebook_Product' ) ) :
|
|
167 |
}
|
168 |
|
169 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
/**
|
171 |
* Gets a list of image URLs to use for this product in Facebook sync.
|
172 |
*
|
@@ -366,6 +381,16 @@ if ( ! class_exists( 'WC_Facebook_Product' ) ) :
|
|
366 |
return $product_data;
|
367 |
}
|
368 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
369 |
public function is_hidden() {
|
370 |
$wpid = $this->id;
|
371 |
if ( WC_Facebookcommerce_Utils::is_variation_type( $this->get_type() ) ) {
|
@@ -381,13 +406,11 @@ if ( ! class_exists( 'WC_Facebook_Product' ) ) :
|
|
381 |
'product_visibility',
|
382 |
$wpid
|
383 |
);
|
384 |
-
|
385 |
-
|
386 |
-
// Explicitly check whether flip 'hide' before.
|
387 |
-
return ( $hidden_from_catalog && $hidden_from_search ) ||
|
388 |
-
$this->fb_visibility === false || ! $this->get_fb_price();
|
389 |
}
|
390 |
|
|
|
391 |
public function get_price_plus_tax( $price ) {
|
392 |
$woo_product = $this->woo_product;
|
393 |
// // wc_get_price_including_tax exist for Woo > 2.7
|
@@ -541,10 +564,9 @@ if ( ! class_exists( 'WC_Facebook_Product' ) ) :
|
|
541 |
}
|
542 |
$categories =
|
543 |
WC_Facebookcommerce_Utils::get_product_categories( $id );
|
544 |
-
|
545 |
-
$brand
|
546 |
-
? WC_Facebookcommerce_Utils::get_store_name()
|
547 |
-
: WC_Facebookcommerce_Utils::clean_string( $brand );
|
548 |
|
549 |
$product_data = array(
|
550 |
'name' => WC_Facebookcommerce_Utils::clean_string(
|
@@ -555,7 +577,7 @@ if ( ! class_exists( 'WC_Facebook_Product' ) ) :
|
|
555 |
'additional_image_urls' => array_slice( $image_urls, 1 ),
|
556 |
'url' => $product_url,
|
557 |
'category' => $categories['categories'],
|
558 |
-
'brand' => $brand,
|
559 |
'retailer_id' => $retailer_id,
|
560 |
'price' => $this->get_fb_price(),
|
561 |
'currency' => get_woocommerce_currency(),
|
9 |
*/
|
10 |
|
11 |
use SkyVerge\WooCommerce\Facebook\Products;
|
12 |
+
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
13 |
|
14 |
if ( ! defined( 'ABSPATH' ) ) {
|
15 |
exit;
|
153 |
$regular_price = floatval( $this->get_regular_price() );
|
154 |
|
155 |
// If it's a bookable product, the normal price is null/0.
|
156 |
+
if ( ! $regular_price && $this->is_bookable_product() ) {
|
157 |
+
|
|
|
158 |
$product = new WC_Product_Booking( $this->woo_product );
|
159 |
+
$regular_price = is_callable( [ $product, 'get_display_cost' ] ) ? $product->get_display_cost() : 0;
|
160 |
}
|
161 |
|
162 |
// Get regular price plus tax, if it's set to display and taxable
|
167 |
}
|
168 |
|
169 |
|
170 |
+
/**
|
171 |
+
* Determines whether the current product is a WooCommerce Bookings product.
|
172 |
+
*
|
173 |
+
* TODO: add an integration that filters the Facebook price instead {WV 2020-07-22}
|
174 |
+
*
|
175 |
+
* @since 2.0.0
|
176 |
+
*
|
177 |
+
* @return bool
|
178 |
+
*/
|
179 |
+
private function is_bookable_product() {
|
180 |
+
|
181 |
+
return facebook_for_woocommerce()->is_plugin_active( 'woocommerce-bookings.php') && class_exists( 'WC_Product_Booking' ) && is_callable( 'is_wc_booking_product' ) && is_wc_booking_product( $this );
|
182 |
+
}
|
183 |
+
|
184 |
+
|
185 |
/**
|
186 |
* Gets a list of image URLs to use for this product in Facebook sync.
|
187 |
*
|
381 |
return $product_data;
|
382 |
}
|
383 |
|
384 |
+
|
385 |
+
/**
|
386 |
+
* Determines whether a product should be excluded from all-products sync or the feed file.
|
387 |
+
*
|
388 |
+
* The plugin also avoids trying to get the Facebook ID of products where is_hidden() returns true.
|
389 |
+
*
|
390 |
+
* @see SkyVerge\WooCommerce\Facebook\Products\Sync::create_or_update_all_products()
|
391 |
+
* @see WC_Facebook_Product_Feed::write_product_feed_file()
|
392 |
+
* @see WC_Facebookcommerce_Integration::get_product_fbid()
|
393 |
+
*/
|
394 |
public function is_hidden() {
|
395 |
$wpid = $this->id;
|
396 |
if ( WC_Facebookcommerce_Utils::is_variation_type( $this->get_type() ) ) {
|
406 |
'product_visibility',
|
407 |
$wpid
|
408 |
);
|
409 |
+
|
410 |
+
return ( $hidden_from_catalog && $hidden_from_search ) || ! $this->get_fb_price();
|
|
|
|
|
|
|
411 |
}
|
412 |
|
413 |
+
|
414 |
public function get_price_plus_tax( $price ) {
|
415 |
$woo_product = $this->woo_product;
|
416 |
// // wc_get_price_including_tax exist for Woo > 2.7
|
564 |
}
|
565 |
$categories =
|
566 |
WC_Facebookcommerce_Utils::get_product_categories( $id );
|
567 |
+
|
568 |
+
$brand = get_the_term_list( $id, 'product_brand', '', ', ' );
|
569 |
+
$brand = is_wp_error( $brand ) || ! $brand ? wp_strip_all_tags( WC_Facebookcommerce_Utils::get_store_name() ) : WC_Facebookcommerce_Utils::clean_string( $brand );
|
|
|
570 |
|
571 |
$product_data = array(
|
572 |
'name' => WC_Facebookcommerce_Utils::clean_string(
|
577 |
'additional_image_urls' => array_slice( $image_urls, 1 ),
|
578 |
'url' => $product_url,
|
579 |
'category' => $categories['categories'],
|
580 |
+
'brand' => Framework\SV_WC_Helper::str_truncate( $brand, 100 ),
|
581 |
'retailer_id' => $retailer_id,
|
582 |
'price' => $this->get_fb_price(),
|
583 |
'currency' => get_woocommerce_currency(),
|
includes/test/facebook-integration-test.php
CHANGED
@@ -40,6 +40,7 @@ if ( ! class_exists( 'WC_Facebook_Integration_Test' ) ) :
|
|
40 |
|
41 |
/** @var WC_Facebookcommerce_Integration full integration object */
|
42 |
public static $commerce = null;
|
|
|
43 |
public static $fbgraph = null;
|
44 |
public static $test_mode = false;
|
45 |
|
40 |
|
41 |
/** @var WC_Facebookcommerce_Integration full integration object */
|
42 |
public static $commerce = null;
|
43 |
+
/** @var WC_Facebookcommerce_Graph_API */
|
44 |
public static $fbgraph = null;
|
45 |
public static $test_mode = false;
|
46 |
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: facebook, automattic, woothemes
|
|
3 |
Tags: facebook, shop, catalog, advertise, pixel, product
|
4 |
Requires at least: 4.4
|
5 |
Tested up to: 5.3.2
|
6 |
-
Stable tag:
|
7 |
Requires PHP: 5.6 or greater
|
8 |
MySQL: 5.6 or greater
|
9 |
License: GPLv2 or later
|
@@ -39,6 +39,15 @@ When opening a bug on GitHub, please give us as many details as possible.
|
|
39 |
|
40 |
== Changelog ==
|
41 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
= 2020.06.04 - version 1.11.4 =
|
43 |
* Fix - Do not sync variations for draft variable products created by duplicating products
|
44 |
* Fix - Do not log an error when the product is null on add to cart redirect
|
3 |
Tags: facebook, shop, catalog, advertise, pixel, product
|
4 |
Requires at least: 4.4
|
5 |
Tested up to: 5.3.2
|
6 |
+
Stable tag: 2.0.0
|
7 |
Requires PHP: 5.6 or greater
|
8 |
MySQL: 5.6 or greater
|
9 |
License: GPLv2 or later
|
39 |
|
40 |
== Changelog ==
|
41 |
|
42 |
+
= 2020.07.30 - version 2.0.0 =
|
43 |
+
* Tweak - Show Facebook options for virtual products and variations
|
44 |
+
* Tweak - Hide "Sync and show" option for virtual products and variations
|
45 |
+
* Tweak - On upgrade, automatically set sync-enabled and visible virtual products and virtual variations to Sync and hide
|
46 |
+
* Tweak - Allow to bulk enable sync for virtual products, but automatically set them to Sync and hide
|
47 |
+
* Fix - Use the plugin version instead of a timestamp as the version number for enqueued scripts and stylesheets
|
48 |
+
* Fix - Use the short description of the parent product for product variations that don't have a description or Facebook description
|
49 |
+
* Fix - Prevent an error when YITH Booking and Appointment for WooCommerce plugin is active
|
50 |
+
|
51 |
= 2020.06.04 - version 1.11.4 =
|
52 |
* Fix - Do not sync variations for draft variable products created by duplicating products
|
53 |
* Fix - Do not log an error when the product is null on add to cart redirect
|