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_Legacy_Cart 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_Legacy_Cart, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 18 | abstract class WC_Legacy_Cart { |
||
| 19 | /** |
||
| 20 | * Handle unset props. |
||
| 21 | * @param string $key |
||
| 22 | * @return mixed |
||
| 23 | */ |
||
| 24 | public function __get( $key ) { |
||
| 103 | |||
| 104 | /** |
||
| 105 | * @deprecated 2.7.0 |
||
| 106 | */ |
||
| 107 | public function add_discount( $coupon_code ) { |
||
| 111 | |||
| 112 | /** |
||
| 113 | * @deprecated 2.7.0 |
||
| 114 | */ |
||
| 115 | public function has_discount( $coupon_code = '' ) { |
||
| 119 | |||
| 120 | /** |
||
| 121 | * @deprecated 2.7.0 |
||
| 122 | */ |
||
| 123 | public function get_applied_coupons() { |
||
| 127 | |||
| 128 | /** |
||
| 129 | * @deprecated 2.7.0 |
||
| 130 | */ |
||
| 131 | public function check_cart_coupons() { |
||
| 135 | |||
| 136 | /** |
||
| 137 | * @deprecated 2.7.0 |
||
| 138 | */ |
||
| 139 | public function check_customer_coupons( $posted ) { |
||
| 144 | |||
| 145 | /** |
||
| 146 | * @deprecated 2.7.0 |
||
| 147 | */ |
||
| 148 | public function show_shipping() { |
||
| 152 | |||
| 153 | /** |
||
| 154 | * @deprecated 2.7.0 |
||
| 155 | */ |
||
| 156 | public function calculate_fees() { |
||
| 160 | |||
| 161 | /** |
||
| 162 | * Add a product to the cart. |
||
| 163 | * @deprecated 2.7.0 |
||
| 164 | * @param int $product_id contains the id of the product to add to the cart |
||
| 165 | * @param int $quantity contains the quantity of the item to add |
||
| 166 | * @param int $variation_id |
||
| 167 | * @param array $variation attribute values |
||
| 168 | * @param array $cart_item_data extra cart item data we want to pass into the item |
||
| 169 | * @return string|bool $cart_item_key |
||
| 170 | */ |
||
| 171 | public function add_to_cart( $product_id = 0, $quantity = 1, $variation_id = 0, $variation = array(), $cart_item_data = array() ) { |
||
| 185 | |||
| 186 | /** |
||
| 187 | * Get cart items quantities - merged so we can do accurate stock checks on items across multiple lines. |
||
| 188 | * @return array |
||
| 189 | */ |
||
| 190 | public function get_cart_item_quantities() { |
||
| 194 | |||
| 195 | /** |
||
| 196 | * @deprecated 2.7.0 |
||
| 197 | */ |
||
| 198 | public function check_cart_items() { |
||
| 202 | |||
| 203 | /** |
||
| 204 | * @deprecated 2.7.0 |
||
| 205 | */ |
||
| 206 | public function check_cart_item_stock() { |
||
| 209 | |||
| 210 | /** |
||
| 211 | * @deprecated 2.7.0 |
||
| 212 | */ |
||
| 213 | public function persistent_cart_update() { |
||
| 216 | |||
| 217 | /** |
||
| 218 | * @deprecated 2.7.0 |
||
| 219 | */ |
||
| 220 | public function persistent_cart_destroy() { |
||
| 223 | |||
| 224 | /** |
||
| 225 | * Determines the value that the customer spent and the subtotal |
||
| 226 | * displayed, used for things like coupon validation. |
||
| 227 | * |
||
| 228 | * Since the coupon lines are displayed based on the TAX DISPLAY value |
||
| 229 | * of cart, this is used to determine the spend. |
||
| 230 | * |
||
| 231 | * If cart totals are shown including tax, use the subtotal. |
||
| 232 | * If cart totals are shown excluding tax, use the subtotal ex tax |
||
| 233 | * (tax is shown after coupons). |
||
| 234 | * @deprecated 2.7.0 |
||
| 235 | * @since 2.6.0 |
||
| 236 | * @return string |
||
| 237 | */ |
||
| 238 | public function get_displayed_subtotal() { |
||
| 242 | |||
| 243 | /** |
||
| 244 | * Get the product row price per item. |
||
| 245 | * |
||
| 246 | * @param WC_Product $product |
||
| 247 | * @return string formatted price |
||
| 248 | */ |
||
| 249 | public function get_product_price( $product ) { |
||
| 253 | |||
| 254 | /** |
||
| 255 | * Gets the sub total (after calculation). |
||
| 256 | * @deprecated 2.7.0 |
||
| 257 | * @param bool $compound whether to include compound taxes |
||
| 258 | * @return string formatted price |
||
| 259 | */ |
||
| 260 | public function get_cart_subtotal( $compound = false ) { |
||
| 264 | |||
| 265 | /** |
||
| 266 | * Get the product row subtotal. |
||
| 267 | * |
||
| 268 | * Gets the tax etc to avoid rounding issues. |
||
| 269 | * |
||
| 270 | * When on the checkout (review order), this will get the subtotal based on the customer's tax rate rather than the base rate. |
||
| 271 | * |
||
| 272 | * @param WC_Product $product |
||
| 273 | * @param int $quantity |
||
| 274 | * @return string formatted price |
||
| 275 | */ |
||
| 276 | public function get_product_subtotal( $product, $quantity ) { |
||
| 280 | |||
| 281 | /** |
||
| 282 | * Gets the total discount amount. |
||
| 283 | * @deprecated 2.7.0 in favor to get_cart_discount_total() |
||
| 284 | */ |
||
| 285 | public function get_total_discount() { |
||
| 289 | |||
| 290 | /** |
||
| 291 | * Gets the url to the cart page. |
||
| 292 | * |
||
| 293 | * @deprecated 2.5.0 in favor to wc_get_cart_url() |
||
| 294 | * @return string url to page |
||
| 295 | */ |
||
| 296 | public function get_cart_url() { |
||
| 300 | |||
| 301 | /** |
||
| 302 | * Gets the url to the checkout page. |
||
| 303 | * |
||
| 304 | * @deprecated 2.5.0 in favor to wc_get_checkout_url() |
||
| 305 | * @return string url to page |
||
| 306 | */ |
||
| 307 | public function get_checkout_url() { |
||
| 311 | |||
| 312 | /** |
||
| 313 | * Coupons enabled function. Filterable. |
||
| 314 | * |
||
| 315 | * @deprecated 2.5.0 in favor to wc_coupons_enabled() |
||
| 316 | * @return bool |
||
| 317 | */ |
||
| 318 | public function coupons_enabled() { |
||
| 322 | |||
| 323 | /** |
||
| 324 | * Sees if we need a shipping address. |
||
| 325 | * |
||
| 326 | * @deprecated 2.5.0 in favor to wc_ship_to_billing_address_only() |
||
| 327 | * @return bool |
||
| 328 | */ |
||
| 329 | public function ship_to_billing_address_only() { |
||
| 333 | |||
| 334 | /** |
||
| 335 | * @deprecated 2.7.0 |
||
| 336 | */ |
||
| 337 | public function get_cross_sells() { |
||
| 341 | |||
| 342 | /** |
||
| 343 | * @deprecated 2.7.0 |
||
| 344 | */ |
||
| 345 | public function get_remove_url( $cart_item_key ) { |
||
| 349 | |||
| 350 | /** |
||
| 351 | * @deprecated 2.7.0 |
||
| 352 | */ |
||
| 353 | public function get_undo_url( $cart_item_key ) { |
||
| 357 | |||
| 358 | /** |
||
| 359 | * @deprecated 2.7.0 |
||
| 360 | */ |
||
| 361 | public function get_discounted_price( $values, $price, $add_totals = false ) { |
||
| 365 | |||
| 366 | /** |
||
| 367 | * @deprecated 2.7.0 |
||
| 368 | */ |
||
| 369 | public function get_item_data( $cart_item, $flat = false ) { |
||
| 373 | |||
| 374 | /** |
||
| 375 | * @deprecated 2.7.0 Unused method. |
||
| 376 | */ |
||
| 377 | public function get_total_ex_tax() { |
||
| 381 | |||
| 382 | /** |
||
| 383 | * @deprecated 2.7.0 Unused method. |
||
| 384 | */ |
||
| 385 | public function init() { |
||
| 388 | |||
| 389 | /** |
||
| 390 | * @deprecated 2.7.0 Taxes are just not calculated when not needed, so no need to remove them. |
||
| 391 | */ |
||
| 392 | public function remove_taxes() { |
||
| 395 | |||
| 396 | /** |
||
| 397 | * @deprecated 2.7.0 |
||
| 398 | */ |
||
| 399 | public function find_product_in_cart( $cart_id = false ) { |
||
| 408 | |||
| 409 | /** |
||
| 410 | * Generate a unique ID for the cart item being added. |
||
| 411 | * @deprecated 2.7.0 |
||
| 412 | * @param int $product_id - id of the product the key is being generated for |
||
| 413 | * @param int $variation_id of the product the key is being generated for |
||
| 414 | * @param array $variation data for the cart item |
||
| 415 | * @param array $cart_item_data other cart item data passed which affects this items uniqueness in the cart |
||
| 416 | * @return string cart item key |
||
| 417 | */ |
||
| 418 | public function generate_cart_id( $product_id, $variation_id = 0, $variation = array(), $cart_item_data = array() ) { |
||
| 422 | |||
| 423 | /** |
||
| 424 | * @deprecated 2.7.0 |
||
| 425 | */ |
||
| 426 | public function check_cart_item_validity() { |
||
| 430 | |||
| 431 | /** |
||
| 432 | * @deprecated 2.7.0 Unused |
||
| 433 | */ |
||
| 434 | public function get_cart_shipping_total() { |
||
| 467 | |||
| 468 | /** |
||
| 469 | * @deprecated 2.7.0 Unused |
||
| 470 | */ |
||
| 471 | public function get_tax_amount( $tax_rate_id ) { |
||
| 476 | |||
| 477 | /** |
||
| 478 | * @deprecated 2.7.0 Unused |
||
| 479 | */ |
||
| 480 | public function get_shipping_tax_amount( $tax_rate_id ) { |
||
| 485 | |||
| 486 | /** |
||
| 487 | * @deprecated 2.7.0 Unused |
||
| 488 | */ |
||
| 489 | public function get_cart_total() { |
||
| 498 | |||
| 499 | /** |
||
| 500 | * @deprecated 2.7.0 Unused |
||
| 501 | */ |
||
| 502 | public function get_cart_tax() { |
||
| 507 | } |
||
| 508 |
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the parent class: