class-wc-settings-tax.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. <?php
  2. /**
  3. * WooCommerce Tax Settings
  4. *
  5. * @author WooThemes
  6. * @category Admin
  7. * @package WooCommerce/Admin
  8. * @version 2.1.0
  9. */
  10. if ( ! defined( 'ABSPATH' ) ) {
  11. exit;
  12. }
  13. if ( class_exists( 'WC_Settings_Tax', false ) ) {
  14. return new WC_Settings_Tax();
  15. }
  16. /**
  17. * WC_Settings_Tax.
  18. */
  19. class WC_Settings_Tax extends WC_Settings_Page {
  20. /**
  21. * Constructor.
  22. */
  23. public function __construct() {
  24. $this->id = 'tax';
  25. $this->label = __( 'Tax', 'woocommerce' );
  26. add_filter( 'woocommerce_settings_tabs_array', array( $this, 'add_settings_page' ), 20 );
  27. if ( wc_tax_enabled() ) {
  28. add_action( 'woocommerce_sections_' . $this->id, array( $this, 'output_sections' ) );
  29. add_action( 'woocommerce_settings_' . $this->id, array( $this, 'output' ) );
  30. add_action( 'woocommerce_settings_save_' . $this->id, array( $this, 'save' ) );
  31. }
  32. }
  33. /**
  34. * Add this page to settings.
  35. *
  36. * @param array $pages Existing pages.
  37. * @return array|mixed
  38. */
  39. public function add_settings_page( $pages ) {
  40. if ( wc_tax_enabled() ) {
  41. return parent::add_settings_page( $pages );
  42. } else {
  43. return $pages;
  44. }
  45. }
  46. /**
  47. * Get sections.
  48. *
  49. * @return array
  50. */
  51. public function get_sections() {
  52. $sections = array(
  53. '' => __( 'Tax options', 'woocommerce' ),
  54. 'standard' => __( 'Standard rates', 'woocommerce' ),
  55. );
  56. // Get tax classes and display as links.
  57. $tax_classes = WC_Tax::get_tax_classes();
  58. foreach ( $tax_classes as $class ) {
  59. $sections[ sanitize_title( $class ) ] = sprintf( __( '%s rates', 'woocommerce' ), $class );
  60. }
  61. return apply_filters( 'woocommerce_get_sections_' . $this->id, $sections );
  62. }
  63. /**
  64. * Get settings array.
  65. *
  66. * @param string $current_section Current section being shown.
  67. * @return array
  68. */
  69. public function get_settings( $current_section = '' ) {
  70. $settings = array();
  71. if ( '' === $current_section ) {
  72. $settings = include 'views/settings-tax.php';
  73. }
  74. return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings, $current_section );
  75. }
  76. /**
  77. * Output the settings.
  78. */
  79. public function output() {
  80. global $current_section;
  81. $tax_classes = WC_Tax::get_tax_class_slugs();
  82. if ( 'standard' === $current_section || in_array( $current_section, $tax_classes, true ) ) {
  83. $this->output_tax_rates();
  84. } else {
  85. $settings = $this->get_settings();
  86. WC_Admin_Settings::output_fields( $settings );
  87. }
  88. }
  89. /**
  90. * Save settings.
  91. */
  92. public function save() {
  93. global $current_section;
  94. if ( ! $current_section ) {
  95. $settings = $this->get_settings();
  96. WC_Admin_Settings::save_fields( $settings );
  97. } elseif ( ! empty( $_POST['tax_rate_country'] ) ) {
  98. $this->save_tax_rates();
  99. }
  100. if ( $current_section ) {
  101. do_action( 'woocommerce_update_options_' . $this->id . '_' . $current_section );
  102. }
  103. // Invalidate caches.
  104. WC_Cache_Helper::incr_cache_prefix( 'taxes' );
  105. WC_Cache_Helper::get_transient_version( 'shipping', true );
  106. }
  107. /**
  108. * Output tax rate tables.
  109. */
  110. public function output_tax_rates() {
  111. global $current_section;
  112. $current_class = $this->get_current_tax_class();
  113. $countries = array();
  114. foreach ( WC()->countries->get_allowed_countries() as $value => $label ) {
  115. $countries[] = array(
  116. 'value' => $value,
  117. 'label' => esc_js( html_entity_decode( $label ) ),
  118. );
  119. }
  120. $states = array();
  121. foreach ( WC()->countries->get_allowed_country_states() as $label ) {
  122. foreach ( $label as $code => $state ) {
  123. $states[] = array(
  124. 'value' => $code,
  125. 'label' => esc_js( html_entity_decode( $state ) ),
  126. );
  127. }
  128. }
  129. $base_url = admin_url(
  130. add_query_arg(
  131. array(
  132. 'page' => 'wc-settings',
  133. 'tab' => 'tax',
  134. 'section' => $current_section,
  135. ), 'admin.php'
  136. )
  137. );
  138. // Localize and enqueue our js.
  139. wp_localize_script(
  140. 'wc-settings-tax', 'htmlSettingsTaxLocalizeScript', array(
  141. 'current_class' => $current_class,
  142. 'wc_tax_nonce' => wp_create_nonce( 'wc_tax_nonce-class:' . $current_class ),
  143. 'base_url' => $base_url,
  144. 'rates' => array_values( WC_Tax::get_rates_for_tax_class( $current_class ) ),
  145. 'page' => ! empty( $_GET['p'] ) ? absint( $_GET['p'] ) : 1,
  146. 'limit' => 100,
  147. 'countries' => $countries,
  148. 'states' => $states,
  149. 'default_rate' => array(
  150. 'tax_rate_id' => 0,
  151. 'tax_rate_country' => '',
  152. 'tax_rate_state' => '',
  153. 'tax_rate' => '',
  154. 'tax_rate_name' => '',
  155. 'tax_rate_priority' => 1,
  156. 'tax_rate_compound' => 0,
  157. 'tax_rate_shipping' => 1,
  158. 'tax_rate_order' => null,
  159. 'tax_rate_class' => $current_class,
  160. ),
  161. 'strings' => array(
  162. 'no_rows_selected' => __( 'No row(s) selected', 'woocommerce' ),
  163. 'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ),
  164. 'csv_data_cols' => array(
  165. __( 'Country code', 'woocommerce' ),
  166. __( 'State code', 'woocommerce' ),
  167. __( 'Postcode / ZIP', 'woocommerce' ),
  168. __( 'City', 'woocommerce' ),
  169. __( 'Rate %', 'woocommerce' ),
  170. __( 'Tax name', 'woocommerce' ),
  171. __( 'Priority', 'woocommerce' ),
  172. __( 'Compound', 'woocommerce' ),
  173. __( 'Shipping', 'woocommerce' ),
  174. __( 'Tax class', 'woocommerce' ),
  175. ),
  176. ),
  177. )
  178. );
  179. wp_enqueue_script( 'wc-settings-tax' );
  180. include 'views/html-settings-tax.php';
  181. }
  182. /**
  183. * Get tax class being edited.
  184. *
  185. * @return string
  186. */
  187. private static function get_current_tax_class() {
  188. global $current_section;
  189. $tax_classes = WC_Tax::get_tax_classes();
  190. $current_class = '';
  191. foreach ( $tax_classes as $class ) {
  192. if ( sanitize_title( $class ) === $current_section ) {
  193. $current_class = $class;
  194. }
  195. }
  196. return $current_class;
  197. }
  198. /**
  199. * Get a posted tax rate.
  200. *
  201. * @param string $key Key of tax rate in the post data array.
  202. * @param int $order Position/order of rate.
  203. * @param string $class Tax class for rate.
  204. * @return array
  205. */
  206. private function get_posted_tax_rate( $key, $order, $class ) {
  207. $tax_rate = array();
  208. $tax_rate_keys = array(
  209. 'tax_rate_country',
  210. 'tax_rate_state',
  211. 'tax_rate',
  212. 'tax_rate_name',
  213. 'tax_rate_priority',
  214. );
  215. foreach ( $tax_rate_keys as $tax_rate_key ) {
  216. if ( isset( $_POST[ $tax_rate_key ], $_POST[ $tax_rate_key ][ $key ] ) ) {
  217. $tax_rate[ $tax_rate_key ] = wc_clean( wp_unslash( $_POST[ $tax_rate_key ][ $key ] ) );
  218. }
  219. }
  220. $tax_rate['tax_rate_compound'] = isset( $_POST['tax_rate_compound'][ $key ] ) ? 1 : 0;
  221. $tax_rate['tax_rate_shipping'] = isset( $_POST['tax_rate_shipping'][ $key ] ) ? 1 : 0;
  222. $tax_rate['tax_rate_order'] = $order;
  223. $tax_rate['tax_rate_class'] = $class;
  224. return $tax_rate;
  225. }
  226. /**
  227. * Save tax rates.
  228. */
  229. public function save_tax_rates() {
  230. global $wpdb;
  231. $current_class = sanitize_title( $this->get_current_tax_class() );
  232. $posted_countries = wc_clean( wp_unslash( $_POST['tax_rate_country'] ) );
  233. // get the tax rate id of the first submited row.
  234. $first_tax_rate_id = key( $posted_countries );
  235. // get the order position of the first tax rate id.
  236. $tax_rate_order = absint( $wpdb->get_var( $wpdb->prepare( "SELECT tax_rate_order FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %s", $first_tax_rate_id ) ) );
  237. $index = isset( $tax_rate_order ) ? $tax_rate_order : 0;
  238. // Loop posted fields.
  239. foreach ( $posted_countries as $key => $value ) {
  240. $mode = ( 0 === strpos( $key, 'new-' ) ) ? 'insert' : 'update';
  241. $tax_rate = $this->get_posted_tax_rate( $key, $index ++, $current_class );
  242. if ( 'insert' === $mode ) {
  243. $tax_rate_id = WC_Tax::_insert_tax_rate( $tax_rate );
  244. } elseif ( 1 === absint( $_POST['remove_tax_rate'][ $key ] ) ) {
  245. $tax_rate_id = absint( $key );
  246. WC_Tax::_delete_tax_rate( $tax_rate_id );
  247. continue;
  248. } else {
  249. $tax_rate_id = absint( $key );
  250. WC_Tax::_update_tax_rate( $tax_rate_id, $tax_rate );
  251. }
  252. if ( isset( $_POST['tax_rate_postcode'][ $key ] ) ) {
  253. WC_Tax::_update_tax_rate_postcodes( $tax_rate_id, wc_clean( wp_unslash( $_POST['tax_rate_postcode'][ $key ] ) ) );
  254. }
  255. if ( isset( $_POST['tax_rate_city'][ $key ] ) ) {
  256. WC_Tax::_update_tax_rate_cities( $tax_rate_id, wc_clean( wp_unslash( $_POST['tax_rate_city'][ $key ] ) ) );
  257. }
  258. }
  259. }
  260. }
  261. return new WC_Settings_Tax();