PluginProbe ʕ •ᴥ•ʔ
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). / 2.2.19
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). v2.2.19
3.0.3 3.0.2 3.0.1 trunk 2.2.14 2.2.15 2.2.16 2.2.17 2.2.18 2.2.19 2.3.0 2.3.1 2.3.10 2.3.11 2.3.12 2.3.13 2.3.14 2.3.2 2.3.3 2.3.4 2.3.5 2.3.6 2.3.7 2.3.8 2.3.9 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.5.0 2.5.1 2.5.2 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.6.5 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 2.7.91 2.7.92 2.7.93 2.8.0 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0
commercebird / includes / classes / zoho-inventory / class-import-items.php
commercebird / includes / classes / zoho-inventory Last commit date
class-categories.php 1 year ago class-import-image.php 1 year ago class-import-items.php 1 year ago class-import-price-list.php 1 year ago class-multi-currency.php 1 year ago class-order-sync.php 1 year ago class-product.php 1 year ago class-users-contact.php 1 year ago index.php 1 year ago
class-import-items.php
1717 lines
1 <?php
2 /**
3 * Class to import Products from Zoho to WooCommerce
4 *
5 * @package zoho_inventory_api
6 */
7 if ( ! defined( 'ABSPATH' ) ) {
8 exit;
9 }
10
11 use Automattic\WooCommerce\Internal\ProductAttributesLookup\LookupDataStore;
12
13 class CMBIRD_Products_ZI {
14
15 private $config;
16 private $is_tax_enabled;
17
18 private $wc_decimal_separator;
19 private $wc_thousand_separator;
20
21 private $wc_price_decimal_separator;
22
23 public function __construct() {
24 add_action( 'init', [ $this, 'initialize_config' ] );
25 }
26
27 public function initialize_config() {
28 if ( ! function_exists( 'wc_get_price_decimal_separator' ) ) {
29 return; // Prevents error if WooCommerce is not active
30 }
31
32 $this->config = array(
33 'ProductZI' => array(
34 'OID' => get_option( 'cmbird_zoho_inventory_oid' ),
35 'APIURL' => get_option( 'cmbird_zoho_inventory_url' ),
36 ),
37 'Settings' => array(
38 'disable_description' => get_option( 'cmbird_zoho_disable_description_sync_status' ),
39 'disable_name' => get_option( 'cmbird_zoho_disable_name_sync_status' ),
40 'disable_price' => get_option( 'cmbird_zoho_disable_price_sync_status' ),
41 'disable_stock' => get_option( 'cmbird_zoho_disable_stock_sync_status' ),
42 'enable_accounting_stock' => get_option( 'cmbird_zoho_enable_accounting_stock_status' ),
43 'enable_warehouse_stock' => get_option( 'cmbird_zoho_enable_warehousestock_status' ),
44 'zoho_warehouse_id' => get_option( 'cmbird_zoho_warehouse_id_status' ),
45 'disable_image' => get_option( 'cmbird_zoho_disable_image_sync_status' ),
46 ),
47 // Get WooCommerce settings
48 'WooCommerce' => array(
49 'decimal_separator' => wc_get_price_decimal_separator(),
50 'thousand_separator' => wc_get_price_thousand_separator(),
51 'price_decimal_separator' => wc_get_price_decimals(),
52 'tax_enabled' => 'yes' === get_option( 'woocommerce_calc_taxes' ),
53 ),
54 );
55
56 // Check if WooCommerce taxes are enabled and store the result
57 $this->is_tax_enabled = $this->config['WooCommerce']['tax_enabled'];
58
59 // Check the WooCommerce settings for decimal and thousand separators
60 $this->wc_decimal_separator = $this->config['WooCommerce']['decimal_separator'];
61 $this->wc_thousand_separator = $this->config['WooCommerce']['thousand_separator'];
62 $this->wc_price_decimal_separator = $this->config['WooCommerce']['price_decimal_separator'];
63 }
64
65 /**
66 * Function to retrieve item details and sync items.
67 *
68 * @param string $url - URL to get details.
69 * @return mixed return true if data false if error.
70 */
71 public function zi_item_bulk_sync( $url ) {
72 // $fd = fopen( __DIR__ . '/zi_item_bulk_sync.txt', 'a+' );
73
74 global $wpdb;
75 $execute_curl_call = new CMBIRD_API_Handler_Zoho();
76 $json = $execute_curl_call->execute_curl_call_get( $url );
77 $code = $json->code;
78
79 // separators
80 $wc_decimal_separator = $this->wc_decimal_separator;
81 $wc_thousand_separator = $this->wc_thousand_separator;
82 $wc_price_decimal_separator = $this->wc_price_decimal_separator;
83
84 $is_tax_enabled = $this->is_tax_enabled;
85
86 // $message = $json->message;
87 // fwrite($fd, PHP_EOL . '$json->item : ' . print_r($json, true));
88
89 if ( 0 === $code || '0' === $code ) {
90
91 foreach ( $json->items as $arr ) {
92 // fwrite( $fd, PHP_EOL . '$arr : ' . print_r( $arr, true ) );
93 if ( ( ! empty( $arr->item_id ) ) && ! ( $arr->is_combo_product ) ) {
94 // fwrite($fd, PHP_EOL . 'Item Id found : ' . $arr->item_id);
95
96 $product_res = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}postmeta WHERE meta_key='zi_item_id' AND meta_value=%s", $arr->item_id ) );
97
98 if ( $product_res && ! empty( $product_res->post_id ) ) {
99 $pdt_id = $product_res->post_id;
100 // Load the Product Object
101 $product = wc_get_product( $pdt_id );
102 if ( empty( $product ) || ! $product ) {
103 continue;
104 }
105
106 $zi_disable_itemdescription_sync = $this->config['Settings']['disable_description'];
107 if ( ! empty( $arr->description ) && ! $zi_disable_itemdescription_sync ) {
108 $product->set_short_description( $arr->description );
109 }
110
111 if ( ! empty( $arr->status ) ) {
112 $status = 'active' === $arr->status ? 'publish' : 'draft';
113 $product->set_status( $status );
114 }
115
116 $zi_disable_itemname_sync = $this->config['Settings']['disable_name'];
117 if ( ( ! $zi_disable_itemname_sync ) && ! empty( $arr->name ) ) {
118 $product->set_name( stripslashes( $arr->name ) );
119 }
120
121 if ( ! empty( $arr->sku ) ) {
122 $product->set_sku( $arr->sku );
123 }
124
125 $zi_disable_itemprice_sync = $this->config['Settings']['disable_price'];
126 if ( ! empty( $arr->rate ) && ! $zi_disable_itemprice_sync ) {
127 $product->set_regular_price( $arr->rate );
128 $sale_price = $product->get_sale_price();
129 if ( empty( $sale_price ) ) {
130 $product->set_price( $arr->rate );
131 }
132 }
133
134 if ( isset( $arr->package_details ) ) {
135 $details = $arr->package_details;
136 if ( is_object( $details ) ) {
137 $product->set_weight( floatval( $details->weight ) );
138 $product->set_length( floatval( $details->length ) );
139 $product->set_width( floatval( $details->width ) );
140 $product->set_height( floatval( $details->height ) );
141 }
142 }
143
144 // Update Purchase Rate as Cost Price
145 $product->update_meta_data( '_cost_price', $arr->purchase_rate );
146
147 // To check status of stock sync option.
148 $zi_disable_stock_sync = $this->config['Settings']['disable_stock'];
149 if ( ! $zi_disable_stock_sync && isset( $arr->available_for_sale_stock ) ) {
150 $stock = '';
151 // Update stock
152 $accounting_stock = $this->config['Settings']['enable_accounting_stock'];
153 // Sync from specific warehouse check
154 $zi_enable_warehousestock = $this->config['Settings']['enable_warehouse_stock'];
155 if ( $zi_enable_warehousestock && isset( $arr->warehouses ) ) {
156 $warehouses = $arr->warehouses;
157 $warehouse_id = $this->config['Settings']['zoho_warehouse_id'];
158 foreach ( $warehouses as $warehouse ) {
159 if ( $warehouse->warehouse_id === $warehouse_id ) {
160 if ( $accounting_stock ) {
161 $stock = $warehouse->warehouse_available_for_sale_stock;
162 } else {
163 $stock = $warehouse->warehouse_actual_available_for_sale_stock;
164 }
165 }
166 }
167 } elseif ( $accounting_stock ) {
168 $stock = $arr->available_for_sale_stock;
169 } else {
170 $stock = $arr->actual_available_for_sale_stock;
171 }
172
173 if ( is_numeric( $stock ) ) {
174 $product->set_manage_stock( true );
175 $product->set_stock_quantity( number_format( $stock, $wc_price_decimal_separator, $wc_decimal_separator, $wc_thousand_separator ) );
176 if ( $stock > 0 ) {
177 $product->set_stock_status( 'instock' );
178 } else {
179 $backorder_status = $product->backorders_allowed();
180 $status = ( $backorder_status === 'yes' ) ? 'onbackorder' : 'outofstock';
181 $product->set_stock_status( $status );
182 }
183 }
184 }
185
186 if ( ! empty( $arr->tax_id ) && ! $is_tax_enabled ) {
187 $zi_common_class = new CMBIRD_Common_Functions();
188 $woo_tax_class = $zi_common_class->get_tax_class_by_percentage( $arr->tax_percentage );
189 $product->set_tax_status( 'taxable' );
190 $product->set_tax_class( $woo_tax_class );
191 }
192 $product->save();
193 // Sync ACF Fields
194 $this->sync_item_custom_fields( $arr->custom_fields, $pdt_id );
195 // Clear/refresh cache
196 wc_delete_product_transients( $pdt_id );
197
198 }
199 }
200 }
201 } else {
202 return false;
203 }
204 // fclose( $fd );
205 // Return if synced.
206 return true;
207 }
208
209 /**
210 * Function to add items recursively by cron job.
211 *
212 * @param [number] $page - Page number for getting item with pagination.
213 * @param [number] $category - Category id to get item of specific category.
214 * @param [string] $source - Source from where function is calling : 'cron'/'sync'.
215 * @return mixed
216 */
217 public function sync_item_recursively() {
218 // $fd = fopen( __DIR__ . '/simple-items-sync.txt', 'a+' );
219
220 $args = func_get_args();
221 // fwrite( $fd, PHP_EOL . 'Args ' . print_r( $args, true ) );
222 if ( is_array( $args ) ) {
223 if ( isset( $args['page'] ) && isset( $args['category'] ) ) {
224 $page = $args['page'];
225 $category = $args['category'];
226 } elseif ( isset( $args[0] ) && isset( $args[1] ) ) {
227 $page = $args[0];
228 $category = $args[1];
229 } elseif ( isset( $args[0] ) && ! isset( $args[1] ) ) {
230 $page = $args[0]['page'];
231 $category = $args[0]['category'];
232 } else {
233 return;
234 }
235 } else {
236 return;
237 }
238
239 // Keep backup of current syncing page of particular category.
240 update_option( 'cmbird_simple_item_sync_page_cat_id_' . $category, $page );
241
242 $zoho_inventory_oid = $this->config['ProductZI']['OID'];
243 $zoho_inventory_url = $this->config['ProductZI']['APIURL'];
244 $urlitem = $zoho_inventory_url . 'inventory/v1/items?organization_id=' . $zoho_inventory_oid . '&category_id=' . $category . '&page=' . $page . '&per_page=100&sort_column=last_modified_time';
245 // fwrite( $fd, PHP_EOL . 'URL : ' . $urlitem );
246
247 $execute_curl_call = new CMBIRD_API_Handler_Zoho();
248 $json = $execute_curl_call->execute_curl_call_get( $urlitem );
249 $code = (int) property_exists( $json, 'code' ) ? $json->code : '0';
250
251 global $wpdb;
252
253 /* Response for item sync with sync button. For cron sync blank array will return. */
254 $response_msg = array();
255 if ( empty( $code ) && property_exists( $json, 'items' ) ) {
256 $item_ids = array();
257 // log items.
258 // fwrite( $fd, PHP_EOL . 'Items : ' . print_r( $json, true ) );
259
260 foreach ( $json->items as $arr ) {
261 $prod_id = wc_get_product_id_by_sku( $arr->sku );
262 $is_bundle = $arr->is_combo_product;
263 if ( isset( $arr->group_id ) ) {
264 $is_grouped = $arr->group_id;
265 }
266 // Flag to enable or disable sync.
267 $allow_to_import = false;
268 // Check if product exists with same sku.
269 if ( $prod_id ) {
270 $zi_item_id = get_post_meta( $prod_id, 'zi_item_id', true );
271 if ( empty( $zi_item_id ) ) {
272 // Map existing item with zoho id.
273 update_post_meta( $prod_id, 'zi_item_id', $arr->item_id );
274 $allow_to_import = true;
275 }
276 }
277 if ( '' == $is_bundle && empty( $is_grouped ) ) {
278 // If product not exists normal behavior of item sync.
279 $allow_to_import = true;
280 }
281 if ( ! empty( $is_grouped ) ) {
282 $this->sync_variation_of_group( $arr );
283 continue;
284 }
285
286 // Get the post id by doing a meta query on the postmeta table.
287 if ( empty( $prod_id ) ) {
288 $pdt = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}postmeta WHERE meta_key = 'zi_item_id' AND meta_value = %s LIMIT 1", $arr->item_id ) );
289 $pdt_id = $pdt ? $pdt->post_id : '';
290 } else {
291 $pdt_id = $prod_id;
292 }
293
294 if ( empty( $pdt_id ) && $allow_to_import && 'active' === $arr->status ) {
295 // Create the product if it does not exist
296 try {
297 $product = new WC_Product();
298 $product->set_name( $arr->name );
299 $product->set_status( 'publish' );
300 if ( isset( $arr->sku ) && ! empty( $arr->sku ) ) {
301 $product->set_sku( $arr->sku );
302 }
303 $product->set_regular_price( $arr->rate );
304 $pdt_id = $product->save();
305 if ( $pdt_id ) {
306 update_post_meta( $pdt_id, 'zi_item_id', $arr->item_id );
307 }
308 } catch (Exception $e) {
309 // fwrite( $fd, PHP_EOL . 'Error : ' . $e->getMessage() );
310 // throw new Exception( esc_html( $e->getMessage() ) );
311 continue;
312 }
313 }
314
315 if ( $pdt_id ) {
316 if ( ! empty( $arr->category_name ) ) {
317 $term = get_term_by( 'name', $arr->category_name, 'product_cat' );
318 $term_id = $term->term_id;
319 if ( empty( $term_id ) ) {
320 $term = wp_insert_term(
321 $arr->category_name,
322 'product_cat',
323 array(
324 'parent' => 0,
325 )
326 );
327 $term_id = $term['term_id'];
328 }
329 if ( $term_id ) {
330 $existing_terms = wp_get_object_terms( $pdt_id, 'product_cat' );
331 if ( $existing_terms && count( $existing_terms ) > 0 ) {
332 $is_terms_exist = $this->zi_check_terms_exists( $existing_terms, $term_id );
333 if ( ! $is_terms_exist ) {
334 update_post_meta( $pdt_id, 'zi_category_id', $category );
335 wp_add_object_terms( $pdt_id, $term_id, 'product_cat' );
336 }
337 } else {
338 update_post_meta( $pdt_id, 'zi_category_id', $category );
339 wp_set_object_terms( $pdt_id, $term_id, 'product_cat' );
340 }
341 }
342 // Remove "uncategorized" category if assigned
343 $uncategorized_term = get_term_by( 'slug', 'uncategorized', 'product_cat' );
344 if ( $uncategorized_term && has_term( $uncategorized_term->term_id, 'product_cat', $pdt_id ) ) {
345 wp_remove_object_terms( $pdt_id, $uncategorized_term->term_id, 'product_cat' );
346 }
347 }
348
349 if ( ! empty( $arr->brand ) ) {
350 // check if the Brand or Brands taxonomy exists and then update the term
351 if ( taxonomy_exists( 'product_brand' ) ) {
352 wp_set_object_terms( $pdt_id, $arr->brand, 'product_brand' );
353 } elseif ( taxonomy_exists( 'product_brand' ) ) {
354 wp_set_object_terms( $pdt_id, $arr->brand, 'product_brand' );
355 }
356 }
357 // Sync Featured Image if not disabled.
358 $zi_disable_image_sync = $this->config['Settings']['disable_image'];
359 if ( ! empty( $arr->image_document_id ) && ! $zi_disable_image_sync ) {
360 $image_class = new CMBIRD_Image_ZI();
361 $image_class->cmbird_zi_get_image( $arr->item_id, $arr->name, $pdt_id, $arr->image_name );
362 }
363
364 $item_ids[] = $arr->item_id;
365 } // end of wpdb post_id check
366 }
367 if ( ! empty( $item_ids ) ) {
368 $item_id_str = implode( ',', $item_ids );
369 // fwrite($fd, PHP_EOL . 'Before Bulk sync');
370 $item_details_url = "{$zoho_inventory_url}inventory/v1/itemdetails?item_ids={$item_id_str}&organization_id={$zoho_inventory_oid}";
371 $this->zi_item_bulk_sync( $item_details_url );
372
373 if ( isset( $json->page_context ) && $json->page_context->has_more_page ) {
374 $data = array(
375 'page' => $page + 1,
376 'category' => $category,
377 );
378 // fwrite( $fd, PHP_EOL . 'Data: ' . print_r( $data, true ) );
379 $existing_schedule = as_has_scheduled_action( 'import_simple_items_cron', array( $data ) );
380 if ( ! $existing_schedule ) {
381 as_schedule_single_action( time(), 'import_simple_items_cron', array( $data ) );
382 // fwrite( $fd, PHP_EOL . 'Scheduled' );
383 }
384 } else {
385 // If there is no more page to sync last backup page will be starting from 1.
386 // This we have used because in shared hosting only 1000 records are syncing.
387 update_option( 'cmbird_simple_item_sync_page_cat_id_' . $category, 1 );
388 }
389 array_push( $response_msg, $this->zi_response_message( $code, $json->message ) );
390 }
391 }
392 // fclose( $fd );
393 return $response_msg;
394 }
395
396 /**
397 * Update or Create Custom Fields of Product
398 *
399 * @param array|object $custom_fields - item object coming in from simple item recursive
400 * @param int $pdt_id - product id
401 * @return void
402 */
403 public function sync_item_custom_fields( $custom_fields, $pdt_id ) {
404 if ( empty( $custom_fields ) || empty( $pdt_id ) ) {
405 return;
406 }
407
408 foreach ( $custom_fields as $custom_field ) {
409 // Extract data from custom field
410 $api_name = isset( $custom_field->api_name ) ? $custom_field->api_name : $custom_field['api_name'];
411 $value = isset( $custom_field->value ) ? $custom_field->value : $custom_field['value'];
412
413 // Check if both API name and value are present
414 if ( ! empty( $api_name ) && ! empty( $value ) ) {
415 // Check if ACF function exists
416 if ( function_exists( 'update_field' ) ) {
417 // Update ACF field
418 update_field( $api_name, $value, $pdt_id );
419 } else {
420 // Fall back to update post meta
421 update_post_meta( $pdt_id, $api_name, $value );
422 }
423 }
424 }
425 }
426
427
428 /**
429 * Function to add group items recursively by manual sync
430 *
431 * @param [number] $page - Page number for getting group item with pagination.
432 * @param [number] $category - Category id to get group item of specific category.
433 * @param [string] $source - Source from where function is calling : 'cron'/'sync'.
434 * @return mixed
435 */
436 public function sync_groupitem_recursively() {
437 // $fd = fopen( __DIR__ . '/sync_groupitem_recursively.txt', 'a+' );
438
439 $args = func_get_args();
440 if ( ! empty( $args ) ) {
441 if ( is_array( $args ) ) {
442 if ( isset( $args['page'] ) && isset( $args['category'] ) ) {
443 $page = $args['page'];
444 $category = $args['category'];
445 } elseif ( isset( $args[0] ) && isset( $args[1] ) ) {
446 $page = $args[0];
447 $category = $args[1];
448 } elseif ( isset( $args[0] ) && ! isset( $args[1] ) ) {
449 $page = $args[0]['page'];
450 $category = $args[0]['category'];
451 } else {
452 return;
453 }
454 } else {
455 return;
456 }
457
458 // Keep backup of current syncing page of particular category.
459 update_option( 'cmbird_group_item_sync_page_cat_id_' . $category, $page );
460
461 // fwrite($fd, PHP_EOL . 'Test name Update ' . print_r($data, true));
462 global $wpdb;
463 $zoho_inventory_oid = $this->config['ProductZI']['OID'];
464 $zoho_inventory_url = $this->config['ProductZI']['APIURL'];
465
466 $url = $zoho_inventory_url . 'inventory/v1/itemgroups/?organization_id=' . $zoho_inventory_oid . '&category_id=' . $category . '&page=' . $page . '&per_page=20&filter_by=Status.Active';
467 // fwrite($fd, PHP_EOL . '$url : ' . $url);
468
469 $execute_curl_call = new CMBIRD_API_Handler_Zoho();
470 $json = $execute_curl_call->execute_curl_call_get( $url );
471
472 $code = $json->code;
473 // $message = $json->message;
474
475 $response_msg = array();
476
477 if ( $code === '0' || $code === 0 ) {
478 $zi_disable_description_sync = $this->config['Settings']['disable_description'];
479 $zi_disable_name_sync = $this->config['Settings']['disable_name'];
480 // fwrite( $fd, PHP_EOL . '$json->itemgroups : ' . print_r( $json->itemgroups, true ) );
481 foreach ( $json->itemgroups as $gp_arr ) {
482 $zi_group_id = $gp_arr->group_id;
483 $zi_group_name = $gp_arr->group_name;
484 // fwrite($fd, PHP_EOL . '$itemGroup : ' . print_r($gp_arr, true));
485 // skip if there is no first attribute
486 $zi_group_attribute1 = $gp_arr->attribute_id1;
487 if ( empty( $zi_group_attribute1 ) ) {
488 continue;
489 }
490
491 // Get Group ID
492 $group_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'zi_item_id' AND meta_value = %s LIMIT 1", $zi_group_id ) );
493 // array_push( $response_msg, $this->zi_response_message( 'SUCCESS', 'Zoho Group Item Synced: ' . $zi_group_name, $group_id ) );
494 /// end insert group product
495 // variable items
496 // fwrite($fd, PHP_EOL . '$group_id exists ' . $group_id);
497 if ( ! empty( $group_id ) ) {
498 $existing_parent_product = wc_get_product( $group_id );
499 // fwrite($fd, PHP_EOL . 'Existing group Id');
500 if ( ! empty( $gp_arr->description ) && ! $zi_disable_description_sync ) {
501 $existing_parent_product->set_short_description( $gp_arr->description );
502 }
503 if ( ! empty( $gp_arr->name ) && ! $zi_disable_name_sync ) {
504 $existing_parent_product->set_name( $gp_arr->name );
505 // santize the name for slug and save the slug
506 $slug = sanitize_title( $gp_arr->name );
507 $existing_parent_product->set_slug( $slug );
508 }
509 // add zi_category_id as meta
510 $existing_parent_product->update_meta_data( 'zi_category_id', $category );
511 // create attributes if not exists.
512 $attributes = $existing_parent_product->get_attributes();
513 if ( empty( $attributes ) ) {
514 // Create or Update the Attributes
515 $attr_created = $this->sync_attributes_of_group( $gp_arr, $group_id );
516 // fwrite($fd, PHP_EOL . '$attr_created ' . $attr_created);
517 }
518 $variations_check = $existing_parent_product->get_children();
519 if ( empty( $variations_check ) ) {
520 // fwrite( $fd, PHP_EOL . 'No Variations found' );
521 $this->import_variable_product_variations( $gp_arr, $group_id );
522 }
523 $existing_parent_product->save();
524 // ACF Fields
525 if ( ! empty( $gp_arr->custom_fields ) ) {
526 // fwrite($fd, PHP_EOL . 'Custom Fields : ' . print_r($gp_arr->custom_fields, true));
527 $this->sync_item_custom_fields( $gp_arr->custom_fields, $group_id );
528 }
529 // update Brand.
530 if ( ! empty( $gp_arr->brand ) ) {
531 // check if the Brand or Brands taxonomy exists and then update the term
532 if ( taxonomy_exists( 'product_brand' ) ) {
533 wp_set_object_terms( $group_id, $gp_arr->brand, 'product_brand' );
534 } elseif ( taxonomy_exists( 'product_brand' ) ) {
535 wp_set_object_terms( $group_id, $gp_arr->brand, 'product_brand' );
536 }
537 }
538 } else {
539 // Create the parent variable product
540 $parent_product = new WC_Product_Variable();
541 $parent_product->set_name( $zi_group_name );
542 $parent_product->set_status( 'publish' );
543 $parent_product->set_short_description( $gp_arr->description );
544 $parent_product->add_meta_data( 'zi_item_id', $zi_group_id );
545 $parent_product->add_meta_data( 'zi_category_id', $category );
546 $group_id = $parent_product->save();
547
548 // Sync category by finding it first
549 $category_handler = new CMBIRD_Categories_ZI();
550 $term_id = $category_handler->cmbird_subcategories_term_id( $category );
551 $term = get_term_by( 'id', $term_id, 'product_cat' );
552 if ( $term && ! is_wp_error( $term ) ) {
553 // Assign the category to the product
554 wp_set_object_terms( $group_id, $term->term_id, 'product_cat' );
555
556 // Remove the "uncategorized" category if it's assigned
557 $uncategorized_term = get_term_by( 'slug', 'uncategorized', 'product_cat' );
558 if ( $uncategorized_term && has_term( $uncategorized_term->term_id, 'product_cat', $group_id ) ) {
559 wp_remove_object_terms( $group_id, $uncategorized_term->term_id, 'product_cat' );
560 }
561 }
562
563 // update Brand.
564 if ( ! empty( $gp_arr->brand ) ) {
565 // check if the Brand or Brands taxonomy exists and then update the term
566 if ( taxonomy_exists( 'product_brand' ) ) {
567 wp_set_object_terms( $group_id, $gp_arr->brand, 'product_brand' );
568 } elseif ( taxonomy_exists( 'product_brand' ) ) {
569 wp_set_object_terms( $group_id, $gp_arr->brand, 'product_brand' );
570 }
571 }
572
573 // fwrite($fd, PHP_EOL . 'New $group_id ' . $group_id);
574 // ACF Fields
575 if ( ! empty( $gp_arr->custom_fields ) ) {
576 // fwrite($fd, PHP_EOL . 'Custom Fields : ' . print_r($gp_arr->custom_fields, true));
577 $this->sync_item_custom_fields( $gp_arr->custom_fields, $group_id );
578 }
579 // Create or Update the Attributes
580 $attr_created = $this->sync_attributes_of_group( $gp_arr, $group_id );
581
582 if ( ! empty( $group_id ) && $attr_created ) {
583 $this->import_variable_product_variations( $gp_arr, $group_id );
584 }
585 } // end of create variable product
586 } // end foreach group items
587
588 if ( isset( $json->page_context ) && $json->page_context->has_more_page ) {
589 $data = array(
590 'page' => $page + 1,
591 'category' => $category,
592 );
593 $existing_schedule = as_has_scheduled_action( 'import_group_items_cron', $data );
594 // Check if the scheduled action exists
595 if ( ! $existing_schedule ) {
596 as_schedule_single_action( time(), 'import_group_items_cron', $data );
597 }
598 } else {
599 // If there is no more page to sync last backup page will be starting from 1.
600 // This we have used because in shared hosting only 1000 records are syncing.
601 update_option( 'cmbird_group_item_sync_page_cat_id_' . $category, 1 );
602 }
603 array_push( $response_msg, $this->zi_response_message( $code, $json->message ) );
604 }
605 // End of logging.
606 // fclose( $fd );
607 return $response_msg;
608 } else {
609 return;
610 }
611 }
612
613 /**
614 * Callback function for importing a variable product and its variations.
615 *
616 * @param object $gp_arr - Group item object.
617 * @param int $group_id - Group item id.
618 */
619 public function import_variable_product_variations( $gp_arr, $group_id ): void {
620 // $fd = fopen( __DIR__ . '/import_variable_product_variations.txt', 'a+' );
621
622 if ( empty( $gp_arr ) || empty( $group_id ) ) {
623 return;
624 }
625
626 global $wpdb;
627 $product = wc_get_product( $group_id );
628
629 // separators
630 $wc_decimal_separator = $this->wc_decimal_separator;
631 $wc_thousand_separator = $this->wc_thousand_separator;
632 $wc_price_decimal_separator = $this->wc_price_decimal_separator;
633
634 if ( ! is_wp_error( $product ) ) {
635
636 $item_group = $gp_arr;
637 // fwrite( $fd, PHP_EOL . 'Item Group : ' . print_r( $item_group, true ) );
638 $items = $item_group->items;
639 $attribute_name1 = $item_group->attribute_name1;
640 $attribute_name2 = $item_group->attribute_name2;
641 $attribute_name3 = $item_group->attribute_name3;
642
643 // fwrite( $fd, PHP_EOL . 'Items : ' . print_r( $items, true ) );
644 // get the options for stock sync
645 $zi_enable_warehousestock = $this->config['Settings']['enable_warehouse_stock'];
646 $warehouse_id = $this->config['Settings']['zoho_warehouse_id'];
647 $accounting_stock = $this->config['Settings']['enable_accounting_stock'];
648 $zi_disable_stock_sync = $this->config['Settings']['disable_stock'];
649
650 foreach ( $items as $item ) {
651 // reset this array
652 $attribute_arr = array();
653 $variation_id = '';
654 $status = $item->status === 'active' ? 'publish' : 'draft';
655
656 $zi_item_id = $item->item_id;
657 $variation_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'zi_item_id' AND meta_value = %s LIMIT 1", $zi_item_id ) );
658
659 if ( ! empty( $variation_id ) ) {
660 $v_product = wc_get_product( $variation_id );
661 // Check if the product object is valid
662 if ( $v_product && is_a( $v_product, 'WC_Product' ) ) {
663 if ( $v_product->is_type( 'simple' ) ) {
664 wp_delete_post( $variation_id, true );
665 }
666 }
667 }
668 // SKU check of the variation, if exits then remove it
669 if ( ! empty( $item->sku ) ) {
670 $sku_prod_id = wc_get_product_id_by_sku( $item->sku );
671 $v_product = wc_get_product( $sku_prod_id );
672 // Check if the product object is valid
673 if ( $v_product && is_a( $v_product, 'WC_Product' ) ) {
674 if ( $v_product->is_type( 'simple' ) ) {
675 wp_delete_post( $variation_id, true );
676 }
677 }
678 }
679 if ( ! empty( $variation_id ) ) {
680 continue;
681 }
682 // Stock mode check
683 $warehouses = $item->warehouses;
684
685 if ( $zi_enable_warehousestock && $warehouse_id ) {
686 foreach ( $warehouses as $warehouse ) {
687 if ( $warehouse->warehouse_id === $warehouse_id ) {
688 if ( $accounting_stock ) {
689 $stock = isset( $warehouse->warehouse_available_stock );
690 } else {
691 $stock = isset( $warehouse->warehouse_actual_available_stock );
692 }
693 }
694 }
695 } elseif ( $accounting_stock ) {
696 $stock = $item->available_stock;
697 } else {
698 $stock = $item->actual_available_stock;
699 }
700 // number format the stock
701 $stock = number_format( $stock, $wc_price_decimal_separator, $wc_decimal_separator, $wc_thousand_separator );
702 // number format the rate
703 $rate = number_format( $item->rate, $wc_price_decimal_separator, $wc_decimal_separator, $wc_thousand_separator );
704
705 $attribute_name11 = $item->attribute_option_name1;
706 $attribute_name12 = $item->attribute_option_name2;
707 $attribute_name13 = $item->attribute_option_name3;
708 // Prepare the variation data
709 if ( ! empty( $attribute_name1 ) ) {
710 $sanitized_name1 = wc_sanitize_taxonomy_name( $attribute_name1 );
711 $attribute_arr[ $sanitized_name1 ] = $attribute_name11;
712 }
713 if ( ! empty( $attribute_name2 ) ) {
714 $sanitized_name2 = wc_sanitize_taxonomy_name( $attribute_name2 );
715 $attribute_arr[ $sanitized_name2 ] = $attribute_name12;
716 }
717 if ( ! empty( $attribute_name3 ) ) {
718 $sanitized_name3 = wc_sanitize_taxonomy_name( $attribute_name3 );
719 $attribute_arr[ $sanitized_name3 ] = $attribute_name13;
720 }
721 // fwrite( $fd, PHP_EOL . '$attribute_arr : ' . print_r( $attribute_arr, true ) );
722
723 // fwrite($fd, PHP_EOL . '$variation_attributes : ' . print_r($variation_attributes, true));
724 // Loop through the variations and create them
725 try {
726 $variation_post = array(
727 'post_title' => $product->get_name(),
728 'post_name' => 'product-' . $group_id . '-variation',
729 'post_status' => $status,
730 'post_parent' => $group_id,
731 'post_type' => 'product_variation',
732 'guid' => $product->get_permalink(),
733 );
734 // Creating the product variation
735 $variation_id = wp_insert_post( $variation_post );
736 if ( is_wp_error( $variation_id ) ) {
737 continue;
738 }
739 $variation = new WC_Product_Variation( $variation_id );
740 $variation->set_regular_price( $rate );
741 $variation->set_sku( $item->sku );
742 if ( ! $zi_disable_stock_sync && $stock > 0 ) {
743 $variation->set_stock_quantity( $stock );
744 $variation->set_manage_stock( true );
745 $variation->set_stock_status( '' );
746 } else {
747 $variation->set_manage_stock( false );
748 }
749 $variation->add_meta_data( 'zi_item_id', $item->item_id );
750 $variation_id = $variation->save();
751 } catch (Exception $e) {
752 // fwrite( $fd, PHP_EOL . 'Error : ' . $e->getMessage() );
753 continue;
754 }
755
756 // Get the variation attributes with correct attribute values
757 foreach ( $attribute_arr as $attribute => $term_name ) {
758 $taxonomy = 'pa_' . $attribute;
759 // If taxonomy doesn't exists we create it
760 if ( ! taxonomy_exists( $taxonomy ) ) {
761 register_taxonomy(
762 $taxonomy,
763 'product_variation',
764 array(
765 'hierarchical' => false,
766 'label' => ucfirst( $attribute ),
767 'query_var' => true,
768 'rewrite' => array( 'slug' => sanitize_title( $attribute ) ),
769 ),
770 );
771 }
772
773 // Check if the Term name exist and if not we create it.
774 if ( ! term_exists( $term_name, $taxonomy ) ) {
775 wp_insert_term( $term_name, $taxonomy );
776 }
777
778 $term_slug = get_term_by( 'name', $term_name, $taxonomy )->slug;
779 // Get the post Terms names from the parent variable product.
780 $post_term_names = wp_get_post_terms( $group_id, $taxonomy, array( 'fields' => 'names' ) );
781 // Check if the post term exist and if not we set it in the parent variable product.
782 if ( ! in_array( $term_name, $post_term_names, true ) ) {
783 wp_set_post_terms( $group_id, $term_name, $taxonomy, true );
784 }
785 // Set/save the attribute data in the product variation
786 update_post_meta( $variation_id, 'attribute_' . $taxonomy, $term_slug );
787 }
788
789 // update purchase price as meta data
790 if ( ! empty( $item->purchase_rate ) ) {
791 update_post_meta( $variation_id, '_cost_price', $item->purchase_rate );
792 }
793
794 // Featured Image of variation
795 if ( ! empty( $item->image_name ) ) {
796 $image_class = new CMBIRD_Image_ZI();
797 $variation_image_id = $image_class->cmbird_zi_get_image( $item->item_id, $item->name, $variation_id, $item->image_name );
798 if ( ! has_post_thumbnail( $group_id ) ) {
799 if ( $variation_image_id ) {
800 set_post_thumbnail( $group_id, $variation_image_id );
801 }
802 }
803 }
804 }
805 // End group item add process
806 // array_push($response_msg, $this->zi_response_message('SUCCESS', 'Zoho variable item created for zoho item id ' . $zi_item_id, $variation_id));
807
808 if ( $product && is_a( $product, 'WC_Product_Variable' ) ) {
809 // Sort the variations
810 $data_store = $product->get_data_store();
811 $data_store->sort_all_product_variations( $group_id );
812 }
813 // End of Logging
814 // fclose( $fd );
815 }
816 }
817
818 /**
819 * Update or Create the Product Attributes for the Variable Item Sync
820 *
821 * @param: $group_id - the parent product id in WooCommerce
822 * @return: bool - true if attributes were created successfully, false otherwise
823 */
824 public function sync_attributes_of_group( $gp_arr, $group_id ) {
825 // $fd = fopen(__DIR__ . '/sync_attributes_of_group.txt', 'a+');
826 // Check if the group item has attributes
827 if ( empty( $gp_arr->attribute_name1 ) ) {
828 return false;
829 }
830 // Create attributes
831 $success = true; // Track the success of attribute creation
832 $attributes_data = array();
833 $attribute_count = 0;
834 $attribute_options_map = array(); // Track unique attribute options
835
836 // Loop through the attribute names
837 for ( $i = 1; $i <= 3; $i++ ) {
838 $attribute_name_key = 'attribute_name' . $i;
839 $attribute_option_name_key = 'attribute_option_name' . $i;
840
841 // Get the attribute name
842 $attribute_name = $gp_arr->$attribute_name_key;
843
844 if ( ! empty( $attribute_name ) ) {
845 // Check if the attribute is already added to the attributes array
846 if ( ! isset( $attributes_data[ $attribute_name ] ) ) {
847 // Create the attribute and add it to the attributes array
848 $attribute = array(
849 'name' => $attribute_name,
850 'position' => $attribute_count,
851 'visible' => true,
852 'variation' => true,
853 'options' => array(),
854 );
855
856 // Loop through the items and retrieve attribute options
857 $attribute_options = array();
858 foreach ( $gp_arr->items as $item ) {
859 $attribute_option = $item->$attribute_option_name_key;
860 if ( ! empty( $attribute_option ) && ! in_array( $attribute_option, $attribute_options_map ) ) {
861 $attribute_options[] = $attribute_option;
862 $attribute_options_map[] = $attribute_option;
863 }
864 }
865
866 // Set the attribute options
867 $attribute['options'] = $attribute_options;
868
869 $attributes_data[] = $attribute;
870 ++$attribute_count;
871 }
872 }
873 }
874 // fwrite($fd, PHP_EOL . '$attributes : ' . print_r($attributes_data, true));
875
876 // Assign the attributes to the parent product
877 if ( count( $attributes_data ) > 0 ) {
878 $attributes = array(); // Initializing
879
880 // Loop through defined attribute data
881 foreach ( $attributes_data as $key => $attribute_array ) {
882 if ( isset( $attribute_array['name'] ) && isset( $attribute_array['options'] ) ) {
883 // Clean attribute name to get the taxonomy
884 $taxonomy = 'pa_' . wc_sanitize_taxonomy_name( $attribute_array['name'] );
885
886 $option_term_ids = array(); // Initializing
887
888 // Create the attribute if it doesn't exist
889 if ( ! taxonomy_exists( $taxonomy ) ) {
890 // Clean attribute label for better display
891 $attribute_label = ucfirst( $attribute_array['name'] );
892
893 // Register the new attribute taxonomy
894 $attribute_args = array(
895 'slug' => $taxonomy,
896 'name' => $attribute_label,
897 'type' => 'select',
898 'order_by' => 'menu_order',
899 'has_archives' => false,
900 );
901
902 $result = wc_create_attribute( $attribute_args );
903 register_taxonomy( $taxonomy, array( 'product' ), array() );
904
905 if ( ! is_wp_error( $result ) ) {
906 // fwrite($fd, PHP_EOL . 'result : ' . $result);
907 // Loop through defined attribute data options (terms values)
908 foreach ( $attribute_array['options'] as $option ) {
909 // Check if the term exists for the attribute taxonomy
910 $term = term_exists( $result, $taxonomy );
911 if ( empty( $term ) ) {
912 // Term doesn't exist, create a new one
913 $term_id = wp_insert_term( $option, $taxonomy );
914
915 if ( ! is_wp_error( $term_id ) ) {
916 $term_id = $term_id['term_id'];
917 } else {
918 $success = false;
919 $error_string = $term_id->get_error_message();
920 // fwrite($fd, PHP_EOL . 'error_string : ' . $error_string);
921 }
922 } else {
923 // Get the existing term ID
924 $term_id = $term['term_id'];
925 }
926 $option_term_ids[] = $term_id;
927 }
928
929 // Add the new attribute to the product attributes array
930 $attributes[ $taxonomy ] = array(
931 'name' => $taxonomy,
932 'value' => $option_term_ids, // Need to be term IDs
933 'position' => $key + 1,
934 'is_visible' => $attribute_array['visible'],
935 'is_variation' => $attribute_array['variation'],
936 'is_taxonomy' => '1',
937 );
938
939 // Get the existing terms for the taxonomy
940 $existing_terms = get_terms(
941 array(
942 'taxonomy' => $taxonomy,
943 'hide_empty' => false,
944 )
945 );
946
947 // Loop through existing terms and assign them to the product
948 foreach ( $existing_terms as $existing_term ) {
949 $existing_term_ids[] = $existing_term->term_id;
950 }
951
952 // Set the selected terms for the product
953 wp_set_object_terms( $group_id, $existing_term_ids, $taxonomy );
954 } else {
955 $success = false;
956 }
957 } else {
958 // Add existing attribute with its selected terms to the product attributes array
959 $existing_terms = get_terms(
960 array(
961 'taxonomy' => $taxonomy,
962 'hide_empty' => false,
963 )
964 );
965
966 if ( $existing_terms ) {
967 $existing_term_ids = array();
968 foreach ( $attribute_array['options'] as $option ) {
969 $match_found = false;
970 foreach ( $existing_terms as $existing_term ) {
971 if ( $existing_term->name === $option ) {
972 $existing_term_ids[] = $existing_term->term_id;
973 $match_found = true;
974 break;
975 }
976 }
977 if ( ! $match_found ) {
978 // Check if the term exists for the attribute taxonomy
979 $term = term_exists( $option, $taxonomy );
980
981 if ( empty( $term ) ) {
982 // Term doesn't exist, create a new one
983 $term = wp_insert_term( $option, $taxonomy );
984
985 if ( ! is_wp_error( $term ) ) {
986 // Get the term ID
987 $term_id = $term['term_id'];
988 $existing_term_ids[] = $term_id;
989 } else {
990 $success = false;
991 }
992 } else {
993 // Get the existing term ID
994 $term_id = $term['term_id'];
995 $existing_term_ids[] = $term_id;
996 }
997 }
998 }
999
1000 if ( ! empty( $existing_term_ids ) ) {
1001 $attributes[ $taxonomy ] = array(
1002 'name' => $taxonomy,
1003 'value' => $existing_term_ids,
1004 'position' => $key + 1,
1005 'is_visible' => $attribute_array['visible'],
1006 'is_variation' => $attribute_array['variation'],
1007 'is_taxonomy' => '1',
1008 );
1009
1010 // Set the selected terms for the product
1011 wp_set_object_terms( $group_id, $existing_term_ids, $taxonomy, false );
1012 }
1013 } else {
1014 $option_term_ids = array(); // Initializing
1015
1016 // Loop through defined attribute data options (terms values)
1017 foreach ( $attribute_array['options'] as $option ) {
1018 // Check if the term exists for the attribute taxonomy
1019 $term = term_exists( $option, $taxonomy );
1020
1021 if ( empty( $term ) ) {
1022 // Term doesn't exist, create a new one
1023 $term = wp_insert_term( $option, $taxonomy );
1024
1025 if ( ! is_wp_error( $term ) ) {
1026 // Get the term ID
1027 $term_id = $term['term_id'];
1028 $option_term_ids[] = $term_id;
1029 } else {
1030 $success = false;
1031 }
1032 } else {
1033 // Get the existing term ID
1034 $term_id = $term['term_id'];
1035 $option_term_ids[] = $term_id;
1036 }
1037 }
1038
1039 // Set the selected terms for the product
1040 wp_set_object_terms( $group_id, $option_term_ids, $taxonomy, false );
1041
1042 // Add the new attribute to the product attributes array
1043 $attributes[ $taxonomy ] = array(
1044 'name' => $taxonomy,
1045 'value' => $option_term_ids,
1046 'position' => $key + 1,
1047 'is_visible' => $attribute_array['visible'],
1048 'is_variation' => $attribute_array['variation'],
1049 'is_taxonomy' => '1',
1050 );
1051 }
1052 }
1053 }
1054 }
1055
1056 // Save the meta entry for product attributes
1057 update_post_meta( $group_id, '_product_attributes', $attributes );
1058 $lookup_data_store = new LookupDataStore();
1059 $lookup_data_store->create_data_for_product( $group_id );
1060 }
1061 // fclose($fd);
1062 return $success;
1063 }
1064
1065 /**
1066 * Update or create variation in WooCommerce if Group-ID already exists in wpdB
1067 *
1068 * @param: $arr - item object coming in from simple item recursive function
1069 * @return: void
1070 */
1071 public function sync_variation_of_group( $item ) {
1072 // $fd = fopen( __DIR__ . '/sync_variation_of_group.txt', 'a+' );
1073 global $wpdb;
1074 // Stock mode check
1075 $zi_disable_stock_sync = $this->config['Settings']['disable_stock'];
1076 $accounting_stock = $this->config['Settings']['enable_accounting_stock'];
1077 $is_tax_enabled = $this->is_tax_enabled;
1078
1079 if ( $accounting_stock ) {
1080 $stock = $item->available_stock;
1081 } else {
1082 $stock = $item->actual_available_stock;
1083 }
1084 // separators
1085 $wc_decimal_separator = $this->wc_decimal_separator;
1086 $wc_thousand_separator = $this->wc_thousand_separator;
1087 $wc_price_decimal_separator = $this->wc_price_decimal_separator;
1088
1089 $item_id = $item->item_id;
1090 // $item_category = $item->category_name;
1091 $groupid = property_exists( $item, 'group_id' ) ? $item->group_id : 0;
1092 // find parent variable product
1093 $group_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'zi_item_id' AND meta_value = %s LIMIT 1", $groupid ) );
1094 // fwrite($fd, PHP_EOL . 'Row Data : ' . print_r($row, true));
1095 // fwrite($fd, PHP_EOL . 'Row $group_id : ' . $group_id);
1096 $stock_quantity = $stock < 0 ? 0 : $stock;
1097 // number format the stock
1098 $stock_quantity = number_format( $stock_quantity, $wc_price_decimal_separator, $wc_decimal_separator, $wc_thousand_separator );
1099 // fwrite($fd, PHP_EOL . 'Before group item sync : ' . $group_id);
1100 if ( ! empty( $group_id ) ) {
1101 // fwrite($fd, PHP_EOL . 'Inside item sync : ' . $item->name);
1102 // Brand
1103 if ( isset( $item->brand ) && ! empty( $group_id ) ) {
1104 if ( taxonomy_exists( 'product_brand' ) ) {
1105 wp_set_object_terms( $group_id, $item->brand, 'product_brand' );
1106 }
1107 }
1108
1109 $variation_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'zi_item_id' AND meta_value = %s LIMIT 1", $item_id ) );
1110 if ( ! empty( $item->sku ) && empty( $variation_id ) ) {
1111 $variation_id = wc_get_product_id_by_sku( $item->sku );
1112 }
1113 if ( $variation_id ) {
1114 $variation = new WC_Product_Variation( $variation_id );
1115 // SKU - Imported
1116 if ( ! empty( $item->sku ) ) {
1117 $variation->set_sku( $item->sku );
1118 }
1119 // update purchase price as meta data
1120 if ( ! empty( $item->purchase_rate ) ) {
1121 update_post_meta( $variation_id, '_cost_price', $item->purchase_rate );
1122 }
1123 // Price - Imported
1124 $zi_disable_price_sync = $this->config['Settings']['disable_price'];
1125 $variation_sale_price = $variation->get_sale_price();
1126 if ( empty( $variation_sale_price ) && ! $zi_disable_price_sync ) {
1127 $variation->set_sale_price( $item->rate );
1128 }
1129 $variation->set_regular_price( $item->rate );
1130 // Set Tax Class
1131 if ( $item->tax_id && ! $is_tax_enabled ) {
1132 $zi_common_class = new CMBIRD_Common_Functions();
1133 $woo_tax_class = $zi_common_class->get_tax_class_by_percentage( $item->tax_percentage );
1134 $variation->set_tax_status( 'taxable' );
1135 $variation->set_tax_class( $woo_tax_class );
1136 }
1137 // Stock Imported code
1138 if ( ! $zi_disable_stock_sync && is_numeric( $stock_quantity ) ) {
1139 $variation->set_manage_stock( true );
1140 if ( $stock_quantity > 0 ) {
1141 $variation->set_manage_stock( true );
1142 $variation->set_stock_quantity( $stock_quantity );
1143 $variation->set_stock_status( 'instock' );
1144 } elseif ( $stock_quantity <= 0 ) {
1145 $variation->set_manage_stock( true );
1146 $variation->set_stock_quantity( $stock_quantity );
1147 $stock_status = $variation->backorders_allowed() ? 'onbackorder' : 'outofstock';
1148 $variation->set_stock_status( $stock_status );
1149 }
1150 }
1151 // Featured Image of variation
1152 if ( ! empty( $item->image_document_id ) ) {
1153 $image_class = new CMBIRD_Image_ZI();
1154 $variation_image_id = $image_class->cmbird_zi_get_image( $item->item_id, $item->name, $variation_id, $item->image_name );
1155 if ( ! has_post_thumbnail( $group_id ) ) {
1156 if ( $variation_image_id ) {
1157 set_post_thumbnail( $group_id, $variation_image_id );
1158 }
1159 }
1160 }
1161 // enable or disable based on status from Zoho
1162 $status = ( 'active' === $item->status ) ? 'publish' : 'draft';
1163 $variation->set_status( $status );
1164 $variation->save();
1165 // clear cache
1166 wc_delete_product_transients( $variation_id );
1167 } else {
1168 // create new variation
1169 // if status is not active then return
1170 if ( 'active' !== $item->status ) {
1171 return;
1172 }
1173
1174 $attribute_name1 = $item->attribute_option_name1;
1175 $attribute_name2 = $item->attribute_option_name2;
1176 $attribute_name3 = $item->attribute_option_name3;
1177 // Prepare the variation data
1178 $attribute_arr = array();
1179 if ( ! empty( $attribute_name1 ) ) {
1180 $sanitized_name1 = wc_sanitize_taxonomy_name( $item->attribute_name1 );
1181 $attribute_arr[ $sanitized_name1 ] = $attribute_name1;
1182 }
1183 if ( ! empty( $attribute_name2 ) ) {
1184 $sanitized_name2 = wc_sanitize_taxonomy_name( $item->attribute_name2 );
1185 $attribute_arr[ $sanitized_name2 ] = $attribute_name2;
1186 }
1187 if ( ! empty( $attribute_name3 ) ) {
1188 $sanitized_name3 = wc_sanitize_taxonomy_name( $item->attribute_name3 );
1189 $attribute_arr[ $sanitized_name3 ] = $attribute_name3;
1190 }
1191 // fwrite( $fd, PHP_EOL . 'Attributes_arr: ' . print_r( $attribute_arr, true ) );
1192
1193 // here actually create new variation because sku not found
1194 $variation = new WC_Product_Variation();
1195 $variation->set_parent_id( $group_id );
1196 $variation->set_status( 'publish' );
1197 $variation->set_regular_price( $item->rate );
1198 $variation->set_sku( $item->sku );
1199 if ( ! $zi_disable_stock_sync ) {
1200 $variation->set_stock_quantity( $stock_quantity );
1201 $variation->set_manage_stock( true );
1202 $variation->set_stock_status( '' );
1203 } else {
1204 $variation->set_manage_stock( false );
1205 }
1206 $variation->add_meta_data( 'zi_item_id', $item->item_id );
1207 $variation_id = $variation->save();
1208
1209 // Get the variation attributes with correct attribute values
1210 foreach ( $attribute_arr as $attribute => $term_name ) {
1211 $taxonomy = $attribute;
1212 // If taxonomy doesn't exists we create it
1213 if ( ! taxonomy_exists( $taxonomy ) ) {
1214 register_taxonomy(
1215 $taxonomy,
1216 'product_variation',
1217 array(
1218 'hierarchical' => false,
1219 'label' => ucfirst( $attribute ),
1220 'query_var' => true,
1221 'rewrite' => array( 'slug' => sanitize_title( $attribute ) ),
1222 ),
1223 );
1224 }
1225
1226 // Check if the Term name exist and if not we create it.
1227 if ( ! term_exists( $term_name, $taxonomy ) ) {
1228 wp_insert_term( $term_name, $taxonomy );
1229 }
1230
1231 $term_slug = get_term_by( 'name', $term_name, $taxonomy )->slug;
1232 // Get the post Terms names from the parent variable product.
1233 $post_term_names = wp_get_post_terms( $group_id, $taxonomy, array( 'fields' => 'names' ) );
1234 // Check if the post term exist and if not we set it in the parent variable product.
1235 if ( ! in_array( $term_name, $post_term_names, true ) ) {
1236 wp_set_post_terms( $group_id, $term_name, $taxonomy, true );
1237 }
1238 // Set/save the attribute data in the product variation
1239 update_post_meta( $variation_id, 'attribute_' . $taxonomy, $term_slug );
1240 }
1241
1242 // update purchase price as meta data
1243 if ( ! empty( $item->purchase_rate ) ) {
1244 update_post_meta( $variation_id, '_cost_price', $item->purchase_rate );
1245 }
1246 // Stock
1247 if ( ! empty( $stock ) && ! $zi_disable_stock_sync ) {
1248 update_post_meta( $variation_id, 'manage_stock', true );
1249 if ( $stock > 0 ) {
1250 update_post_meta( $variation_id, '_stock', $stock );
1251 update_post_meta( $variation_id, '_stock_status', 'instock' );
1252 } else {
1253 $backorder_status = get_post_meta( $group_id, '_backorders', true );
1254 update_post_meta( $variation_id, '_stock', $stock );
1255 if ( $backorder_status === 'yes' ) {
1256 update_post_meta( $variation_id, '_stock_status', 'onbackorder' );
1257 } else {
1258 update_post_meta( $variation_id, '_stock_status', 'outofstock' );
1259 }
1260 }
1261 }
1262 // Featured Image of variation
1263 if ( ! empty( $item->image_document_id ) ) {
1264 $image_class = new CMBIRD_Image_ZI();
1265 $variation_image_id = $image_class->cmbird_zi_get_image( $item->item_id, $item->name, $variation_id, $item->image_name );
1266 if ( ! has_post_thumbnail( $group_id ) ) {
1267 if ( $variation_image_id ) {
1268 set_post_thumbnail( $group_id, $variation_image_id );
1269 }
1270 }
1271 }
1272 update_post_meta( $variation_id, 'zi_item_id', $item_id );
1273 WC_Product_Variable::sync( $group_id );
1274 // Regenerate lookup table for attributes
1275 $lookup_data_store = new LookupDataStore();
1276 $lookup_data_store->create_data_for_product( $group_id );
1277 // End group item add process
1278 unset( $attribute_arr );
1279 }
1280 // end of grouped item updating
1281 } else {
1282 // fwrite($fd, PHP_EOL . 'Group item empty');
1283 return;
1284 }
1285 // fwrite($fd, PHP_EOL . 'After group item sync');
1286 // fclose( $fd );
1287 }
1288
1289 /**
1290 * Helper Function to check if child of composite items already synced or not
1291 *
1292 * @param string $composite_zoho_id - zoho composite item id to check if it's child are already synced.
1293 * @param string $zi_url - zoho api url.
1294 * @param string $zi_key - zoho access token.
1295 * @param string $zi_org_id - zoho organization id.
1296 * @return array of child id and metadata if child item already synced else will return false.
1297 */
1298 public function zi_check_if_child_synced_already( $composite_zoho_id, $zi_url, $zi_org_id, $prod_id ) {
1299 if ( $prod_id ) {
1300 $bundle_childs = WC_PB_DB::query_bundled_items(
1301 array(
1302 'return' => 'id=>product_id',
1303 'bundle_id' => array( $prod_id ),
1304 )
1305 );
1306 }
1307 global $wpdb;
1308
1309 $url = $zi_url . 'inventory/v1/compositeitems/' . $composite_zoho_id . '?organization_id=' . $zi_org_id;
1310
1311 $execute_curl_call = new CMBIRD_API_Handler_Zoho();
1312 $json = $execute_curl_call->execute_curl_call_get( $url );
1313 $code = $json->code;
1314 // Flag to allow sync of parent composite item.
1315 $allow_sync = false;
1316 // Array of child object metadata.
1317 $product_array = array(); // [{prod_id:'',metadata:{key:'',value:''}},...].
1318 if ( '0' === $code || 0 === $code ) {
1319 foreach ( $json->composite_item->mapped_items as $child_item ) {
1320 $prod_meta = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->postmeta WHERE meta_key = 'zi_item_id' AND meta_value = %s", $child_item->item_id ) );
1321 // If any child will not have zoho id in meta field then process will return false and syncing will be skipped for given item.
1322 if ( ! empty( $prod_meta->post_id ) ) {
1323
1324 $allow_sync = true;
1325 $prod_obj = (object) array(
1326 'prod_id' => $prod_meta->post_id,
1327 'metadata' => (object) array(
1328 'quantity_min' => max( 1, $child_item->quantity ),
1329 'quantity_max' => max( 1, $child_item->quantity ),
1330 'stock_status' => ( $child_item->stock_on_hand ) ? 'in_stock' : 'out_of_stock',
1331 'max_stock' => $child_item->stock_on_hand,
1332 ),
1333 );
1334 if ( is_array( $bundle_childs ) && ! empty( $bundle_childs ) ) {
1335 $index = array_search( $prod_meta->post_id, $bundle_childs );
1336 unset( $bundle_childs[ $index ] );
1337 }
1338 array_push( $product_array, $prod_obj );
1339 } else {
1340 continue;
1341 }
1342 }
1343 }
1344 if ( is_array( $bundle_childs ) && ! empty( $bundle_childs ) ) {
1345 foreach ( $bundle_childs as $item_id => $val ) {
1346 WC_PB_DB::delete_bundled_item( $item_id );
1347 }
1348 }
1349 if ( $allow_sync ) {
1350 return $product_array;
1351 }
1352 return false;
1353 }
1354 /**
1355 * Mapping of bundled product
1356 *
1357 * @param number $product_id - Product id of child item of bundle product.
1358 * @param number $bundle_id - Bundle id of product.
1359 * @param number $menu_order - Listing order of child product ($menu_order will useful at composite product details page).
1360 * @return void
1361 */
1362 public function add_bundle_product( $product_id, $bundle_id, $menu_order = 0 ) {
1363 $bundle_items = WC_PB_DB::query_bundled_items(
1364 array(
1365 'return' => 'id=>product_id',
1366 'bundle_id' => array( $bundle_id ),
1367 'product_id' => array( $product_id ),
1368 )
1369 );
1370 $data = array(
1371 'menu_order' => $menu_order,
1372 );
1373
1374 if ( count( $bundle_items ) > 0 ) {
1375 $result = WC_PB_DB::update_bundled_item( $bundle_id, $data );
1376 return $result;
1377 } else {
1378 // create data array of bundle item.
1379 $data = array(
1380 'product_id' => $product_id,
1381 'bundle_id' => $bundle_id,
1382 'menu_order' => $menu_order,
1383 );
1384 $bundle_id = WC_PB_DB::add_bundled_item( $data );
1385 return $bundle_id;
1386 }
1387 }
1388
1389 /**
1390 * Create or update bundle item metadata
1391 *
1392 * @param number $bundle_item_id bundle item id.
1393 * @param string $meta_key - metadata key.
1394 * @param string $meta_value - metadata value.
1395 * @return void
1396 */
1397
1398 public function zi_update_bundle_meta( $bundle_item_id, $meta_key, $meta_value ) {
1399 // first get metadata from db.
1400 $metadata = WC_PB_DB::get_bundled_item_meta( $bundle_item_id, $meta_key );
1401 if ( $metadata ) {
1402 $result = WC_PB_DB::update_bundled_item_meta( $bundle_item_id, $meta_key, $meta_value );
1403 } else {
1404 $result = WC_PB_DB::add_bundled_item_meta( $bundle_item_id, $meta_key, $meta_value );
1405 return $result;
1406 }
1407 }
1408
1409 /**
1410 * Function to sync composite item from zoho to woocommerce
1411 *
1412 * @param integer $page - Page number of composite item data.
1413 * @param string $category - Category id of composite data.
1414 * @param string $source - Source of calling function.
1415 * @return mixed - mostly array of response message.
1416 */
1417 public function recursively_sync_composite_item_from_zoho( $page, $category, $source ) {
1418 // Start logging
1419 // $fd = fopen( __DIR__ . '/recursively_sync_composite_item_from_zoho.txt', 'a+' );
1420
1421 global $wpdb;
1422 $zi_org_id = $this->config['ProductZI']['OID'];
1423 $zi_url = $this->config['ProductZI']['APIURL'];
1424
1425 $current_user = wp_get_current_user();
1426 $admin_author_id = $current_user->ID;
1427 if ( ! $admin_author_id ) {
1428 $admin_author_id = 1;
1429 }
1430
1431 $url = $zi_url . 'inventory/v1/compositeitems/?organization_id=' . $zi_org_id . '&filter_by=Status.Active&category_id=' . $category . '&page=' . $page;
1432
1433 $execute_curl_call = new CMBIRD_API_Handler_Zoho();
1434 $json = $execute_curl_call->execute_curl_call_get( $url );
1435 $code = $json->code;
1436 // $message = $json->message;
1437 // fwrite($fd, PHP_EOL . '$json : ' . print_r($json, true));
1438 // Response for item sync with sync button. For cron sync blank array will return.
1439 $response_msg = array();
1440 if ( $code === '0' || $code === 0 ) {
1441 if ( empty( $json->composite_items ) ) {
1442 array_push( $response_msg, $this->zi_response_message( 'ERROR', 'No composite item to sync for category : ' . $category ) );
1443 return $response_msg;
1444 }
1445 // Accounting stock mode check
1446 $accounting_stock = $this->config['Settings']['enable_accounting_stock'];
1447 foreach ( $json->composite_items as $comp_item ) {
1448 // fwrite( $fd, PHP_EOL . 'Composite Item : ' . print_r( $comp_item, true ) );
1449 // Sync stock from specific warehouse check
1450 $zi_enable_warehousestock = $this->config['Settings']['enable_warehousestock'];
1451 $warehouse_id = $this->config['Settings']['warehouse_id'];
1452 $warehouses = $comp_item->warehouses;
1453
1454 if ( $zi_enable_warehousestock === true ) {
1455 foreach ( $warehouses as $warehouse ) {
1456 if ( $warehouse->warehouse_id === $warehouse_id ) {
1457 if ( $accounting_stock ) {
1458 $stock = $warehouse->warehouse_available_stock;
1459 } else {
1460 $stock = $warehouse->warehouse_actual_available_stock;
1461 }
1462 }
1463 }
1464 } elseif ( $accounting_stock ) {
1465 $stock = $comp_item->available_stock;
1466 } else {
1467 $stock = $comp_item->actual_available_stock;
1468 }
1469
1470 // ----------------- Create composite item in woocommerce--------------.
1471 // Code to skip sync with item already exists with same sku.
1472 $prod_id = wc_get_product_id_by_sku( $comp_item->sku );
1473 // Flag to enable or disable sync.
1474 $allow_to_import = false;
1475 // Check if product exists with same sku.
1476 if ( $prod_id ) {
1477 $zi_item_id = get_post_meta( $prod_id, 'zi_item_id', true );
1478 if ( $zi_item_id === $comp_item->composite_item_id ) {
1479 // If product is with same sku and zi_item_id mapped.
1480 // Do not import ...
1481 $allow_to_import = false;
1482 } else {
1483 // Map existing item with zoho id.
1484 update_post_meta( $prod_id, 'zi_item_id', $comp_item->composite_item_id );
1485 $allow_to_import = false;
1486 }
1487 } else {
1488 // If product not exists normal bahaviour of item sync.
1489 $allow_to_import = true;
1490 }
1491 $zoho_comp_item_id = $comp_item->composite_item_id;
1492 if ( $comp_item->composite_item_id ) {
1493 $child_items = $this->zi_check_if_child_synced_already( $zoho_comp_item_id, $zi_url, $zi_org_id, $prod_id );
1494 // Check if child items already synced with zoho.
1495 if ( ! $child_items ) {
1496 array_push( $response_msg, $this->zi_response_message( 'ERROR', 'Child not synced for composite item : ' . $zoho_comp_item_id ) );
1497 continue;
1498 }
1499 $product_res = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->postmeta} WHERE meta_key = 'zi_item_id' AND meta_value = %s", $zoho_comp_item_id ) );
1500 if ( ! empty( $product_res->post_id ) ) {
1501 $com_prod_id = $product_res->post_id;
1502 }
1503 // Check if item is allowed to import or not.
1504 if ( $allow_to_import ) {
1505 $product_class = new CMBIRD_Products_ZI_Export();
1506 $item_array = json_decode( wp_json_encode( $comp_item ), true );
1507 $com_prod_id = $product_class->cmbird_zi_product_to_woocommerce( $item_array, $stock, 'composite' );
1508 update_post_meta( $com_prod_id, 'zi_item_id', $zoho_comp_item_id );
1509 }
1510 }
1511 // Map composite items to database.
1512 if ( ! empty( $com_prod_id ) ) {
1513 wp_set_object_terms( $com_prod_id, 'bundle', 'product_type' );
1514 foreach ( $child_items as $child_prod ) {
1515 // Adding product to bundle.
1516 $child_bundle_id = $this->add_bundle_product( $child_prod->prod_id, $com_prod_id );
1517 if ( $child_bundle_id ) {
1518 foreach ( $child_prod->metadata as $bundle_meta_key => $bundle_meta_val ) {
1519 $this->zi_update_bundle_meta( $child_bundle_id, $bundle_meta_key, $bundle_meta_val );
1520 }
1521 }
1522 }
1523 }
1524 // --------------------------------------------------------------------.
1525
1526 $is_synced_flag = false; // loggin purpose only .
1527
1528 $product = wc_get_product( $com_prod_id );
1529 foreach ( $comp_item as $key => $value ) {
1530 if ( $key === 'status' ) {
1531 if ( ! empty( $com_prod_id ) ) {
1532 $status = $value === 'active' ? 'publish' : 'draft';
1533 $product->set_status( $status );
1534 }
1535 }
1536 if ( $key === 'description' ) {
1537 if ( ! empty( $com_prod_id ) && ! empty( $value ) ) {
1538 $product->set_short_description( $value );
1539 }
1540 }
1541 if ( $key === 'name' ) {
1542 if ( ! empty( $com_prod_id ) ) {
1543 $product->set_name( $value );
1544 }
1545 }
1546 if ( $key === 'sku' ) {
1547 if ( ! empty( $com_prod_id ) ) {
1548 $product->set_sku( $value );
1549 }
1550 }
1551 // Check if stock sync allowed by plugin.
1552 if ( $key === 'available_stock' || $key === 'actual_available_stock' ) {
1553 $zi_disable_stock_sync = $this->config['Settings']['disable_stock'];
1554 if ( ! $zi_disable_stock_sync ) {
1555 if ( $stock ) {
1556 if ( ! empty( $com_prod_id ) ) {
1557 // If value is less than 0 default 1.
1558 $stock_quantity = $stock < 0 ? 0 : $stock;
1559 $product->set_manage_stock( true );
1560 $product->set_stock_quantity( $stock_quantity );
1561 if ( $stock_quantity > 0 ) {
1562 $status = 'instock';
1563 } else {
1564 $backorder_status = get_post_meta( $com_prod_id, '_backorders', true );
1565 $status = ( $backorder_status === 'yes' ) ? 'onbackorder' : 'outofstock';
1566 }
1567 $product->set_stock_status( $status );
1568 update_post_meta( $com_prod_id, '_wc_pb_bundled_items_stock_status', $status );
1569 }
1570 }
1571 }
1572 }
1573 if ( $key === 'rate' ) {
1574 if ( ! empty( $com_prod_id ) ) {
1575 $sale_price = $product->get_sale_price();
1576 if ( empty( $sale_price ) ) {
1577 $product->set_regular_price( $value );
1578 $product->set_price( $value );
1579 update_post_meta( $com_prod_id, '_wc_pb_base_price', $value );
1580 update_post_meta( $com_prod_id, '_wc_pb_base_regular_price', $value );
1581 update_post_meta( $com_prod_id, '_wc_sw_max_regular_price', $value );
1582 } else {
1583 $product->set_regular_price( $value );
1584 update_post_meta( $com_prod_id, '_wc_pb_base_price', $value );
1585 update_post_meta( $com_prod_id, '_wc_pb_base_regular_price', $value );
1586 update_post_meta( $com_prod_id, '_wc_sw_max_regular_price', $value );
1587 }
1588 }
1589 }
1590 $product->save();
1591
1592 if ( $key === 'image_document_id' ) {
1593 if ( ! empty( $com_prod_id ) && ! empty( $value ) ) {
1594 $image_class = new CMBIRD_Image_ZI();
1595 $image_class->cmbird_zi_get_image( $zoho_comp_item_id, $comp_item->name, $com_prod_id, $comp_item->image_name );
1596 }
1597 }
1598 if ( $key === 'category_name' ) {
1599 if ( ! empty( $com_prod_id ) && $comp_item->category_name != '' ) {
1600 $term = get_term_by( 'name', $comp_item->category_name, 'product_cat' );
1601 $term_id = $term->term_id;
1602 if ( empty( $term_id ) ) {
1603 $term = wp_insert_term(
1604 $comp_item->category_name,
1605 'product_cat',
1606 array(
1607 'parent' => 0,
1608 )
1609 );
1610 $term_id = $term['term_id'];
1611 }
1612 if ( $term_id ) {
1613 $existing_terms = wp_get_object_terms( $com_prod_id, 'product_cat' );
1614 if ( $existing_terms && count( $existing_terms ) > 0 ) {
1615 $is_terms_exist = $this->zi_check_terms_exists( $existing_terms, $term_id );
1616 if ( ! $is_terms_exist ) {
1617 update_post_meta( $com_prod_id, 'zi_category_id', $category );
1618 wp_add_object_terms( $com_prod_id, $term_id, 'product_cat' );
1619 }
1620 } else {
1621 update_post_meta( $com_prod_id, 'zi_category_id', $category );
1622 wp_set_object_terms( $com_prod_id, $term_id, 'product_cat' );
1623 }
1624 }
1625 // Remove "uncategorized" category if assigned
1626 $uncategorized_term = get_term_by( 'slug', 'uncategorized', 'product_cat' );
1627 if ( $uncategorized_term && has_term( $uncategorized_term->term_id, 'product_cat', $com_prod_id ) ) {
1628 wp_remove_object_terms( $com_prod_id, $uncategorized_term->term_id, 'product_cat' );
1629 }
1630 }
1631 }
1632 }
1633
1634 // sync dimensions and weight
1635 $item_url = "{$zi_url}inventory/v1/compositeitems/{$zoho_comp_item_id}?organization_id={$zi_org_id}";
1636 $this->zi_item_dimension_weight( $item_url, $com_prod_id, true );
1637
1638 // If item synced append to log : logging purpose only.
1639 if ( $is_synced_flag ) {
1640 array_push( $response_msg, $this->zi_response_message( 'SUCCESS', 'Composite item synced for id : ' . $comp_item->composite_item_id, $com_prod_id ) );
1641 }
1642 }
1643
1644 if ( $json->page_context->has_more_page ) {
1645 ++$page;
1646 $this->recursively_sync_composite_item_from_zoho( $page, $category, $source );
1647 }
1648 } else {
1649 array_push( $response_msg, $this->zi_response_message( $code, $json->message ) );
1650 }
1651 // fclose( $fd ); // End of logging.
1652
1653 return $response_msg;
1654 }
1655
1656 /**
1657 * Function to retrieve item details, update weight and dimensions.
1658 *
1659 * @param string $url - URL to ge details.
1660 * @return mixed return true if data false if error.
1661 */
1662 public function zi_item_dimension_weight( $url, $product_id, $is_composite = false ) {
1663 // $fd = fopen(__DIR__ . '/zi_item_dimension_weight.txt', 'a+');
1664 // Check if item is for syncing purpose.
1665 $execute_curl_call = new CMBIRD_API_Handler_Zoho();
1666 $json = $execute_curl_call->execute_curl_call_get( $url );
1667 $code = $json->code;
1668 $message = $json->message;
1669 if ( 0 === $code || '0' === $code ) {
1670 if ( $is_composite ) {
1671 // fwrite($fd, PHP_EOL . '$json : ' . print_r($json, true));
1672 $details = $json->composite_item->package_details;
1673 } else {
1674 $details = $json->item->package_details;
1675 }
1676 $product = wc_get_product( $product_id );
1677 $product->set_weight( floatval( $details->weight ) );
1678 $product->set_length( floatval( $details->length ) );
1679 $product->set_width( floatval( $details->width ) );
1680 $product->set_height( floatval( $details->height ) );
1681 $product->save();
1682 } else {
1683 false;
1684 }
1685 // fclose($fd);
1686 }
1687
1688 /**
1689 * Create response object based on data.
1690 *
1691 * @param mixed $index_col - Index value error message.
1692 * @param string $message - Response message.
1693 * @return object
1694 */
1695 public function zi_response_message( $index_col, $message, $woo_id = '' ) {
1696 return (object) array(
1697 'resp_id' => $index_col,
1698 'message' => $message,
1699 'woo_prod_id' => $woo_id,
1700 );
1701 }
1702
1703 /**
1704 * Helper Function to check if terms already exists.
1705 */
1706 public function zi_check_terms_exists( $existing_terms, $term_id ) {
1707 foreach ( $existing_terms as $woo_existing_term ) {
1708 if ( $woo_existing_term->term_id === $term_id ) {
1709 return true;
1710 } else {
1711 return false;
1712 }
1713 }
1714 }
1715 }
1716 $cmbird_products_zi = new CMBIRD_Products_ZI();
1717