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_Shortcode_My_Account 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_Shortcode_My_Account, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
12 | class WC_Shortcode_My_Account { |
||
13 | |||
14 | /** |
||
15 | * Get the shortcode content. |
||
16 | * |
||
17 | * @param array $atts |
||
18 | * @return string |
||
19 | */ |
||
20 | public static function get( $atts ) { |
||
23 | |||
24 | /** |
||
25 | * Output the shortcode. |
||
26 | * |
||
27 | * @param array $atts |
||
28 | */ |
||
29 | public static function output( $atts ) { |
||
30 | global $wp; |
||
31 | |||
32 | // Check cart class is loaded or abort |
||
33 | if ( is_null( WC()->cart ) ) { |
||
34 | return; |
||
35 | } |
||
36 | |||
37 | if ( ! is_user_logged_in() ) { |
||
38 | $message = apply_filters( 'woocommerce_my_account_message', '' ); |
||
39 | |||
40 | if ( ! empty( $message ) ) { |
||
41 | wc_add_notice( $message ); |
||
42 | } |
||
43 | |||
44 | if ( isset( $wp->query_vars['lost-password'] ) ) { |
||
45 | self::lost_password(); |
||
46 | } else { |
||
47 | wc_get_template( 'myaccount/form-login.php' ); |
||
48 | } |
||
49 | } else { |
||
50 | // Start output buffer since the html may need discarding for BW compatibility |
||
51 | ob_start(); |
||
52 | |||
53 | // Collect notices before output |
||
54 | $notices = wc_get_notices(); |
||
55 | |||
56 | // Output the new account page |
||
57 | self::my_account( $atts ); |
||
58 | |||
59 | /** |
||
60 | * Deprecated my-account.php template handling. This code should be |
||
61 | * removed in a future release. |
||
62 | * |
||
63 | * If woocommerce_account_content did not run, this is an old template |
||
64 | * so we need to render the endpoint content again. |
||
65 | */ |
||
66 | if ( ! did_action( 'woocommerce_account_content' ) ) { |
||
67 | foreach ( $wp->query_vars as $key => $value ) { |
||
68 | if ( 'pagename' === $key ) { |
||
69 | continue; |
||
70 | } |
||
71 | if ( has_action( 'woocommerce_account_' . $key . '_endpoint' ) ) { |
||
72 | ob_clean(); // Clear previous buffer |
||
73 | wc_set_notices( $notices ); |
||
74 | wc_print_notices(); |
||
75 | do_action( 'woocommerce_account_' . $key . '_endpoint', $value ); |
||
76 | break; |
||
77 | } |
||
78 | } |
||
79 | |||
80 | _deprecated_function( 'Your theme version of my-account.php template', '2.6', 'the latest version, which supports multiple account pages and navigation, from WC 2.6.0' ); |
||
81 | } |
||
82 | |||
83 | // Send output buffer |
||
84 | ob_end_flush(); |
||
85 | } |
||
86 | } |
||
87 | |||
88 | /** |
||
89 | * My account page. |
||
90 | * |
||
91 | * @param array $atts |
||
92 | */ |
||
93 | private static function my_account( $atts ) { |
||
94 | extract( shortcode_atts( array( |
||
95 | 'order_count' => 15 // @deprecated 2.6.0. Keep for backward compatibility. |
||
96 | ), $atts ) ); |
||
97 | |||
98 | wc_get_template( 'myaccount/my-account.php', array( |
||
99 | 'current_user' => get_user_by( 'id', get_current_user_id() ), |
||
100 | 'order_count' => 'all' == $order_count ? -1 : $order_count, |
||
101 | ) ); |
||
102 | } |
||
103 | |||
104 | /** |
||
105 | * View order page. |
||
106 | * |
||
107 | * @param int $order_id |
||
108 | */ |
||
109 | public static function view_order( $order_id ) { |
||
110 | $order = wc_get_order( $order_id ); |
||
111 | |||
112 | View Code Duplication | if ( ! current_user_can( 'view_order', $order_id ) ) { |
|
|
|||
113 | echo '<div class="woocommerce-error">' . __( 'Invalid order.', 'woocommerce' ) . ' <a href="' . wc_get_page_permalink( 'myaccount' ).'" class="wc-forward">'. __( 'My Account', 'woocommerce' ) .'</a>' . '</div>'; |
||
114 | return; |
||
115 | } |
||
116 | |||
117 | // Backwards compatibility |
||
118 | $status = new stdClass(); |
||
119 | $status->name = wc_get_order_status_name( $order->get_status() ); |
||
120 | |||
121 | wc_get_template( 'myaccount/view-order.php', array( |
||
122 | 'status' => $status, // @deprecated 2.2 |
||
123 | 'order' => wc_get_order( $order_id ), |
||
124 | 'order_id' => $order_id |
||
125 | ) ); |
||
126 | } |
||
127 | |||
128 | /** |
||
129 | * Edit account details page. |
||
130 | */ |
||
131 | public static function edit_account() { |
||
134 | |||
135 | /** |
||
136 | * Edit address page. |
||
137 | * |
||
138 | * @param string $load_address |
||
139 | */ |
||
140 | public static function edit_address( $load_address = 'billing' ) { |
||
180 | |||
181 | /** |
||
182 | * Lost password page handling. |
||
183 | */ |
||
184 | public static function lost_password() { |
||
222 | |||
223 | /** |
||
224 | * Handles sending password retrieval email to customer. |
||
225 | * |
||
226 | * Based on retrieve_password() in core wp-login.php. |
||
227 | * |
||
228 | * @uses $wpdb WordPress Database object |
||
229 | * @return bool True: when finish. False: on error |
||
230 | */ |
||
231 | public static function retrieve_password() { |
||
301 | |||
302 | /** |
||
303 | * Retrieves a user row based on password reset key and login. |
||
304 | * |
||
305 | * @uses $wpdb WordPress Database object |
||
306 | * |
||
307 | * @param string $key Hash to validate sending user's password |
||
308 | * @param string $login The user login |
||
309 | * @return WP_USER|bool User's database row on success, false for invalid keys |
||
310 | */ |
||
311 | public static function check_password_reset_key( $key, $login ) { |
||
344 | |||
345 | /** |
||
346 | * Handles resetting the user's password. |
||
347 | * |
||
348 | * @param object $user The user |
||
349 | * @param string $new_pass New password for the user in plaintext |
||
350 | */ |
||
351 | public static function reset_password( $user, $new_pass ) { |
||
359 | |||
360 | /** |
||
361 | * Set or unset the cookie. |
||
362 | */ |
||
363 | public static function set_reset_password_cookie( $value = '' ) { |
||
373 | |||
374 | /** |
||
375 | * Show the add payment method page. |
||
376 | */ |
||
377 | public static function add_payment_method() { |
||
397 | |||
398 | } |
||
399 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.