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