class-wc-api-taxes.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. <?php
  2. /**
  3. * WooCommerce API Taxes Class
  4. *
  5. * Handles requests to the /taxes endpoint
  6. *
  7. * @author WooThemes
  8. * @category API
  9. * @package WooCommerce/API
  10. * @since 2.5.0
  11. */
  12. if ( ! defined( 'ABSPATH' ) ) {
  13. exit; // Exit if accessed directly
  14. }
  15. class WC_API_Taxes extends WC_API_Resource {
  16. /** @var string $base the route base */
  17. protected $base = '/taxes';
  18. /**
  19. * Register the routes for this class
  20. *
  21. * GET /taxes
  22. * GET /taxes/count
  23. * GET /taxes/<id>
  24. *
  25. * @since 2.1
  26. * @param array $routes
  27. * @return array
  28. */
  29. public function register_routes( $routes ) {
  30. # GET/POST /taxes
  31. $routes[ $this->base ] = array(
  32. array( array( $this, 'get_taxes' ), WC_API_Server::READABLE ),
  33. array( array( $this, 'create_tax' ), WC_API_Server::CREATABLE | WC_API_Server::ACCEPT_DATA ),
  34. );
  35. # GET /taxes/count
  36. $routes[ $this->base . '/count' ] = array(
  37. array( array( $this, 'get_taxes_count' ), WC_API_Server::READABLE ),
  38. );
  39. # GET/PUT/DELETE /taxes/<id>
  40. $routes[ $this->base . '/(?P<id>\d+)' ] = array(
  41. array( array( $this, 'get_tax' ), WC_API_Server::READABLE ),
  42. array( array( $this, 'edit_tax' ), WC_API_SERVER::EDITABLE | WC_API_SERVER::ACCEPT_DATA ),
  43. array( array( $this, 'delete_tax' ), WC_API_SERVER::DELETABLE ),
  44. );
  45. # GET/POST /taxes/classes
  46. $routes[ $this->base . '/classes' ] = array(
  47. array( array( $this, 'get_tax_classes' ), WC_API_Server::READABLE ),
  48. array( array( $this, 'create_tax_class' ), WC_API_Server::CREATABLE | WC_API_Server::ACCEPT_DATA ),
  49. );
  50. # GET /taxes/classes/count
  51. $routes[ $this->base . '/classes/count' ] = array(
  52. array( array( $this, 'get_tax_classes_count' ), WC_API_Server::READABLE ),
  53. );
  54. # GET /taxes/classes/<slug>
  55. $routes[ $this->base . '/classes/(?P<slug>\w[\w\s\-]*)' ] = array(
  56. array( array( $this, 'delete_tax_class' ), WC_API_SERVER::DELETABLE ),
  57. );
  58. # POST|PUT /taxes/bulk
  59. $routes[ $this->base . '/bulk' ] = array(
  60. array( array( $this, 'bulk' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),
  61. );
  62. return $routes;
  63. }
  64. /**
  65. * Get all taxes
  66. *
  67. * @since 2.5.0
  68. *
  69. * @param string $fields
  70. * @param array $filter
  71. * @param string $class
  72. * @param int $page
  73. *
  74. * @return array
  75. */
  76. public function get_taxes( $fields = null, $filter = array(), $class = null, $page = 1 ) {
  77. if ( ! empty( $class ) ) {
  78. $filter['tax_rate_class'] = $class;
  79. }
  80. $filter['page'] = $page;
  81. $query = $this->query_tax_rates( $filter );
  82. $taxes = array();
  83. foreach ( $query['results'] as $tax ) {
  84. $taxes[] = current( $this->get_tax( $tax->tax_rate_id, $fields ) );
  85. }
  86. // Set pagination headers
  87. $this->server->add_pagination_headers( $query['headers'] );
  88. return array( 'taxes' => $taxes );
  89. }
  90. /**
  91. * Get the tax for the given ID
  92. *
  93. * @since 2.5.0
  94. *
  95. * @param int $id The tax ID
  96. * @param string $fields fields to include in response
  97. *
  98. * @return array|WP_Error
  99. */
  100. public function get_tax( $id, $fields = null ) {
  101. global $wpdb;
  102. try {
  103. $id = absint( $id );
  104. // Permissions check
  105. if ( ! current_user_can( 'manage_woocommerce' ) ) {
  106. throw new WC_API_Exception( 'woocommerce_api_user_cannot_read_tax', __( 'You do not have permission to read tax rate', 'woocommerce' ), 401 );
  107. }
  108. // Get tax rate details
  109. $tax = WC_Tax::_get_tax_rate( $id );
  110. if ( is_wp_error( $tax ) || empty( $tax ) ) {
  111. throw new WC_API_Exception( 'woocommerce_api_invalid_tax_id', __( 'A tax rate with the provided ID could not be found', 'woocommerce' ), 404 );
  112. }
  113. $tax_data = array(
  114. 'id' => (int) $tax['tax_rate_id'],
  115. 'country' => $tax['tax_rate_country'],
  116. 'state' => $tax['tax_rate_state'],
  117. 'postcode' => '',
  118. 'city' => '',
  119. 'rate' => $tax['tax_rate'],
  120. 'name' => $tax['tax_rate_name'],
  121. 'priority' => (int) $tax['tax_rate_priority'],
  122. 'compound' => (bool) $tax['tax_rate_compound'],
  123. 'shipping' => (bool) $tax['tax_rate_shipping'],
  124. 'order' => (int) $tax['tax_rate_order'],
  125. 'class' => $tax['tax_rate_class'] ? $tax['tax_rate_class'] : 'standard',
  126. );
  127. // Get locales from a tax rate
  128. $locales = $wpdb->get_results( $wpdb->prepare( "
  129. SELECT location_code, location_type
  130. FROM {$wpdb->prefix}woocommerce_tax_rate_locations
  131. WHERE tax_rate_id = %d
  132. ", $id ) );
  133. if ( ! is_wp_error( $tax ) && ! is_null( $tax ) ) {
  134. foreach ( $locales as $locale ) {
  135. $tax_data[ $locale->location_type ] = $locale->location_code;
  136. }
  137. }
  138. return array( 'tax' => apply_filters( 'woocommerce_api_tax_response', $tax_data, $tax, $fields, $this ) );
  139. } catch ( WC_API_Exception $e ) {
  140. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
  141. }
  142. }
  143. /**
  144. * Create a tax
  145. *
  146. * @since 2.5.0
  147. *
  148. * @param array $data
  149. *
  150. * @return array|WP_Error
  151. */
  152. public function create_tax( $data ) {
  153. try {
  154. if ( ! isset( $data['tax'] ) ) {
  155. throw new WC_API_Exception( 'woocommerce_api_missing_tax_data', sprintf( __( 'No %1$s data specified to create %1$s', 'woocommerce' ), 'tax' ), 400 );
  156. }
  157. // Check permissions
  158. if ( ! current_user_can( 'manage_woocommerce' ) ) {
  159. throw new WC_API_Exception( 'woocommerce_api_user_cannot_create_tax', __( 'You do not have permission to create tax rates', 'woocommerce' ), 401 );
  160. }
  161. $data = apply_filters( 'woocommerce_api_create_tax_data', $data['tax'], $this );
  162. $tax_data = array(
  163. 'tax_rate_country' => '',
  164. 'tax_rate_state' => '',
  165. 'tax_rate' => '',
  166. 'tax_rate_name' => '',
  167. 'tax_rate_priority' => 1,
  168. 'tax_rate_compound' => 0,
  169. 'tax_rate_shipping' => 1,
  170. 'tax_rate_order' => 0,
  171. 'tax_rate_class' => '',
  172. );
  173. foreach ( $tax_data as $key => $value ) {
  174. $new_key = str_replace( 'tax_rate_', '', $key );
  175. $new_key = 'tax_rate' === $new_key ? 'rate' : $new_key;
  176. if ( isset( $data[ $new_key ] ) ) {
  177. if ( in_array( $new_key, array( 'compound', 'shipping' ) ) ) {
  178. $tax_data[ $key ] = $data[ $new_key ] ? 1 : 0;
  179. } else {
  180. $tax_data[ $key ] = $data[ $new_key ];
  181. }
  182. }
  183. }
  184. // Create tax rate
  185. $id = WC_Tax::_insert_tax_rate( $tax_data );
  186. // Add locales
  187. if ( ! empty( $data['postcode'] ) ) {
  188. WC_Tax::_update_tax_rate_postcodes( $id, wc_clean( $data['postcode'] ) );
  189. }
  190. if ( ! empty( $data['city'] ) ) {
  191. WC_Tax::_update_tax_rate_cities( $id, wc_clean( $data['city'] ) );
  192. }
  193. do_action( 'woocommerce_api_create_tax', $id, $data );
  194. $this->server->send_status( 201 );
  195. return $this->get_tax( $id );
  196. } catch ( WC_API_Exception $e ) {
  197. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
  198. }
  199. }
  200. /**
  201. * Edit a tax
  202. *
  203. * @since 2.5.0
  204. *
  205. * @param int $id The tax ID
  206. * @param array $data
  207. *
  208. * @return array|WP_Error
  209. */
  210. public function edit_tax( $id, $data ) {
  211. try {
  212. if ( ! isset( $data['tax'] ) ) {
  213. throw new WC_API_Exception( 'woocommerce_api_missing_tax_data', sprintf( __( 'No %1$s data specified to edit %1$s', 'woocommerce' ), 'tax' ), 400 );
  214. }
  215. // Check permissions
  216. if ( ! current_user_can( 'manage_woocommerce' ) ) {
  217. throw new WC_API_Exception( 'woocommerce_api_user_cannot_edit_tax', __( 'You do not have permission to edit tax rates', 'woocommerce' ), 401 );
  218. }
  219. $data = $data['tax'];
  220. // Get current tax rate data
  221. $tax = $this->get_tax( $id );
  222. if ( is_wp_error( $tax ) ) {
  223. $error_data = $tax->get_error_data();
  224. throw new WC_API_Exception( $tax->get_error_code(), $tax->get_error_message(), $error_data['status'] );
  225. }
  226. $current_data = $tax['tax'];
  227. $data = apply_filters( 'woocommerce_api_edit_tax_data', $data, $this );
  228. $tax_data = array();
  229. $default_fields = array(
  230. 'tax_rate_country',
  231. 'tax_rate_state',
  232. 'tax_rate',
  233. 'tax_rate_name',
  234. 'tax_rate_priority',
  235. 'tax_rate_compound',
  236. 'tax_rate_shipping',
  237. 'tax_rate_order',
  238. 'tax_rate_class',
  239. );
  240. foreach ( $data as $key => $value ) {
  241. $new_key = 'rate' === $key ? 'tax_rate' : 'tax_rate_' . $key;
  242. // Check if the key is valid
  243. if ( ! in_array( $new_key, $default_fields ) ) {
  244. continue;
  245. }
  246. // Test new data against current data
  247. if ( $value === $current_data[ $key ] ) {
  248. continue;
  249. }
  250. // Fix compound and shipping values
  251. if ( in_array( $key, array( 'compound', 'shipping' ) ) ) {
  252. $value = $value ? 1 : 0;
  253. }
  254. $tax_data[ $new_key ] = $value;
  255. }
  256. // Update tax rate
  257. WC_Tax::_update_tax_rate( $id, $tax_data );
  258. // Update locales
  259. if ( ! empty( $data['postcode'] ) && $current_data['postcode'] != $data['postcode'] ) {
  260. WC_Tax::_update_tax_rate_postcodes( $id, wc_clean( $data['postcode'] ) );
  261. }
  262. if ( ! empty( $data['city'] ) && $current_data['city'] != $data['city'] ) {
  263. WC_Tax::_update_tax_rate_cities( $id, wc_clean( $data['city'] ) );
  264. }
  265. do_action( 'woocommerce_api_edit_tax_rate', $id, $data );
  266. return $this->get_tax( $id );
  267. } catch ( WC_API_Exception $e ) {
  268. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
  269. }
  270. }
  271. /**
  272. * Delete a tax
  273. *
  274. * @since 2.5.0
  275. *
  276. * @param int $id The tax ID
  277. *
  278. * @return array|WP_Error
  279. */
  280. public function delete_tax( $id ) {
  281. global $wpdb;
  282. try {
  283. // Check permissions
  284. if ( ! current_user_can( 'manage_woocommerce' ) ) {
  285. throw new WC_API_Exception( 'woocommerce_api_user_cannot_delete_tax', __( 'You do not have permission to delete tax rates', 'woocommerce' ), 401 );
  286. }
  287. $id = absint( $id );
  288. WC_Tax::_delete_tax_rate( $id );
  289. if ( 0 === $wpdb->rows_affected ) {
  290. throw new WC_API_Exception( 'woocommerce_api_cannot_delete_tax', __( 'Could not delete the tax rate', 'woocommerce' ), 401 );
  291. }
  292. return array( 'message' => sprintf( __( 'Deleted %s', 'woocommerce' ), 'tax' ) );
  293. } catch ( WC_API_Exception $e ) {
  294. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
  295. }
  296. }
  297. /**
  298. * Get the total number of taxes
  299. *
  300. * @since 2.5.0
  301. *
  302. * @param string $class
  303. * @param array $filter
  304. *
  305. * @return array|WP_Error
  306. */
  307. public function get_taxes_count( $class = null, $filter = array() ) {
  308. try {
  309. if ( ! current_user_can( 'manage_woocommerce' ) ) {
  310. throw new WC_API_Exception( 'woocommerce_api_user_cannot_read_taxes_count', __( 'You do not have permission to read the taxes count', 'woocommerce' ), 401 );
  311. }
  312. if ( ! empty( $class ) ) {
  313. $filter['tax_rate_class'] = $class;
  314. }
  315. $query = $this->query_tax_rates( $filter, true );
  316. return array( 'count' => (int) $query['headers']->total );
  317. } catch ( WC_API_Exception $e ) {
  318. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
  319. }
  320. }
  321. /**
  322. * Helper method to get tax rates objects
  323. *
  324. * @since 2.5.0
  325. *
  326. * @param array $args
  327. * @param bool $count_only
  328. *
  329. * @return array
  330. */
  331. protected function query_tax_rates( $args, $count_only = false ) {
  332. global $wpdb;
  333. $results = '';
  334. // Set args
  335. $args = $this->merge_query_args( $args, array() );
  336. $query = "
  337. SELECT tax_rate_id
  338. FROM {$wpdb->prefix}woocommerce_tax_rates
  339. WHERE 1 = 1
  340. ";
  341. // Filter by tax class
  342. if ( ! empty( $args['tax_rate_class'] ) ) {
  343. $tax_rate_class = 'standard' !== $args['tax_rate_class'] ? sanitize_title( $args['tax_rate_class'] ) : '';
  344. $query .= " AND tax_rate_class = '$tax_rate_class'";
  345. }
  346. // Order tax rates
  347. $order_by = ' ORDER BY tax_rate_order';
  348. // Pagination
  349. $per_page = isset( $args['posts_per_page'] ) ? $args['posts_per_page'] : get_option( 'posts_per_page' );
  350. $offset = 1 < $args['paged'] ? ( $args['paged'] - 1 ) * $per_page : 0;
  351. $pagination = sprintf( ' LIMIT %d, %d', $offset, $per_page );
  352. if ( ! $count_only ) {
  353. $results = $wpdb->get_results( $query . $order_by . $pagination );
  354. }
  355. $wpdb->get_results( $query );
  356. $headers = new stdClass;
  357. $headers->page = $args['paged'];
  358. $headers->total = (int) $wpdb->num_rows;
  359. $headers->is_single = $per_page > $headers->total;
  360. $headers->total_pages = ceil( $headers->total / $per_page );
  361. return array(
  362. 'results' => $results,
  363. 'headers' => $headers,
  364. );
  365. }
  366. /**
  367. * Bulk update or insert taxes
  368. * Accepts an array with taxes in the formats supported by
  369. * WC_API_Taxes->create_tax() and WC_API_Taxes->edit_tax()
  370. *
  371. * @since 2.5.0
  372. *
  373. * @param array $data
  374. *
  375. * @return array|WP_Error
  376. */
  377. public function bulk( $data ) {
  378. try {
  379. if ( ! isset( $data['taxes'] ) ) {
  380. throw new WC_API_Exception( 'woocommerce_api_missing_taxes_data', sprintf( __( 'No %1$s data specified to create/edit %1$s', 'woocommerce' ), 'taxes' ), 400 );
  381. }
  382. $data = $data['taxes'];
  383. $limit = apply_filters( 'woocommerce_api_bulk_limit', 100, 'taxes' );
  384. // Limit bulk operation
  385. if ( count( $data ) > $limit ) {
  386. throw new WC_API_Exception( 'woocommerce_api_taxes_request_entity_too_large', sprintf( __( 'Unable to accept more than %s items for this request.', 'woocommerce' ), $limit ), 413 );
  387. }
  388. $taxes = array();
  389. foreach ( $data as $_tax ) {
  390. $tax_id = 0;
  391. // Try to get the tax rate ID
  392. if ( isset( $_tax['id'] ) ) {
  393. $tax_id = intval( $_tax['id'] );
  394. }
  395. if ( $tax_id ) {
  396. // Tax rate exists / edit tax rate
  397. $edit = $this->edit_tax( $tax_id, array( 'tax' => $_tax ) );
  398. if ( is_wp_error( $edit ) ) {
  399. $taxes[] = array(
  400. 'id' => $tax_id,
  401. 'error' => array( 'code' => $edit->get_error_code(), 'message' => $edit->get_error_message() ),
  402. );
  403. } else {
  404. $taxes[] = $edit['tax'];
  405. }
  406. } else {
  407. // Tax rate don't exists / create tax rate
  408. $new = $this->create_tax( array( 'tax' => $_tax ) );
  409. if ( is_wp_error( $new ) ) {
  410. $taxes[] = array(
  411. 'id' => $tax_id,
  412. 'error' => array( 'code' => $new->get_error_code(), 'message' => $new->get_error_message() ),
  413. );
  414. } else {
  415. $taxes[] = $new['tax'];
  416. }
  417. }
  418. }
  419. return array( 'taxes' => apply_filters( 'woocommerce_api_taxes_bulk_response', $taxes, $this ) );
  420. } catch ( WC_API_Exception $e ) {
  421. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
  422. }
  423. }
  424. /**
  425. * Get all tax classes
  426. *
  427. * @since 2.5.0
  428. *
  429. * @param string $fields
  430. *
  431. * @return array|WP_Error
  432. */
  433. public function get_tax_classes( $fields = null ) {
  434. try {
  435. // Permissions check
  436. if ( ! current_user_can( 'manage_woocommerce' ) ) {
  437. throw new WC_API_Exception( 'woocommerce_api_user_cannot_read_tax_classes', __( 'You do not have permission to read tax classes', 'woocommerce' ), 401 );
  438. }
  439. $tax_classes = array();
  440. // Add standard class
  441. $tax_classes[] = array(
  442. 'slug' => 'standard',
  443. 'name' => __( 'Standard rate', 'woocommerce' ),
  444. );
  445. $classes = WC_Tax::get_tax_classes();
  446. foreach ( $classes as $class ) {
  447. $tax_classes[] = apply_filters( 'woocommerce_api_tax_class_response', array(
  448. 'slug' => sanitize_title( $class ),
  449. 'name' => $class,
  450. ), $class, $fields, $this );
  451. }
  452. return array( 'tax_classes' => apply_filters( 'woocommerce_api_tax_classes_response', $tax_classes, $classes, $fields, $this ) );
  453. } catch ( WC_API_Exception $e ) {
  454. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
  455. }
  456. }
  457. /**
  458. * Create a tax class.
  459. *
  460. * @since 2.5.0
  461. *
  462. * @param array $data
  463. *
  464. * @return array|WP_Error
  465. */
  466. public function create_tax_class( $data ) {
  467. try {
  468. if ( ! isset( $data['tax_class'] ) ) {
  469. throw new WC_API_Exception( 'woocommerce_api_missing_tax_class_data', sprintf( __( 'No %1$s data specified to create %1$s', 'woocommerce' ), 'tax_class' ), 400 );
  470. }
  471. // Check permissions
  472. if ( ! current_user_can( 'manage_woocommerce' ) ) {
  473. throw new WC_API_Exception( 'woocommerce_api_user_cannot_create_tax_class', __( 'You do not have permission to create tax classes', 'woocommerce' ), 401 );
  474. }
  475. $data = $data['tax_class'];
  476. if ( empty( $data['name'] ) ) {
  477. throw new WC_API_Exception( 'woocommerce_api_missing_tax_class_name', sprintf( __( 'Missing parameter %s', 'woocommerce' ), 'name' ), 400 );
  478. }
  479. $name = sanitize_text_field( $data['name'] );
  480. $slug = sanitize_title( $name );
  481. $classes = WC_Tax::get_tax_classes();
  482. $exists = false;
  483. // Check if class exists.
  484. foreach ( $classes as $key => $class ) {
  485. if ( sanitize_title( $class ) === $slug ) {
  486. $exists = true;
  487. break;
  488. }
  489. }
  490. // Return error if tax class already exists.
  491. if ( $exists ) {
  492. throw new WC_API_Exception( 'woocommerce_api_cannot_create_tax_class', __( 'Tax class already exists', 'woocommerce' ), 401 );
  493. }
  494. // Add the new class.
  495. $classes[] = $name;
  496. update_option( 'woocommerce_tax_classes', implode( "\n", $classes ) );
  497. do_action( 'woocommerce_api_create_tax_class', $slug, $data );
  498. $this->server->send_status( 201 );
  499. return array(
  500. 'tax_class' => array(
  501. 'slug' => $slug,
  502. 'name' => $name,
  503. ),
  504. );
  505. } catch ( WC_API_Exception $e ) {
  506. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
  507. }
  508. }
  509. /**
  510. * Delete a tax class
  511. *
  512. * @since 2.5.0
  513. *
  514. * @param int $slug The tax class slug
  515. *
  516. * @return array|WP_Error
  517. */
  518. public function delete_tax_class( $slug ) {
  519. global $wpdb;
  520. try {
  521. // Check permissions
  522. if ( ! current_user_can( 'manage_woocommerce' ) ) {
  523. throw new WC_API_Exception( 'woocommerce_api_user_cannot_delete_tax_class', __( 'You do not have permission to delete tax classes', 'woocommerce' ), 401 );
  524. }
  525. $slug = sanitize_title( $slug );
  526. $classes = WC_Tax::get_tax_classes();
  527. $deleted = false;
  528. foreach ( $classes as $key => $class ) {
  529. if ( sanitize_title( $class ) === $slug ) {
  530. unset( $classes[ $key ] );
  531. $deleted = true;
  532. break;
  533. }
  534. }
  535. if ( ! $deleted ) {
  536. throw new WC_API_Exception( 'woocommerce_api_cannot_delete_tax_class', __( 'Could not delete the tax class', 'woocommerce' ), 401 );
  537. }
  538. update_option( 'woocommerce_tax_classes', implode( "\n", $classes ) );
  539. // Delete tax rate locations locations from the selected class.
  540. $wpdb->query( $wpdb->prepare( "
  541. DELETE locations.*
  542. FROM {$wpdb->prefix}woocommerce_tax_rate_locations AS locations
  543. INNER JOIN
  544. {$wpdb->prefix}woocommerce_tax_rates AS rates
  545. ON rates.tax_rate_id = locations.tax_rate_id
  546. WHERE rates.tax_rate_class = '%s'
  547. ", $slug ) );
  548. // Delete tax rates in the selected class.
  549. $wpdb->delete( $wpdb->prefix . 'woocommerce_tax_rates', array( 'tax_rate_class' => $slug ), array( '%s' ) );
  550. return array( 'message' => sprintf( __( 'Deleted %s', 'woocommerce' ), 'tax_class' ) );
  551. } catch ( WC_API_Exception $e ) {
  552. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
  553. }
  554. }
  555. /**
  556. * Get the total number of tax classes
  557. *
  558. * @since 2.5.0
  559. *
  560. * @return array|WP_Error
  561. */
  562. public function get_tax_classes_count() {
  563. try {
  564. if ( ! current_user_can( 'manage_woocommerce' ) ) {
  565. throw new WC_API_Exception( 'woocommerce_api_user_cannot_read_tax_classes_count', __( 'You do not have permission to read the tax classes count', 'woocommerce' ), 401 );
  566. }
  567. $total = count( WC_Tax::get_tax_classes() ) + 1; // +1 for Standard Rate
  568. return array( 'count' => $total );
  569. } catch ( WC_API_Exception $e ) {
  570. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
  571. }
  572. }
  573. }