PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 3.6.4
Tutor LMS – eLearning and online course solution v3.6.4
3.9.15 3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / ecommerce / Tax.php
tutor / ecommerce Last commit date
Cart 1 year ago PaymentGateways 1 year ago AdminMenu.php 1 year ago BillingController.php 1 year ago CartController.php 1 year ago CheckoutController.php 1 year ago CouponController.php 1 year ago Ecommerce.php 1 year ago EmailController.php 1 year ago HooksHandler.php 1 year ago OptionKeys.php 1 year ago OrderActivitiesController.php 1 year ago OrderController.php 1 year ago PaymentHandler.php 1 year ago Settings.php 1 year ago Tax.php 1 year ago currency.php 1 year ago
Tax.php
315 lines
1 <?php
2 /**
3 * Tax calculation class for tutor monetization.
4 *
5 * @package Tutor\Ecommerce
6 * @author Themeum
7 * @link https://themeum.com
8 * @since 3.0.0
9 */
10
11 namespace Tutor\Ecommerce;
12
13 use Tutor\Traits\JsonResponse;
14
15 /**
16 * Class Tax
17 *
18 * @since 3.0.0
19 */
20 class Tax {
21 use JsonResponse;
22
23 /**
24 * Tax type const.
25 */
26 const TYPE_INCLUSIVE = 'inclusive';
27 const TYPE_EXCLUSIVE = 'exclusive';
28
29 /**
30 * Register hooks and dependencies.
31 *
32 * @since 3.0.0
33 *
34 * @param boolean $register_hooks hook register or not.
35 */
36 public function __construct( $register_hooks = true ) {
37 if ( ! $register_hooks ) {
38 return;
39 }
40
41 add_filter( 'tutor_option_input', array( $this, 'format_tax_data_before_save' ) );
42 add_action( 'wp_ajax_tutor_get_tax_settings', array( $this, 'ajax_get_tax_settings' ) );
43 }
44
45 /**
46 * Format ecommerce tax setting data before save it to tutor settings.
47 *
48 * @param array $option option.
49 *
50 * @return array
51 */
52 public function format_tax_data_before_save( $option ) {
53 if ( ! empty( $option['ecommerce_tax'] ) ) {
54 $option['ecommerce_tax'] = wp_unslash( $option['ecommerce_tax'] );
55 }
56
57 return $option;
58 }
59
60 /**
61 * Get the tax settings from the tutor options.
62 *
63 * @since 3.0.0
64 *
65 * @return void
66 */
67 public function ajax_get_tax_settings() {
68 tutor_utils()->checking_nonce();
69 tutor_utils()->check_current_user_capability();
70
71 $tax_settings = self::get_settings();
72
73 if ( ! empty( $tax_settings->active_country ) ) {
74 $tax_settings->active_country = null;
75 }
76
77 $this->json_response( __( 'Success', 'tutor' ), $tax_settings );
78 }
79
80 /**
81 * Get tax settings.
82 *
83 * @since 3.0.0
84 *
85 * @return object
86 */
87 public static function get_settings() {
88 $tax_settings = tutor_utils()->get_option( 'ecommerce_tax' );
89
90 if ( ! empty( $tax_settings ) && is_string( $tax_settings ) ) {
91 $tax_settings = json_decode( $tax_settings );
92 }
93
94 return $tax_settings;
95 }
96
97 /**
98 * Get tax settings key data.
99 *
100 * @since 3.0.0
101 *
102 * @param string $key key.
103 * @param mixed $default default value.
104 *
105 * @return mixed
106 */
107 public static function get_setting( $key, $default = false ) {
108 $tax_settings = self::get_settings();
109
110 if ( ! empty( $tax_settings->$key ) ) {
111 return $tax_settings->$key;
112 }
113
114 return $default;
115 }
116
117 /**
118 * Calculate tax.
119 *
120 * @since 3.0.0
121 *
122 * @param float $amount amount.
123 * @param float $rate tax rate.
124 *
125 * @return float
126 */
127 public static function calculate_tax( $amount, $rate ) {
128 if ( 0 === $rate ) {
129 return $rate;
130 }
131
132 if ( self::is_tax_included_in_price() ) {
133 // Tax = (Tax Rate X Price) / (1 + Tax Rate).
134 // Amount Without Tax = Amount With Tax / (1 + Tax Rate).
135 $tax_rate = $rate / 100;
136 $tax = ( $tax_rate * $amount ) / ( 1 + $tax_rate );
137 } else {
138 try {
139 $tax = $amount * ( $rate / 100 );
140 } catch ( \Throwable $th ) {
141 $tax = 0.0;
142 }
143 }
144
145 // Tax amount should not negative value.
146 return max( 0, round( $tax, 2 ) );
147 }
148
149 /**
150 * Get text rate for a user according to billing country and state.
151 *
152 * @param integer $user_id user id.
153 *
154 * @return float tax rate.
155 */
156 public static function get_user_tax_rate( $user_id = 0 ) {
157 $billing_info = ( new BillingController( false ) )->get_billing_info( $user_id );
158 $billing_country = $billing_info->billing_country ?? '';
159 $billing_state = $billing_info->billing_state ?? '';
160
161 return self::get_country_state_tax_rate( $billing_country, $billing_state );
162 }
163
164 /**
165 * Check site admin configured tax or not.
166 *
167 * @since 3.0.0
168 *
169 * @return boolean
170 */
171 public static function is_tax_configured() {
172 $tax_settings = self::get_settings();
173
174 return ( is_object( $tax_settings )
175 && isset( $tax_settings->rates )
176 && count( $tax_settings->rates ) );
177 }
178
179 /**
180 * Check tax is included in price or not.
181 *
182 * @since 3.0.0
183 *
184 * @return boolean
185 */
186 public static function is_tax_included_in_price() {
187 return (bool) self::get_setting( 'is_tax_included_in_price' );
188 }
189
190 /**
191 * Show price with tax in course list and details.
192 *
193 * @since 3.0.0
194 *
195 * @return bool
196 */
197 public static function show_price_with_tax() {
198 return (bool) self::get_setting( 'show_price_with_tax' );
199 }
200
201 /**
202 * Get tax type.
203 *
204 * @since 3.0.0
205 *
206 * @return string
207 */
208 public static function get_tax_type() {
209 return self::is_tax_included_in_price() ? self::TYPE_INCLUSIVE : self::TYPE_EXCLUSIVE;
210 }
211
212 /**
213 * Get country rate.
214 *
215 * @since 3.0.0
216 *
217 * @since 3.3.0 Country param is optional
218 *
219 * @param string $country the country code for which the tax rate needs to be found.
220 * @param string $state state name.
221 *
222 * @return float tax rate value.
223 */
224 public static function get_country_state_tax_rate( $country = null, $state = null ) {
225 $zero_tax = 0.0;
226
227 $country = apply_filters( 'tutor_ecommerce_tax_country', $country );
228 $state = apply_filters( 'tutor_ecommerce_tax_state', $state );
229
230 if ( empty( $country ) ) {
231 return $zero_tax;
232 }
233
234 $country_info = self::get_country_info( $country );
235 if ( ! $country_info ) {
236 return $zero_tax;
237 }
238
239 $country_code = $country_info['numeric_code'] ?? '';
240 $country_rate_data = null;
241
242 $tax_settings = self::get_settings();
243 if ( empty( $tax_settings->rates ) ) {
244 return $zero_tax;
245 }
246
247 foreach ( $tax_settings->rates as $rate ) {
248 if ( $rate->country === $country_code ) {
249 $country_rate_data = $rate;
250 break;
251 }
252 }
253
254 if ( empty( $country_rate_data ) ) {
255 return $zero_tax;
256 }
257
258 if ( $country_rate_data->is_same_rate || 0 === count( $country_rate_data->states ) ) {
259 return floatval( $country_rate_data->rate );
260 } else {
261 // Get state rate.
262 $state_info = self::get_state_info( $country_info['states'], $state );
263 if ( empty( $state_info ) ) {
264 return $zero_tax;
265 }
266
267 $state_rate = null;
268 foreach ( $country_rate_data->states as $item ) {
269 if ( $item->id === $state_info['id'] ) {
270 $state_rate = floatval( $item->rate );
271 break;
272 }
273 }
274
275 return $state_rate;
276 }
277 }
278
279 /**
280 * Get country info by name.
281 *
282 * @since 3.0.0
283 *
284 * @param string $name name of country.
285 *
286 * @return array|null
287 */
288 public static function get_country_info( $name ) {
289 $countries = tutor_get_country_list();
290 foreach ( $countries as $country ) {
291 if ( strtolower( $country['name'] ) === strtolower( $name ) ) {
292 return $country;
293 }
294 }
295 }
296
297 /**
298 * Get state info of a country.
299 *
300 * @since 3.0.0
301 *
302 * @param array $states list of states of a country.
303 * @param string $state_name name of state.
304 *
305 * @return array|null
306 */
307 public static function get_state_info( $states, $state_name ) {
308 foreach ( $states as $state ) {
309 if ( strtolower( $state['name'] ) === strtolower( $state_name ) ) {
310 return $state;
311 }
312 }
313 }
314 }
315