Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like WC_Tax often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use WC_Tax, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
16 | class WC_Tax { |
||
17 | |||
18 | /** |
||
19 | * Precision. |
||
20 | * |
||
21 | * @var int |
||
22 | */ |
||
23 | public static $precision; |
||
24 | |||
25 | /** |
||
26 | * Round at subtotal. |
||
27 | * |
||
28 | * @var bool |
||
29 | */ |
||
30 | public static $round_at_subtotal; |
||
31 | |||
32 | /** |
||
33 | * Load options. |
||
34 | * |
||
35 | * @access public |
||
36 | */ |
||
37 | public static function init() { |
||
41 | |||
42 | /** |
||
43 | * Calculate tax for a line. |
||
44 | * @param float $price Price to calc tax on |
||
45 | * @param array $rates Rates to apply |
||
46 | * @param boolean $price_includes_tax Whether the passed price has taxes included |
||
47 | * @param boolean $suppress_rounding Whether to suppress any rounding from taking place |
||
48 | * @return array Array of rates + prices after tax |
||
49 | */ |
||
50 | public static function calc_tax( $price, $rates, $price_includes_tax = false, $suppress_rounding = false ) { |
||
71 | |||
72 | /** |
||
73 | * Calculate the shipping tax using a passed array of rates. |
||
74 | * |
||
75 | * @param float Price |
||
76 | * @param array Taxation Rate |
||
77 | * @return array |
||
78 | */ |
||
79 | public static function calc_shipping_tax( $price, $rates ) { |
||
82 | |||
83 | /** |
||
84 | * Multiply cost by pow precision. |
||
85 | * @param float $price |
||
86 | * @return float |
||
87 | */ |
||
88 | private static function precision( $price ) { |
||
91 | |||
92 | /** |
||
93 | * Divide cost by pow precision. |
||
94 | * @param float $price |
||
95 | * @return float |
||
96 | */ |
||
97 | private static function remove_precision( $price ) { |
||
100 | |||
101 | /** |
||
102 | * Round to precision. |
||
103 | * |
||
104 | * Filter example: to return rounding to .5 cents you'd use: |
||
105 | * |
||
106 | * function euro_5cent_rounding( $in ) { |
||
107 | * return round( $in / 5, 2 ) * 5; |
||
108 | * } |
||
109 | * add_filter( 'woocommerce_tax_round', 'euro_5cent_rounding' ); |
||
110 | * @return double |
||
111 | */ |
||
112 | public static function round( $in ) { |
||
115 | |||
116 | /** |
||
117 | * Calc tax from inclusive price. |
||
118 | * |
||
119 | * @param float $price |
||
120 | * @param array $rates |
||
121 | * @return array |
||
122 | */ |
||
123 | public static function calc_inclusive_tax( $price, $rates ) { |
||
159 | |||
160 | /** |
||
161 | * Calc tax from exclusive price. |
||
162 | * |
||
163 | * @param float $price |
||
164 | * @param array $rates |
||
165 | * @return array |
||
166 | */ |
||
167 | public static function calc_exclusive_tax( $price, $rates ) { |
||
214 | |||
215 | /** |
||
216 | * Searches for all matching country/state/postcode tax rates. |
||
217 | * |
||
218 | * @param array $args |
||
219 | * @return array |
||
220 | */ |
||
221 | public static function find_rates( $args = array() ) { |
||
247 | |||
248 | /** |
||
249 | * Searches for all matching country/state/postcode tax rates. |
||
250 | * |
||
251 | * @param array $args |
||
252 | * @return array |
||
253 | */ |
||
254 | public static function find_shipping_rates( $args = array() ) { |
||
268 | |||
269 | /** |
||
270 | * Loop through a set of tax rates and get the matching rates (1 per priority). |
||
271 | * |
||
272 | * @param string $country |
||
273 | * @param string $state |
||
274 | * @param string $postcode |
||
275 | * @param string $city |
||
276 | * @param string $tax_class |
||
277 | * @return array |
||
278 | */ |
||
279 | private static function get_matched_tax_rates( $country, $state, $postcode, $city, $tax_class ) { |
||
358 | |||
359 | /** |
||
360 | * Get the customer tax location based on their status and the current page. |
||
361 | * |
||
362 | * Used by get_rates(), get_shipping_rates(). |
||
363 | * |
||
364 | * @param $tax_class string Optional, passed to the filter for advanced tax setups. |
||
365 | * @return array |
||
366 | */ |
||
367 | public static function get_tax_location( $tax_class = '' ) { |
||
383 | |||
384 | /** |
||
385 | * Get's an array of matching rates for a tax class. |
||
386 | * @param string $tax_class |
||
387 | * @return array |
||
388 | */ |
||
389 | public static function get_rates( $tax_class = '' ) { |
||
408 | |||
409 | /** |
||
410 | * Get's an array of matching rates for the shop's base country. |
||
411 | * |
||
412 | * @param string Tax Class |
||
413 | * @return array |
||
414 | */ |
||
415 | public static function get_base_tax_rates( $tax_class = '' ) { |
||
424 | |||
425 | /** |
||
426 | * Alias for get_base_tax_rates(). |
||
427 | * |
||
428 | * @deprecated 2.3 |
||
429 | * @param string Tax Class |
||
430 | * @return array |
||
431 | */ |
||
432 | public static function get_shop_base_rate( $tax_class = '' ) { |
||
435 | |||
436 | /** |
||
437 | * Gets an array of matching shipping tax rates for a given class. |
||
438 | * |
||
439 | * @param string Tax Class |
||
440 | * @return mixed |
||
441 | */ |
||
442 | public static function get_shipping_tax_rates( $tax_class = null ) { |
||
512 | |||
513 | /** |
||
514 | * Return true/false depending on if a rate is a compound rate. |
||
515 | * |
||
516 | * @param int key |
||
517 | * @return bool |
||
518 | */ |
||
519 | public static function is_compound( $key ) { |
||
523 | |||
524 | /** |
||
525 | * Return a given rates label. |
||
526 | * |
||
527 | * @param mixed $key_or_rate Tax rate ID, or the db row itself in object format |
||
528 | * @return string |
||
529 | */ |
||
530 | public static function get_rate_label( $key_or_rate ) { |
||
547 | |||
548 | /** |
||
549 | * Return a given rates percent. |
||
550 | * |
||
551 | * @param mixed $key_or_rate Tax rate ID, or the db row itself in object format |
||
552 | * @return string |
||
553 | */ |
||
554 | public static function get_rate_percent( $key_or_rate ) { |
||
567 | |||
568 | /** |
||
569 | * Get a rates code. Code is made up of COUNTRY-STATE-NAME-Priority. E.g GB-VAT-1, US-AL-TAX-1. |
||
570 | * |
||
571 | * @access public |
||
572 | * @param mixed $key_or_rate Tax rate ID, or the db row itself in object format |
||
573 | * @return string |
||
574 | */ |
||
575 | public static function get_rate_code( $key_or_rate ) { |
||
599 | |||
600 | /** |
||
601 | * Round tax lines and return the sum. |
||
602 | * |
||
603 | * @param array |
||
604 | * @return float |
||
605 | */ |
||
606 | public static function get_tax_total( $taxes ) { |
||
609 | |||
610 | /** |
||
611 | * Get store tax classes. |
||
612 | * @return array |
||
613 | */ |
||
614 | public static function get_tax_classes() { |
||
617 | |||
618 | /** |
||
619 | * format the city. |
||
620 | * @param string $city |
||
621 | * @return string |
||
622 | */ |
||
623 | private static function format_tax_rate_city( $city ) { |
||
624 | return strtoupper( trim( $city ) ); |
||
625 | } |
||
626 | |||
627 | /** |
||
628 | * format the state. |
||
629 | * @param string $state |
||
630 | * @return string |
||
631 | */ |
||
632 | private static function format_tax_rate_state( $state ) { |
||
636 | |||
637 | /** |
||
638 | * format the country. |
||
639 | * @param string $country |
||
640 | * @return string |
||
641 | */ |
||
642 | private static function format_tax_rate_country( $country ) { |
||
646 | |||
647 | /** |
||
648 | * format the tax rate name. |
||
649 | * @param string $name |
||
650 | * @return string |
||
651 | */ |
||
652 | private static function format_tax_rate_name( $name ) { |
||
655 | |||
656 | /** |
||
657 | * format the rate. |
||
658 | * @param double $rate |
||
659 | * @return string |
||
660 | */ |
||
661 | private static function format_tax_rate( $rate ) { |
||
664 | |||
665 | /** |
||
666 | * format the priority. |
||
667 | * @param string $priority |
||
668 | * @return int |
||
669 | */ |
||
670 | private static function format_tax_rate_priority( $priority ) { |
||
673 | |||
674 | /** |
||
675 | * format the class. |
||
676 | * @param string $class |
||
677 | * @return string |
||
678 | */ |
||
679 | public static function format_tax_rate_class( $class ) { |
||
687 | |||
688 | /** |
||
689 | * Prepare and format tax rate for DB insertion. |
||
690 | * @param array $tax_rate |
||
691 | * @return array |
||
692 | */ |
||
693 | private static function prepare_tax_rate( $tax_rate ) { |
||
701 | |||
702 | /** |
||
703 | * Insert a new tax rate. |
||
704 | * |
||
705 | * Internal use only. |
||
706 | * |
||
707 | * @since 2.3.0 |
||
708 | * @access private |
||
709 | * |
||
710 | * @param array $tax_rate |
||
711 | * |
||
712 | * @return int tax rate id |
||
713 | */ |
||
714 | public static function _insert_tax_rate( $tax_rate ) { |
||
725 | |||
726 | /** |
||
727 | * Get tax rate. |
||
728 | * |
||
729 | * Internal use only. |
||
730 | * |
||
731 | * @since 2.5.0 |
||
732 | * @access private |
||
733 | * |
||
734 | * @param int $tax_rate_id |
||
735 | * @param string $output_type |
||
736 | * |
||
737 | * @return array |
||
738 | */ |
||
739 | public static function _get_tax_rate( $tax_rate_id, $output_type = ARRAY_A ) { |
||
748 | |||
749 | /** |
||
750 | * Update a tax rate. |
||
751 | * |
||
752 | * Internal use only. |
||
753 | * |
||
754 | * @since 2.3.0 |
||
755 | * @access private |
||
756 | * |
||
757 | * @param int $tax_rate_id |
||
758 | * @param array $tax_rate |
||
759 | */ |
||
760 | public static function _update_tax_rate( $tax_rate_id, $tax_rate ) { |
||
777 | |||
778 | /** |
||
779 | * Delete a tax rate from the database. |
||
780 | * |
||
781 | * Internal use only. |
||
782 | * |
||
783 | * @since 2.3.0 |
||
784 | * @access private |
||
785 | * |
||
786 | * @param int $tax_rate_id |
||
787 | */ |
||
788 | public static function _delete_tax_rate( $tax_rate_id ) { |
||
798 | |||
799 | /** |
||
800 | * Update postcodes for a tax rate in the DB. |
||
801 | * |
||
802 | * Internal use only. |
||
803 | * |
||
804 | * @since 2.3.0 |
||
805 | * @access private |
||
806 | * |
||
807 | * @param int $tax_rate_id |
||
808 | * @param string $postcodes String of postcodes separated by ; characters |
||
809 | * @return string |
||
810 | */ |
||
811 | public static function _update_tax_rate_postcodes( $tax_rate_id, $postcodes ) { |
||
812 | if ( ! is_array( $postcodes ) ) { |
||
813 | $postcodes = explode( ';', $postcodes ); |
||
814 | } |
||
815 | self::_update_tax_rate_locations( $tax_rate_id, array_diff( array_map( 'wc_normalize_postcode', array_filter( $postcodes ) ), array( '*' ) ), 'postcode' ); |
||
816 | } |
||
817 | |||
818 | /** |
||
819 | * Update cities for a tax rate in the DB. |
||
820 | * |
||
821 | * Internal use only. |
||
822 | * |
||
823 | * @since 2.3.0 |
||
824 | * @access private |
||
825 | * |
||
826 | * @param int $tax_rate_id |
||
827 | * @param string $cities |
||
828 | * @return string |
||
829 | */ |
||
830 | public static function _update_tax_rate_cities( $tax_rate_id, $cities ) { |
||
838 | |||
839 | /** |
||
840 | * Updates locations (postcode and city). |
||
841 | * |
||
842 | * Internal use only. |
||
843 | * |
||
844 | * @since 2.3.0 |
||
845 | * @access private |
||
846 | * |
||
847 | * @param int $tax_rate_id |
||
848 | * @param string $type |
||
849 | * @return string |
||
850 | */ |
||
851 | private static function _update_tax_rate_locations( $tax_rate_id, $values, $type ) { |
||
873 | |||
874 | /** |
||
875 | * Used by admin settings page. |
||
876 | * |
||
877 | * @param string $tax_class |
||
878 | * |
||
879 | * @return array|null|object |
||
880 | */ |
||
881 | public static function get_rates_for_tax_class( $tax_class ) { |
||
908 | } |
||
909 | WC_Tax::init(); |
||
910 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.