PluginProbe ʕ •ᴥ•ʔ
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). / 2.3.9
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). v2.3.9
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 / admin / includes / Actions / Ajax / ZohoInventoryAjax.php
commercebird / admin / includes / Actions / Ajax Last commit date
AcfAjax.php 1 year ago ExactOnlineAjax.php 1 year ago ZohoCRMAjax.php 1 year ago ZohoInventoryAjax.php 1 year ago index.php 1 year ago
ZohoInventoryAjax.php
895 lines
1 <?php
2
3 namespace CommerceBird\Admin\Actions\Ajax;
4
5 use CMBIRD_Auth_Zoho;
6 use CMBIRD_API_Handler_Zoho;
7 use CMBIRD_Pricelist_ZI;
8 use CMBIRD_Categories_ZI;
9 use CommerceBird\Admin\Template;
10 use CommerceBird\Admin\Traits\AjaxRequest;
11 use CommerceBird\Admin\Traits\OptionStatus;
12 use CommerceBird\Admin\Traits\Singleton;
13 use CommerceBird\Admin\Traits\LogWriter;
14 use Throwable;
15 use WC_Tax;
16 use WpOrg\Requests\Exception;
17 use function gettype;
18
19 if ( ! defined( 'ABSPATH' ) ) {
20 exit;
21 }
22 final class ZohoInventoryAjax {
23
24
25 use Singleton;
26 use AjaxRequest;
27 use OptionStatus;
28 use LogWriter;
29
30 private const FORMS = array(
31 'settings' => array(
32 'id',
33 'email',
34 ),
35 'tax' => array(
36 'selectedTaxRates',
37 ),
38 'product' => array(
39 'item_from_zoho',
40 'disable_stock_sync',
41 'disable_product_sync',
42 'enable_accounting_stock',
43 ),
44 'cron' => array(
45 'form',
46 'categories',
47 ),
48 'order' => array(
49 'disable_sync',
50 'enable_auto_number',
51 'enable_order_status',
52 'order_prefix',
53 'location_id',
54 'enable_locationstock',
55 ),
56 'contact' => array(
57 'enable_cron',
58 ),
59 'price' => array(
60 'wp_user_role',
61 'zoho_inventory_pricelist',
62 'wcb2b',
63 ),
64 );
65
66 private const ACTIONS = array(
67 'get_subscription' => 'subscription_get',
68 'get_settings' => 'settings_get',
69 'save_settings' => 'settings_set',
70 'reset_settings' => 'settings_reset',
71 'get_zoho_connect' => 'connection_get',
72 'save_zoho_connect' => 'connection_set',
73 'reset_zoho_connect' => 'connection_reset',
74 'get_zoho_tax' => 'tax_get',
75 'save_zoho_tax' => 'tax_set',
76 'reset_zoho_tax' => 'tax_reset',
77 'get_zoho_product' => 'product_get',
78 'save_zoho_product' => 'product_set',
79 'reset_zoho_product' => 'product_reset',
80 'get_zoho_cron' => 'cron_get',
81 'save_zoho_cron' => 'cron_set',
82 'reset_zoho_cron' => 'cron_reset',
83 'get_zoho_order' => 'order_get',
84 'save_zoho_order' => 'order_set',
85 'reset_zoho_order' => 'order_reset',
86 'get_zoho_contact' => 'contact_get',
87 'save_zoho_contact' => 'contact_set',
88 'reset_zoho_contact' => 'contact_reset',
89 'get_zoho_price' => 'price_get',
90 'save_zoho_price' => 'price_set',
91 'reset_zoho_price' => 'price_reset',
92 'get_zoho_fields' => 'fields_get',
93 'save_zoho_fields' => 'fields_set',
94 'reset_zoho_fields' => 'fields_reset',
95 'is_connected' => 'connection_done',
96 'get_wc_taxes' => 'wc_tax_collect',
97 'get_zoho_taxes' => 'zoho_tax_rates_collect',
98 'get_zoho_categories' => 'zoho_categories_collect',
99 'get_zoho_locations' => 'zoho_locations_collect',
100 'get_zoho_prices' => 'zoho_prices_collect',
101 'get_all_custom_fields' => 'wc_custom_fields_collect',
102 'handle_code' => 'handle_code',
103 );
104
105 private const SOURCE = 'zoho';
106
107 /**
108 * ZohoInventoryAjax constructor.
109 */
110 public function __construct() {
111 $this->load_actions();
112 }
113
114 /**
115 * Collects custom checkout fields for WooCommerce.
116 *
117 * This function verifies the request and collects custom fields from the
118 * THWCFD_Utils::get_checkout_fields() function if the THWCFD class exists.
119 *
120 * @return void
121 */
122 public function wc_custom_fields_collect(): void {
123 $this->verify();
124 $types = array( 'billing', 'shipping', 'additional' );
125 $all_fields = array();
126 $custom_fields = array();
127 // Get all the fields.
128 foreach ( $types as $type ) {
129 // Skip if an unsupported type.
130 if (
131 ! in_array(
132 $type,
133 array(
134 'billing',
135 'shipping',
136 'additional',
137 ),
138 true,
139 )
140 ) {
141 continue;
142 }
143
144 $temp_fields = get_option( 'wc_fields_' . $type );
145 if ( false !== $temp_fields ) {
146 $all_fields = array_merge( $all_fields, $temp_fields );
147 }
148 }
149 // Loop through each field to see if it is a custom field.
150 foreach ( $all_fields as $name => $options ) {
151 if ( isset( $options['custom'] ) && $options['custom'] ) {
152 $label = trim( $options['label'] );
153 $custom_fields[ $name ] = empty( $label ) ? __( 'Please set label', 'commercebird' ) : $label;
154 }
155 }
156
157 $this->response = $custom_fields;
158
159 $this->serve();
160 }
161
162 /**
163 * Retrieves the connection details.
164 *
165 * @return void
166 */
167 public function connection_get(): void {
168 $this->verify();
169 $this->response['account_domain'] = get_option( 'cmbird_zoho_inventory_domain' );
170 $this->response['organization_id'] = get_option( 'cmbird_zoho_inventory_oid' );
171 $this->response['client_id'] = get_option( 'cmbird_zoho_inventory_cid' );
172 $this->response['client_secret'] = get_option( 'cmbird_zoho_inventory_cs' );
173 $this->response['inventory_url'] = get_option( 'cmbird_zoho_inventory_url' );
174 $this->response['redirect_uri'] = get_option( 'cmbird_authorization_redirect_uri' );
175 $this->serve();
176 }
177
178 /**
179 * Retrieves the subscription details.
180 *
181 * @return void
182 */
183 public function subscription_get(): void {
184 $this->verify();
185 $this->response = $this->get_subscription_data();
186 $this->serve();
187 }
188
189 /**
190 * @return array
191 */
192 public function get_subscription_data(): array {
193 $transient = get_transient( 'zoho_subscription' );
194 if ( ! empty( $transient ) ) {
195 return $transient;
196 }
197
198 $data = $this->get_subscription_data_from_api();
199
200 if ( ! empty( $data ) && array_key_exists( 'status', $data ) && 'error' !== $data['status'] ) {
201 set_transient( 'zoho_subscription', $data, WEEK_IN_SECONDS );
202 }
203
204 return $data;
205 }
206
207 private function get_subscription_data_from_api(): array {
208 $subscription_id = get_option( 'cmbird_zoho_id_status', 0 );
209 if ( ! $subscription_id ) {
210 return array();
211 }
212 $response = wp_safe_remote_get(
213 'https://commercebird.com/wp-json/app/v1/subscription/?subscription_id=' . rawurlencode( $subscription_id ),
214 array(
215 'headers' => array(
216 'Accept' => 'application/json',
217 'Authorization' => 'Basic Y2tfYjAzMDViODhmNmQ1ZDI2ZTY0MjNjMDczZjZmOTVkZTExOWNjOWU1NTpjc182MDljMTNmMjgxODE2YjkzNzQ5OWIyYTAwNTJlMTE0NTc0NWFjZGMz',
218 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
219 ),
220 'timeout' => 30,
221 ),
222 );
223
224 if ( is_wp_error( $response ) ) {
225 $this->errors = array( 'message' => $response->get_error_messages() );
226 $this->response = array( 'status' => 'error' );
227 return array();
228 }
229
230 $body = wp_remote_retrieve_body( $response );
231 $decode = json_decode( $body, true );
232 if ( ! $decode || ! array_key_exists( 'line_items', $decode ) ) {
233 return array();
234 }
235
236 $data = $this->extract_data(
237 $decode,
238 array(
239 'fee_lines',
240 'total',
241 'currency',
242 'next_payment_date_gmt',
243 'needs_payment',
244 'payment_url',
245 'status',
246 'variation_id',
247 'line_items',
248 'billing',
249 ),
250 );
251 $data['variation_id'] = array_column( $data['line_items'], 'variation_id' );
252 $data['plan'] = array_column( $data['line_items'], 'name' );
253
254 return $data;
255 }
256
257 /**
258 * Resets the settings details.
259 *
260 * @return void
261 */
262 public function settings_reset(): void {
263 $this->verify();
264 $this->option_status_remove( self::FORMS['settings'], self::SOURCE );
265 $this->response = array( 'message' => 'Reset successfully!' );
266 $this->serve();
267 }
268
269 /**
270 * Retrieves the settings details.
271 *
272 * @return void
273 */
274 public function settings_get(): void {
275 $this->verify();
276 $this->response = $this->option_status_get( self::FORMS['settings'], self::SOURCE );
277 $this->serve();
278 }
279
280 /**
281 * Sets the settings for the class.
282 *
283 * @return void
284 */
285 public function settings_set(): void {
286 try {
287 $this->verify( self::FORMS['settings'] );
288 if ( $this->data ) {
289 $this->option_status_update( $this->data, self::SOURCE );
290 delete_transient( 'zoho_subscription' );
291 } else {
292 $this->errors = array(
293 'message' => 'Invalid Inputs',
294 $this->data,
295 );
296 }
297 } catch (Exception $exception) {
298 $this->errors = array( 'message' => $exception->getMessage() );
299 }
300 $this->serve();
301 }
302
303 /**
304 * Retrieves the fields and serves the response.
305 *
306 * @return void
307 */
308 public function fields_get(): void {
309 $this->verify();
310 $this->response['form'] = get_option( 'cmbird_wootozoho_custom_fields', array() );
311 $this->serve();
312 }
313
314 /**
315 * Sets the custom fields for the form.
316 *
317 * @return void
318 */
319 public function fields_set(): void {
320 $this->verify( array( 'form' ) );
321 try {
322 update_option( 'cmbird_wootozoho_custom_fields', $this->data['form'] );
323 $this->response = array( 'message' => 'saved' );
324 } catch (Throwable $throwable) {
325 $this->errors = array( 'message' => $throwable->getMessage() );
326 }
327 $this->serve();
328 }
329
330 /**
331 * Resets the fields.
332 *
333 * @return void
334 */
335 public function fields_reset(): void {
336 $this->verify();
337 delete_option( 'cmbird_wootozoho_custom_fields' );
338 $this->response = array( 'message' => 'Reset successfully!' );
339 $this->serve();
340 }
341
342 /**
343 * Resets the price.
344 *
345 * @return void
346 */
347 public function price_reset(): void {
348 $this->verify();
349 delete_option( 'cmbird_zoho_pricelist_id' );
350 delete_option( 'cmbird_zoho_pricelist_role' );
351 delete_option( 'cmbird_zoho_pricelist_wcb2b_groups' );
352 $this->response = array( 'message' => 'Reset successfully!' );
353 $this->serve();
354 }
355
356 /**
357 * Retrieves the price information.
358 *
359 * @return void
360 */
361 public function price_get(): void {
362 $this->verify();
363 $this->response['zoho_inventory_pricelist'] = get_option( 'cmbird_zoho_pricelist_id' );
364 $this->response['wp_user_role'] = get_option( 'cmbird_zoho_pricelist_role' );
365 if ( class_exists( 'WooCommerceB2B' ) ) {
366 $this->response['wcb2b'] = get_option( 'cmbird_zoho_pricelist_wcb2b_groups' );
367 }
368 $this->serve();
369 }
370
371 /**
372 * Sets the price and saves the pricelist.
373 *
374 */
375 public function price_set(): void {
376 $this->verify( self::FORMS['price'] );
377 try {
378 $import_pricelist = new CMBIRD_Pricelist_ZI();
379 $success = $import_pricelist->save_price_list( $this->data );
380 if ( class_exists( 'Addify_B2B_Plugin' ) ) {
381 update_option( 'cmbird_zoho_pricelist_role', $this->data['wp_user_role'] );
382 } else {
383 update_option( 'cmbird_zoho_pricelist_wcb2b_groups', $this->data['wcb2b'] );
384 }
385 if ( $success ) {
386 $this->response = array( 'message' => 'Saved' );
387 if ( class_exists( 'WooCommerceB2B' ) ) {
388 $this->response['wcb2b'] = $this->data['wcb2b'];
389 }
390 } else {
391 $this->errors = array( 'message' => 'Failed to save' );
392 }
393 } catch (Throwable $throwable) {
394 $this->errors = array( 'message' => $throwable->getMessage() );
395 $this->write_log(
396 array(
397 'message' => $throwable->getMessage(),
398 'files' => wp_list_pluck( $throwable->getTrace(), 'file', 'line' ),
399 ),
400 'zoho-ajax-error'
401 );
402 }
403
404 $this->serve();
405 }
406
407 /**
408 * Collects Zoho prices.
409 *
410 * @return void
411 */
412 public function zoho_prices_collect(): void {
413 $this->verify();
414 $price_list_class = new CMBIRD_Pricelist_ZI();
415 $prices = $price_list_class->zi_get_all_pricelist();
416 $this->response = wp_list_pluck( $prices, 'name', 'pricebook_id' );
417 $this->serve();
418 }
419
420 /**
421 * Retrieves the contact details.
422 * @return void
423 */
424 public function contact_get() {
425 $this->verify();
426 $this->response = $this->option_status_get( self::FORMS['contact'], self::SOURCE );
427 $this->serve();
428 }
429 /**
430 * Sets the contact and updates the status.
431 * @return void
432 */
433 public function contact_set() {
434 $this->verify( self::FORMS['contact'] );
435 $this->option_status_update( $this->data, self::SOURCE );
436 if ( isset( $this->data['enable'] ) && ! empty( $this->data['enable'] ) ) {
437 if ( ! wp_next_scheduled( 'zoho_contact_sync' ) ) {
438 wp_schedule_event( time(), 'daily', 'zoho_contact_sync' );
439 }
440 } else {
441 wp_clear_scheduled_hook( 'zoho_contact_sync' );
442 }
443 $this->response = array( 'message' => 'Saved!' );
444 $this->serve();
445 }
446 /**
447 * Resets the contact.
448 * @return void
449 */
450 public function contact_reset() {
451 $this->verify();
452 $this->option_status_remove( self::FORMS['contact'], self::SOURCE );
453 $this->response = array( 'message' => 'Reset successfully!' );
454 $this->serve();
455 }
456
457 /**
458 * Sets the order and updates the status.
459 *
460 * @return void
461 */
462 public function order_set(): void {
463 $this->verify( self::FORMS['order'] );
464 $this->option_status_update( $this->data, self::SOURCE );
465 $this->response = array( 'message' => 'Saved!' );
466 $this->serve();
467 }
468
469 /**
470 * Retrieves the order.
471 *
472 * @return void
473 */
474 public function order_get(): void {
475 $this->verify();
476 $this->response = $this->option_status_get( self::FORMS['order'], self::SOURCE );
477 $this->serve();
478 }
479
480 /**
481 * Resets the order.
482 *
483 * @return void
484 */
485 public function order_reset(): void {
486 $this->verify();
487 $this->option_status_remove( self::FORMS['order'], self::SOURCE );
488 $this->response = array( 'message' => 'Reset successfully!' );
489 $this->serve();
490 }
491
492 /**
493 * Collects Zoho locations.
494 *
495 * This function verifies the request, retrieves the Zoho inventory
496 * organization ID and URL from the options, constructs the URL
497 * for the API call, and executes the cURL call to retrieve the
498 * locations. The response is then processed to extract the
499 * location names and IDs, and stored in the class property.
500 *
501 * @return void
502 */
503 public function zoho_locations_collect(): void {
504 // $fd = fopen( __DIR__ . '/zoho_locations.txt', 'w+' );
505 $this->verify();
506 $zoho_inventory_oid = get_option( 'cmbird_zoho_inventory_oid' );
507 $zoho_inventory_url = get_option( 'cmbird_zoho_inventory_url' );
508 $url = $zoho_inventory_url . 'inventory/v1/locations?organization_id=' . $zoho_inventory_oid;
509 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
510 $json = $execute_curl_call_handle->execute_curl_call_get( $url );
511 // save the first location id to the database of the first object of json
512 if ( ! empty( $json->locations ) && is_array( $json->locations ) && array_key_exists( 0, $json->locations ) ) {
513 $location_id = $json->locations[0]->location_id;
514 update_option( 'cmbird_zoho_parent_location_id_status', $location_id );
515 }
516 $this->response = wp_list_pluck( $json->locations, 'location_name', 'location_id' );
517 $this->serve();
518 }
519
520 /**
521 * Sets the cron for the class.
522 *
523 */
524 public function cron_set(): void {
525 $this->verify( self::FORMS['cron'] );
526 if ( array_key_exists( 'form', $this->data ) ) {
527 $decode = json_decode( $this->data['form'], true );
528 update_option( 'zi_cron_interval', $decode['zi_cron_interval'] );
529 unset( $decode['zi_cron_interval'] );
530 $this->option_status_update( $decode, self::SOURCE );
531 }
532 if ( array_key_exists( 'categories', $this->data ) ) {
533 $decode = json_decode( $this->data['categories'] );
534 update_option( 'cmbird_zoho_item_category', serialize( $decode ) );
535 }
536 $this->response = array( 'message' => 'Saved' );
537 // also set the cron job to sync categories.
538 if ( ! wp_next_scheduled( 'cmbird_zi_category_cron' ) ) {
539 wp_schedule_event( time(), 'daily', 'cmbird_zi_category_cron' );
540 }
541 $this->serve();
542 }
543
544 /**
545 * Executes the cron_get function.
546 *
547 * This function verifies the form status and retrieves the form options
548 * for syncing name, price, image, and description. It also retrieves
549 * the cron interval and the Zoho item categories.
550 *
551 * @return void
552 */
553 public function cron_get(): void {
554 $this->verify();
555 $this->response = array();
556 $this->response['form'] = $this->option_status_get(
557 array(
558 'disable_name_sync',
559 'disable_price_sync',
560 'disable_image_sync',
561 'disable_description_sync',
562 ),
563 self::SOURCE,
564 );
565 $this->response['form']['zi_cron_interval'] = get_option( 'zi_cron_interval', 'none' );
566 $categories = get_option( 'cmbird_zoho_item_category', '' );
567 $this->response['categories'] = maybe_unserialize( $categories );
568 $this->serve();
569 }
570
571 /**
572 * Resets the cron job.
573 *
574 * This function verifies the cron job, removes the specified options,
575 * deletes the 'zoho_item_category' option, and serves the cron job.
576 *
577 * @return void
578 */
579 public function cron_reset(): void {
580 $this->verify();
581 $this->option_status_remove(
582 array(
583 'disable_name_sync',
584 'disable_price_sync',
585 'disable_image_sync',
586 'disable_description_sync',
587 ),
588 self::SOURCE,
589 );
590 delete_option( 'cmbird_zoho_item_category' );
591 // delete all options that contain 'zoho_id_for_term_id_'
592 global $wpdb;
593 $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE 'zoho_id_for_term_id_%'" );
594 $this->response = array( 'message' => 'Reset successfully!' );
595 $this->serve();
596 }
597
598 /**
599 * Collects Zoho categories.
600 *
601 * This function verifies the data and retrieves the Zoho item categories.
602 * If the categories are successfully retrieved, it filters the data to
603 * include only the 'name' and 'category_id' fields, and removes the
604 * category with ID -1. Finally, it sets the response with the filtered
605 * categories and serves the response.
606 */
607 public function zoho_categories_collect(): void {
608 $this->verify();
609 $category_class = new CMBIRD_Categories_ZI();
610 $categories = $category_class->cmbird_get_zoho_item_categories();
611 if ( gettype( $categories ) === 'array' ) {
612 // $filtered = wp_list_pluck( $categories, 'name', 'category_id' );
613 // unset( $filtered[ -1 ] );
614 $this->response = $categories;
615 }
616 $this->serve();
617 }
618
619 /**
620 * Executes the connection process and handles the response.
621 */
622 public function connection_done(): void {
623 $this->verify();
624 $zoho_inventory_url = get_option( 'cmbird_zoho_inventory_url' );
625 $zoho_inventory_oid = get_option( 'cmbird_zoho_inventory_oid' );
626 $url = $zoho_inventory_url . 'inventory/v1/apiusagereport/dashboard?version=all&organization_id=' . $zoho_inventory_oid;
627
628 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
629 $json = $execute_curl_call_handle->execute_curl_call_get( $url );
630
631 if ( is_wp_error( $json ) ) {
632 $this->errors = array( 'message' => $json->get_error_message() );
633 return;
634 }
635
636 if ( empty( $json ) || empty( $json->data ) || empty( $json->data->api_usage ) ) {
637 $this->errors = array( 'message' => 'We lost connection with Zoho. Please refresh the page.' );
638 return;
639 }
640 $api_usage = $json->data->api_usage;
641 // Debug JSON encoding
642 $encoded_api_usage = wp_json_encode( $api_usage );
643 // Ensure it's not null
644 $this->response = json_decode( $encoded_api_usage, true ) ?? array();
645 $this->serve();
646 }
647
648 /**
649 * Executes the product_set function.
650 */
651 public function product_set(): void {
652 $this->verify( self::FORMS['product'] );
653 if ( ! empty( $this->data ) ) {
654 $this->option_status_update( $this->data, self::SOURCE );
655 }
656 $this->response = array( 'message' => 'Saved!' );
657 $this->serve();
658 }
659
660 /**
661 * Retrieves the product data.
662 *
663 * @return void
664 */
665 public function product_get(): void {
666 $this->verify();
667 $this->response = $this->option_status_get( self::FORMS['product'], self::SOURCE );
668 $this->serve();
669 }
670
671 /**
672 * Resets the product.
673 *
674 * @return void
675 */
676 public function product_reset(): void {
677 $this->verify();
678 $this->option_status_remove( self::FORMS['product'], self::SOURCE );
679 $this->response = array( 'message' => 'Reset successfully!' );
680 $this->serve();
681 }
682
683 /**
684 * Retrieves the tax information.
685 *
686 * @return void
687 */
688 public function tax_get(): void {
689 $this->verify();
690 $this->response = array();
691 foreach ( $this->wc_taxes() as $tax ) {
692 $this->response['selectedTaxRates'][] = $tax['id'] . '^^' . get_option( 'cmbird_zoho_inventory_tax_rate_' . $tax['id'] );
693 }
694 $this->serve();
695 }
696
697 /**
698 * Retrieves an array of all tax rates from WooCommerce.
699 *
700 * @return array An array of all tax rates.
701 */
702 public function wc_taxes(): array {
703 $wc_tax_array = array();
704 $tax_classes = WC_Tax::get_tax_classes(); // Retrieve all tax classes.
705 if ( ! in_array( '', $tax_classes ) ) { // Make sure "Standard rate" (empty class name) is present.
706 array_unshift( $tax_classes, '' );
707 }
708
709 foreach ( $tax_classes as $tax_class ) { // For each tax class, get all rates.
710 $taxes = WC_Tax::get_rates_for_tax_class( $tax_class );
711
712 foreach ( $taxes as $key => $tax ) {
713 $taxarray = (array) $tax;
714 $taxarray['id'] = $key;
715 $wc_tax_array[] = $taxarray;
716 }
717 }
718
719 return $wc_tax_array;
720 }
721
722 /**
723 * Resets the tax settings.
724 *
725 * This function verifies the tax settings and then deletes the options
726 * related to the tax rates
727 *
728 * @return void
729 */
730 public function tax_reset(): void {
731 $this->verify();
732 foreach ( $this->wc_taxes() as $tax ) {
733 delete_option( 'cmbird_zoho_inventory_tax_rate_' . $tax['id'] );
734 }
735 $this->response = array( 'message' => 'Reset successfully!' );
736 $this->serve();
737 }
738
739 /**
740 * Saves tax rates to the database.
741 */
742 public function tax_set(): void {
743 $this->verify( self::FORMS['tax'] );
744 $rates = array_filter( $this->data['selectedTaxRates'] );
745 try {
746 foreach ( $rates as $value ) {
747 $valarray = explode( '^^', $value );
748 update_option( 'cmbird_zoho_inventory_tax_rate_' . $valarray[0], $valarray[1] );
749 }
750 $this->response = array( 'message' => 'Saved' );
751 } catch (Throwable $throwable) {
752 $this->errors = array( 'message' => $throwable->getMessage() );
753 }
754
755 $this->serve();
756 }
757
758 /**
759 * Sets the connection for the Zoho Inventory API.
760 */
761 public function connection_set(): void {
762 $this->verify(
763 array(
764 'account_domain',
765 'organization_id',
766 'client_id',
767 'client_secret',
768 'redirect_uri',
769 ),
770 );
771 try {
772 $inventory = sprintf( 'https://www.zohoapis.%s/', $this->data['account_domain'] );
773 update_option( 'cmbird_zoho_inventory_domain', $this->data['account_domain'] );
774 update_option( 'cmbird_zoho_inventory_oid', $this->data['organization_id'] );
775 update_option( 'cmbird_zoho_inventory_cid', $this->data['client_id'] );
776 update_option( 'cmbird_zoho_inventory_cs', $this->data['client_secret'] );
777 update_option( 'cmbird_zoho_inventory_url', $inventory );
778 update_option( 'cmbird_authorization_redirect_uri', $this->data['redirect_uri'] );
779 $redirect = esc_url_raw( 'https://accounts.zoho.' . $this->data['account_domain'] . '/oauth/v2/auth?response_type=code&client_id=' . $this->data['client_id'] . '&scope=ZohoInventory.FullAccess.all&redirect_uri=' . $this->data['redirect_uri'] . '&prompt=consent&access_type=offline&state=' . wp_create_nonce( Template::NAME ) );
780 $this->response = array(
781 'redirect' => $redirect,
782 'message' => 'We are redirecting you to zoho. please wait...',
783 );
784 } catch (Throwable $throwable) {
785 $this->errors = array( 'message' => $throwable->getMessage() );
786 }
787
788 $this->serve();
789 }
790
791 /**
792 * Resets the connection by deleting specific options from the database.
793 */
794 public function connection_reset(): void {
795 $this->verify();
796 try {
797 // Check if resetAll is true (sent from Vue)
798 $reset_all = isset( $this->data['reset'] ) && $this->data['reset'] == 1;
799 if ( ! $reset_all ) {
800 $options = array(
801 'cmbird_zoho_inventory_domain',
802 'cmbird_zoho_inventory_oid',
803 'cmbird_zoho_inventory_cid',
804 'cmbird_zoho_inventory_cs',
805 'cmbird_zoho_inventory_url',
806 'cmbird_zoho_inventory_access_token',
807 );
808 foreach ( $options as $zi_option ) {
809 delete_option( $zi_option );
810 }
811 $this->response = array( 'message' => 'Reset successfully!' );
812 } else {
813 global $wpdb;
814 // Delete all product and customer meta keys
815 $wpdb->query( "DELETE FROM {$wpdb->prefix}postmeta WHERE meta_key IN ('zi_item_id', 'zi_category_id')" );
816 $wpdb->query( "DELETE FROM {$wpdb->prefix}usermeta WHERE meta_key IN ('zi_contact_id', 'zi_primary_contact_id', 'zi_billing_address_id', 'zi_shipping_address_id', 'zi_contact_persons_id')" );
817 // reset every option that starts with cmbird_
818 $wpdb->query( "DELETE FROM {$wpdb->prefix}options WHERE option_name LIKE 'cmbird_zoho_%'" );
819 $this->response['message'] = __( 'All settings are reset successfully', 'commercebird' );
820 }
821 } catch (Throwable $throwable) {
822 $this->errors = array( 'message' => $throwable->getMessage() );
823 }
824
825 $this->serve();
826 }
827
828 /**
829 * Retrieves the Zoho tax rates for the organization.
830 *
831 * This function verifies the request, retrieves the organization ID and URL
832 * from the options, constructs the URL for the API request, and executes
833 * the cURL call to fetch the tax rates. If the response contains the
834 * 'taxes' key, it sets the response to the tax rates. Otherwise, it sets
835 * the errors to a default message.
836 */
837 public function zoho_tax_rates_collect(): void {
838 $this->verify();
839 $zoho_inventory_oid = get_option( 'cmbird_zoho_inventory_oid' );
840 $zoho_inventory_url = get_option( 'cmbird_zoho_inventory_url' );
841 $url = $zoho_inventory_url . 'inventory/v1/settings/taxes?organization_id=' . $zoho_inventory_oid;
842 try {
843 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
844 $json = (array) $execute_curl_call_handle->execute_curl_call_get( $url );
845 if ( array_key_exists( 'taxes', $json ) ) {
846 $this->response = $json['taxes'];
847 } else {
848 $this->errors = array( 'message' => 'Something went wrong!' );
849 }
850 } catch (Throwable $throwable) {
851 $this->errors = array( 'message' => $throwable->getMessage() );
852 }
853
854 $this->serve();
855 }
856
857 /**
858 * Executes the wc_tax_collect function.
859 *
860 * This function verifies the current state, retrieves the taxes using the
861 * wc_taxes method, and serves the response.
862 */
863 public function wc_tax_collect(): void {
864 $this->verify();
865 $this->response = $this->wc_taxes();
866 $this->serve();
867 }
868
869 /**
870 * Handles the oAuth code.
871 */
872 public function handle_code(): void {
873 $this->verify();
874 if ( array_key_exists( 'code', $this->request ) ) {
875 $class_functions = new CMBIRD_Auth_Zoho();
876 $code = $this->request['code'];
877 try {
878 $access_token = $class_functions->get_zoho_access_token( $code, 'zoho_inventory' );
879 if ( array_key_exists( 'access_token', $access_token ) ) {
880 update_option( 'cmbird_zoho_inventory_auth_code', $code );
881 update_option( 'cmbird_zoho_inventory_access_token', $access_token['access_token'] );
882 update_option( 'cmbird_zoho_inventory_refresh_token', $access_token['refresh_token'] );
883 update_option( 'cmbird_zoho_inventory_timestamp', strtotime( gmdate( 'Y-m-d H:i:s' ) ) + $access_token['expires_in'] );
884 $this->response = (array) $access_token;
885 } else {
886 $this->errors = (array) $access_token;
887 }
888 } catch (Throwable $throwable) {
889 $this->errors = array( 'message' => $throwable->getMessage() );
890 }
891 }
892 $this->serve();
893 }
894 }
895