class-categories.php
1 year ago
class-import-image.php
11 months ago
class-import-items.php
11 months ago
class-import-price-list.php
1 year ago
class-multi-currency.php
1 year ago
class-order-sync.php
11 months ago
class-product.php
1 year ago
class-users-contact.php
1 year ago
index.php
1 year ago
class-categories.php
422 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Class to import categories from Zoho Inventory to WooCommerce and vice versa. |
| 4 | * |
| 5 | * @package zoho_inventory_api |
| 6 | */ |
| 7 | if ( ! defined( 'ABSPATH' ) ) { |
| 8 | exit; |
| 9 | } |
| 10 | class CMBIRD_Categories_ZI { |
| 11 | |
| 12 | private $config; |
| 13 | public function __construct() { |
| 14 | $this->config = array( |
| 15 | 'ConnectZI' => array( |
| 16 | 'OID' => get_option( 'cmbird_zoho_inventory_oid' ), |
| 17 | 'APIURL' => get_option( 'cmbird_zoho_inventory_url' ), |
| 18 | ), |
| 19 | ); |
| 20 | add_action( 'wp_ajax_zoho_ajax_call_category', array( $this, 'cmbird_zi_category_sync_call' ) ); |
| 21 | add_action( 'wp_ajax_zoho_ajax_call_subcategory', array( $this, 'cmbird_zi_subcategory_sync_call' ) ); |
| 22 | } |
| 23 | |
| 24 | /** |
| 25 | * Create response object based on data. |
| 26 | * |
| 27 | * @param mixed $index_col - Index value error message. |
| 28 | * @param string $message - Response message. |
| 29 | * |
| 30 | * @return object |
| 31 | */ |
| 32 | private function cmbird_zi_response_message( $index_col, $message, $woo_id = '' ) { |
| 33 | return (object) array( |
| 34 | 'resp_id' => $index_col, |
| 35 | 'message' => $message, |
| 36 | 'woo_prod_id' => $woo_id, |
| 37 | ); |
| 38 | } |
| 39 | |
| 40 | /** |
| 41 | * Get Term ID from Zoho category ID |
| 42 | * |
| 43 | * @return string - Term ID |
| 44 | */ |
| 45 | |
| 46 | public function cmbird_subcategories_term_id( $option_value ) { |
| 47 | global $wpdb; |
| 48 | $row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}options WHERE option_value = %s", $option_value ) ); |
| 49 | if ( ! empty( $row->option_name ) ) { |
| 50 | $ex = explode( 'zoho_id_for_term_id_', $row->option_name ); |
| 51 | $cat_id = $ex[1]; |
| 52 | } |
| 53 | $term = get_term_by( 'term_id', $cat_id, 'product_cat' ); |
| 54 | if ( empty( $term ) ) { |
| 55 | // remove the option from the database. |
| 56 | delete_option( $row->option_name ); |
| 57 | return ''; |
| 58 | } else { |
| 59 | return $cat_id; |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | /** |
| 64 | * Get all categories from Zoho Inventory. |
| 65 | * |
| 66 | * @return bool | string |
| 67 | */ |
| 68 | public function cmbird_zi_category_sync_call() { |
| 69 | // $fd = fopen( __DIR__ . '/cmbird_zi_category_sync_call.txt', 'a+' ); |
| 70 | |
| 71 | $response = array(); // Response array. |
| 72 | $zoho_categories = $this->cmbird_get_zoho_item_categories(); |
| 73 | // fwrite( $fd, PHP_EOL . 'categories: ' . print_r( $zoho_categories, true ) ); |
| 74 | // Import category from zoho to woocommerce. |
| 75 | $response[] = $this->cmbird_zi_response_message( '-', '-', '--- Importing Category from zoho ---' ); |
| 76 | |
| 77 | foreach ( $zoho_categories as $category ) { |
| 78 | |
| 79 | if ( '-1' === $category['category_id'] ) { |
| 80 | continue; |
| 81 | } |
| 82 | |
| 83 | if ( '-1' === $category['parent_category_id'] ) { |
| 84 | |
| 85 | if ( $category['category_id'] ) { |
| 86 | // sanitize category name. |
| 87 | $category_slug = wc_sanitize_taxonomy_name( $category['name'] ); |
| 88 | // fwrite( $fd, PHP_EOL . 'Category Name : ' . $category_name ); |
| 89 | $terms = get_terms( |
| 90 | array( |
| 91 | 'taxonomy' => 'product_cat', |
| 92 | 'hide_empty' => false, |
| 93 | 'slug' => $category_slug, |
| 94 | ) |
| 95 | ); |
| 96 | if ( ! is_wp_error( $terms ) && ! empty( $terms ) ) { |
| 97 | $term_id = $terms[0]->term_id; |
| 98 | } else { |
| 99 | $term = wp_insert_term( |
| 100 | $category['name'], |
| 101 | 'product_cat', |
| 102 | array( |
| 103 | 'parent' => 0, |
| 104 | ) |
| 105 | ); |
| 106 | if ( is_wp_error( $term ) ) { |
| 107 | $response[] = $this->cmbird_zi_response_message( $category['category_id'], $term->get_error_message(), '-' ); |
| 108 | } else { |
| 109 | $term_id = $term['term_id']; |
| 110 | } |
| 111 | } |
| 112 | if ( $term_id ) { |
| 113 | // Update zoho category id for term(category) of woocommerce. |
| 114 | // fwrite( $fd, PHP_EOL . 'Category ID : ' . $category['category_id'] . ' Term ID : ' . $term_id ); |
| 115 | update_option( 'cmbird_zoho_id_for_term_id_' . $term_id, $category['category_id'] ); |
| 116 | } |
| 117 | $response[] = $this->cmbird_zi_response_message( $category['category_id'], $category['name'], $term_id ); |
| 118 | } |
| 119 | } |
| 120 | } |
| 121 | // fclose( $fd ); |
| 122 | // Closing of import of category from woo to zoho. |
| 123 | $categories_terms = get_terms( |
| 124 | array( |
| 125 | 'taxonomy' => 'product_cat', |
| 126 | 'child_of' => false, |
| 127 | ) |
| 128 | ); |
| 129 | $log_head = '---Exporting Category to zoho---'; |
| 130 | $response[] = $this->cmbird_zi_response_message( '-', '-', $log_head ); |
| 131 | if ( $categories_terms && count( $categories_terms ) > 0 ) { |
| 132 | |
| 133 | foreach ( $categories_terms as $term ) { |
| 134 | //remove uncategorized from loop |
| 135 | if ( $term->slug == 'uncategorized' ) { |
| 136 | continue; |
| 137 | } |
| 138 | |
| 139 | $zoho_cat_id = get_option( 'cmbird_zoho_id_for_term_id_' . $term->term_id ); |
| 140 | if ( empty( $zoho_cat_id ) ) { |
| 141 | // fwrite( $fd, PHP_EOL . 'Category Name : ' . $term->name ); |
| 142 | $add_response = $this->cmbird_zi_category_export( $term->name, $term->term_id ); |
| 143 | // fwrite( $fd, PHP_EOL . 'Response : ' . print_r( $add_response, true ) ); |
| 144 | $response[] = $add_response; |
| 145 | } else { |
| 146 | $response[] = $this->cmbird_zi_response_message( $zoho_cat_id, 'Category name : "' . $term->name . '" already synced with zoho', $term->term_id ); |
| 147 | } |
| 148 | } |
| 149 | } else { |
| 150 | $response[] = $this->cmbird_zi_response_message( '-', 'Categories not available to export', '-' ); |
| 151 | } |
| 152 | $encoded_response = wp_json_encode( $response ); |
| 153 | // fwrite( $fd, PHP_EOL . 'Final Response : ' . print_r( $encoded_response, true ) ); |
| 154 | // fclose( $fd ); |
| 155 | |
| 156 | return $encoded_response; |
| 157 | } |
| 158 | |
| 159 | public function cmbird_get_zoho_item_categories() { |
| 160 | // $fd = fopen( __DIR__ . '/cmbird_get_zoho_item_categories.txt', 'a+' ); |
| 161 | |
| 162 | // first remove duplicates from woocommerce categories. |
| 163 | $this->cmbird_remove_duplicate_woocommerce_categories(); |
| 164 | |
| 165 | $zoho_inventory_oid = $this->config['ConnectZI']['OID']; |
| 166 | $zoho_inventory_url = $this->config['ConnectZI']['APIURL']; |
| 167 | |
| 168 | $url = $zoho_inventory_url . 'inventory/v1/categories/?organization_id=' . $zoho_inventory_oid; |
| 169 | |
| 170 | $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho(); |
| 171 | $json = $execute_curl_call_handle->execute_curl_call_get( $url ); |
| 172 | $code = $json->code; |
| 173 | if ( '0' == $code || 0 == $code ) { |
| 174 | $response = $json->categories; |
| 175 | // Initialize an array to store unique categories |
| 176 | $unique_categories = array(); |
| 177 | |
| 178 | // Initialize an associative array to track category occurrences |
| 179 | $category_count = array(); |
| 180 | |
| 181 | // First pass: count occurrences and track the category with active items |
| 182 | foreach ( $response as $category ) { |
| 183 | $category_name = $category->name; |
| 184 | |
| 185 | // skip -1 category_id |
| 186 | if ( '-1' === $category->category_id ) { |
| 187 | continue; |
| 188 | } |
| 189 | // Count occurrences |
| 190 | if ( isset( $category_count[ $category_name ] ) ) { |
| 191 | ++$category_count[ $category_name ]; |
| 192 | } else { |
| 193 | $category_count[ $category_name ] = 1; |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | // Second pass: add categories to unique array based on the counts and active items |
| 198 | foreach ( $response as $category ) { |
| 199 | // skip -1 category_id |
| 200 | if ( '-1' === $category->category_id ) { |
| 201 | continue; |
| 202 | } |
| 203 | |
| 204 | // remove the duplicated categories from Zoho by doing a check on the active item |
| 205 | if ( ! $category->has_active_items ) { |
| 206 | // if category is not in category_count array, then do DELETE call to Zoho API to delete the category |
| 207 | if ( 1 !== $category_count[ $category->name ] ) { |
| 208 | $delete_url = $zoho_inventory_url . 'inventory/v1/categories/' . $category->category_id . '/?organization_id=' . $zoho_inventory_oid; |
| 209 | $delete_response = $execute_curl_call_handle->execute_curl_call_delete( $delete_url ); |
| 210 | // fwrite( $fd, PHP_EOL . 'Category Deleted : ' . print_r( $delete_response, true ) ); |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | $category_name = $category->name; |
| 215 | if ( 1 === $category_count[ $category_name ] || $category->has_active_items ) { |
| 216 | // Add if mentioned only once |
| 217 | $unique_categories[] = $category; |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | // Reset keys to have a sequential array |
| 222 | $unique_categories = array_values( $unique_categories ); |
| 223 | |
| 224 | } else { |
| 225 | $response = array(); |
| 226 | return $response; |
| 227 | } |
| 228 | |
| 229 | $response = wp_json_encode( $unique_categories ); |
| 230 | // fwrite( $fd, print_r( $response, true ) ); |
| 231 | // fclose( $fd ); |
| 232 | |
| 233 | return json_decode( $response, true ); |
| 234 | } |
| 235 | |
| 236 | public function cmbird_zi_subcategory_sync_call() { |
| 237 | // $fd = fopen( __DIR__ . '/ajax_subcategory_sync_call.txt', 'a+' ); |
| 238 | $response = array(); // Response array. |
| 239 | $zoho_subcategories = $this->cmbird_get_zoho_item_categories(); |
| 240 | // Import category from zoho to woocommerce. |
| 241 | $response[] = $this->cmbird_zi_response_message( '-', '-', '--- Importing Sub Category from zoho ---' ); |
| 242 | //echo '<pre>'; print_r($zoho_categories); |
| 243 | foreach ( $zoho_subcategories as $subcategory ) { |
| 244 | if ( $subcategory['parent_category_id'] > 0 ) { |
| 245 | if ( '-1' !== $subcategory['category_id'] && $subcategory['category_id'] > 0 ) { |
| 246 | $subcategory_slug = wc_sanitize_taxonomy_name( $subcategory['name'] ); |
| 247 | $terms = get_terms( |
| 248 | array( |
| 249 | 'taxonomy' => 'product_cat', |
| 250 | 'hide_empty' => false, |
| 251 | 'slug' => $subcategory_slug, |
| 252 | ) |
| 253 | ); |
| 254 | |
| 255 | if ( $subcategory['parent_category_id'] > 0 ) { |
| 256 | $zoho_pid = intval( $this->cmbird_subcategories_term_id( $subcategory['parent_category_id'] ) ); |
| 257 | } |
| 258 | if ( ! is_wp_error( $terms ) && ! empty( $terms ) ) { |
| 259 | $term_id = $terms[0]->term_id; |
| 260 | // update the term as sub category of parent category. |
| 261 | wp_update_term( |
| 262 | $term_id, |
| 263 | 'product_cat', |
| 264 | array( |
| 265 | 'parent' => $zoho_pid, |
| 266 | ) |
| 267 | ); |
| 268 | } elseif ( empty( $terms ) && $zoho_pid ) { |
| 269 | $child_term = wp_insert_term( |
| 270 | $subcategory['name'], |
| 271 | 'product_cat', |
| 272 | array( |
| 273 | 'parent' => $zoho_pid, |
| 274 | ) |
| 275 | ); |
| 276 | // Check if there is error in creating child category add message. |
| 277 | if ( is_wp_error( $child_term ) ) { |
| 278 | $response[] = $this->cmbird_zi_response_message( $subcategory['category_id'], $child_term->get_error_message(), '-' ); |
| 279 | } else { |
| 280 | $term_id = $child_term['term_id']; |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | if ( $term_id && $zoho_pid > 0 ) { |
| 285 | // Update zoho sub category id for term(sub category) of woocommerce. |
| 286 | update_option( 'cmbird_zoho_id_for_term_id_' . $term_id, $subcategory['category_id'] ); |
| 287 | |
| 288 | } |
| 289 | $response[] = $this->cmbird_zi_response_message( $subcategory['category_id'], $subcategory['name'], $term_id ); |
| 290 | } |
| 291 | } |
| 292 | } |
| 293 | // Closing of import of category from woo to zoho . |
| 294 | |
| 295 | // Get product categories from woocommerce. |
| 296 | $categories_terms = get_terms( |
| 297 | array( |
| 298 | 'taxonomy' => 'product_cat', |
| 299 | 'child_of' => false, |
| 300 | ) |
| 301 | ); |
| 302 | $log_head = '---Exporting Sub Category to zoho---'; |
| 303 | $response[] = $this->cmbird_zi_response_message( '-', '-', $log_head ); |
| 304 | $c = 0; |
| 305 | if ( $categories_terms && count( $categories_terms ) > 0 ) { |
| 306 | |
| 307 | foreach ( $categories_terms as $parent_term ) { |
| 308 | $parent_id = $parent_term->term_id; |
| 309 | $args = array( |
| 310 | 'taxonomy' => 'product_cat', |
| 311 | 'hide_empty' => false, |
| 312 | 'parent' => $parent_id, |
| 313 | ); |
| 314 | $subcategories_terms = get_terms( $args ); |
| 315 | if ( $subcategories_terms && count( $subcategories_terms ) > 0 ) { |
| 316 | foreach ( $subcategories_terms as $term ) { |
| 317 | $zoho_cat_id = get_option( 'cmbird_zoho_id_for_term_id_' . $term->term_id ); |
| 318 | if ( empty( $zoho_cat_id ) ) { |
| 319 | $zoho_cat_id = get_option( 'cmbird_zoho_id_for_term_id_' . $parent_id ); |
| 320 | $pid = $zoho_cat_id; |
| 321 | $add_response = $this->cmbird_zi_category_export( $term->name, $term->term_id, $pid ); |
| 322 | $response[] = $add_response; |
| 323 | } else { |
| 324 | $response[] = $this->cmbird_zi_response_message( $zoho_cat_id, 'Sub Category name : "' . $term->name . '" already synced with zoho', $term->term_id ); |
| 325 | } |
| 326 | ++$c; |
| 327 | } |
| 328 | } |
| 329 | } |
| 330 | } |
| 331 | // fwrite( $fd, PHP_EOL . 'Sub Categories : ' . print_r( $response, true ) ); |
| 332 | // fclose( $fd ); |
| 333 | |
| 334 | if ( 0 === $c ) { |
| 335 | $response[] = $this->cmbird_zi_response_message( '-', 'Sub Categories not available to export', '-' ); |
| 336 | } |
| 337 | return wp_json_encode( $response ); |
| 338 | } |
| 339 | |
| 340 | /** |
| 341 | * Create woocommerce category in zoho inventory. |
| 342 | * |
| 343 | * @return boolean - true if category created successfully. |
| 344 | */ |
| 345 | public function cmbird_zi_category_export( $cat_name, $term_id = '0', $pid = '' ) { |
| 346 | |
| 347 | $zoho_inventory_oid = $this->config['ConnectZI']['OID']; |
| 348 | $zoho_inventory_url = $this->config['ConnectZI']['APIURL']; |
| 349 | |
| 350 | if ( ! empty( $pid ) || $pid > 0 ) { |
| 351 | $zidata = '"name" : "' . $cat_name . '","parent_category_id" : "' . $pid . '",'; |
| 352 | } else { |
| 353 | $zidata = '"name" : "' . $cat_name . '",'; |
| 354 | } |
| 355 | |
| 356 | $data = array( |
| 357 | 'JSONString' => '{' . $zidata . '}', |
| 358 | ); |
| 359 | |
| 360 | $url = $zoho_inventory_url . 'inventory/v1/categories/?organization_id=' . $zoho_inventory_oid; |
| 361 | |
| 362 | $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho(); |
| 363 | $json = $execute_curl_call_handle->execute_curl_call_post( $url, $data ); |
| 364 | |
| 365 | $code = $json->code; |
| 366 | |
| 367 | if ( '0' == $code || 0 == $code ) { |
| 368 | foreach ( $json->category as $key => $value ) { |
| 369 | if ( 'category_id' === $key ) { |
| 370 | update_option( 'cmbird_zoho_id_for_term_id_' . $term_id, $value ); |
| 371 | } |
| 372 | } |
| 373 | } |
| 374 | $response_msg = $json->message; |
| 375 | |
| 376 | //echo '<pre>'; print_r($json); |
| 377 | $return = $this->cmbird_zi_response_message( $code, $response_msg, $term_id ); |
| 378 | return wp_json_encode( $return ); |
| 379 | } |
| 380 | |
| 381 | /** |
| 382 | * Remove duplicate WooCommerce categories. |
| 383 | */ |
| 384 | public function cmbird_remove_duplicate_woocommerce_categories() { |
| 385 | // Get all product categories, including empty ones |
| 386 | $terms = get_terms( |
| 387 | array( |
| 388 | 'taxonomy' => 'product_cat', |
| 389 | 'hide_empty' => false, // Include categories with zero product count |
| 390 | ) |
| 391 | ); |
| 392 | |
| 393 | if ( is_wp_error( $terms ) || empty( $terms ) ) { |
| 394 | return; // No terms found or an error occurred |
| 395 | } |
| 396 | |
| 397 | // Create an array to store category names and their associated terms |
| 398 | $categories_by_name = array(); |
| 399 | |
| 400 | foreach ( $terms as $term ) { |
| 401 | $name = strtolower( $term->name ); // Normalize the name for comparison |
| 402 | |
| 403 | // Check if a category with this name is already processed |
| 404 | if ( isset( $categories_by_name[ $name ] ) ) { |
| 405 | $existing_term = $categories_by_name[ $name ]; |
| 406 | |
| 407 | if ( $term->count > 0 && $existing_term->count === 0 ) { |
| 408 | // Keep the current term, remove the existing one |
| 409 | wp_delete_term( $existing_term->term_id, 'product_cat' ); |
| 410 | $categories_by_name[ $name ] = $term; |
| 411 | } elseif ( $term->count === 0 ) { |
| 412 | // Remove the current term as it has zero product count |
| 413 | wp_delete_term( $term->term_id, 'product_cat' ); |
| 414 | } |
| 415 | } else { |
| 416 | // Add the term to the array if not already processed |
| 417 | $categories_by_name[ $name ] = $term; |
| 418 | } |
| 419 | } |
| 420 | } |
| 421 | } |
| 422 |