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