Completed
Pull Request — master (#9826)
by Mike
22:02
created

WC_Settings_Shipping   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 255
Duplicated Lines 3.14 %

Coupling/Cohesion

Components 1
Dependencies 7
Metric Value
wmc 33
lcom 1
cbo 7
dl 8
loc 255
rs 9.4

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 8 8 1
A add_settings_page() 0 3 2
B get_sections() 0 21 5
B get_settings() 0 46 1
B output() 0 25 6
B save() 0 23 5
A output_zones_screen() 0 9 3
B zone_methods_screen() 0 24 2
A zones_screen() 0 21 1
C instance_settings_screen() 0 27 7

How to fix   Duplicated Code   

Duplicated Code

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:

1
<?php
1 ignored issue
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 20 and the first side effect is on line 12.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * WooCommerce Shipping Settings
4
 *
5
 * @author      WooThemes
6
 * @category    Admin
7
 * @package     WooCommerce/Admin
8
 * @version     2.6.0
9
 */
10
11
if ( ! defined( 'ABSPATH' ) ) {
12
	exit;
13
}
14
15
if ( ! class_exists( 'WC_Settings_Shipping' ) ) :
16
17
/**
18
 * WC_Settings_Shipping.
19
 */
20
class WC_Settings_Shipping extends WC_Settings_Page {
21
22
	/**
23
	 * Constructor.
24
	 */
25 View Code Duplication
	public function __construct() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
26
		$this->id    = 'shipping';
27
		$this->label = __( 'Shipping', 'woocommerce' );
28
		add_filter( 'woocommerce_settings_tabs_array', array( $this, 'add_settings_page' ), 20 );
29
		add_action( 'woocommerce_sections_' . $this->id, array( $this, 'output_sections' ) );
30
		add_action( 'woocommerce_settings_' . $this->id, array( $this, 'output' ) );
31
		add_action( 'woocommerce_settings_save_' . $this->id, array( $this, 'save' ) );
32
	}
33
34
	/**
35
	 * Add this page to settings.
36
	 */
37
	public function add_settings_page( $pages ) {
38
		return wc_shipping_enabled() ? parent::add_settings_page( $pages ) : $pages;
39
	}
40
41
	/**
42
	 * Get sections.
43
	 *
44
	 * @return array
45
	 */
46
	public function get_sections() {
47
		$sections = array(
48
			''        => __( 'Shipping Zones', 'woocommerce' ),
49
			'options' => __( 'Shipping Options', 'woocommerce' )
50
		);
51
52
		if ( ! defined( 'WC_INSTALLING' ) ) {
53
			// Load shipping methods so we can show any global options they may have
54
			$shipping_methods = WC()->shipping->load_shipping_methods();
55
56
			foreach ( $shipping_methods as $method ) {
57
				if ( ! $method->has_settings() ) {
58
					continue;
59
				}
60
				$title = empty( $method->method_title ) ? ucfirst( $method->id ) : $method->method_title;
61
				$sections[ strtolower( get_class( $method ) ) ] = esc_html( $title );
62
			}
63
		}
64
65
		return apply_filters( 'woocommerce_get_sections_' . $this->id, $sections );
66
	}
67
68
	/**
69
	 * Get settings array.
70
	 *
71
	 * @return array
72
	 */
73
	public function get_settings() {
74
		$settings = apply_filters( 'woocommerce_shipping_settings', array(
75
76
			array( 'title' => __( 'Shipping Options', 'woocommerce' ), 'type' => 'title', 'id' => 'shipping_options' ),
77
78
			array(
79
				'title'         => __( 'Calculations', 'woocommerce' ),
80
				'desc'          => __( 'Enable the shipping calculator on the cart page', 'woocommerce' ),
81
				'id'            => 'woocommerce_enable_shipping_calc',
82
				'default'       => 'yes',
83
				'type'          => 'checkbox',
84
				'checkboxgroup' => 'start',
85
				'autoload'      => false
86
			),
87
88
			array(
89
				'desc'          => __( 'Hide shipping costs until an address is entered', 'woocommerce' ),
90
				'id'            => 'woocommerce_shipping_cost_requires_address',
91
				'default'       => 'no',
92
				'type'          => 'checkbox',
93
				'checkboxgroup' => 'end',
94
				'autoload'      => false
95
			),
96
97
			array(
98
				'title'   => __( 'Shipping Destination', 'woocommerce' ),
99
				'desc'    => __( 'This controls which shipping address is used by default.', 'woocommerce' ),
100
				'id'      => 'woocommerce_ship_to_destination',
101
				'default' => 'billing',
102
				'type'    => 'radio',
103
				'options' => array(
104
					'shipping'     => __( 'Default to customer shipping address', 'woocommerce' ),
105
					'billing'      => __( 'Default to customer billing address', 'woocommerce' ),
106
					'billing_only' => __( 'Force shipping to the customer billing address', 'woocommerce' ),
107
				),
108
				'autoload'        => false,
109
				'desc_tip'        =>  true,
110
				'show_if_checked' => 'option',
111
			),
112
113
			array( 'type' => 'sectionend', 'id' => 'shipping_options' ),
114
115
		) );
116
117
		return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings );
118
	}
119
120
	/**
121
	 * Output the settings.
122
	 */
123
	public function output() {
124
		global $current_section, $hide_save_button;
125
126
		// Load shipping methods so we can show any global options they may have
127
		$shipping_methods = WC()->shipping->load_shipping_methods();
128
129
		switch ( $current_section ) {
130
			case 'options' :
131
				$settings = $this->get_settings();
132
				WC_Admin_Settings::output_fields( $settings );
133
			break;
134
			case '' :
135
				$hide_save_button = true;
136
				$this->output_zones_screen();
137
			break;
138
			default :
139
				foreach ( $shipping_methods as $method ) {
140
					if ( strtolower( get_class( $method ) ) == strtolower( $current_section ) && $method->has_settings() ) {
141
						$method->admin_options();
142
						break;
143
					}
144
				}
145
			break;
146
		}
147
	}
148
149
	/**
150
	 * Save settings.
151
	 */
152
	public function save() {
153
		global $current_section;
154
155
		switch ( $current_section ) {
156
			case 'options' :
157
				WC_Admin_Settings::save_fields( $this->get_settings() );
158
			break;
159
			case '' :
160
			break;
161
			default :
162
				$wc_shipping = WC_Shipping::instance();
163
164
				foreach ( $wc_shipping->get_shipping_methods() as $method_id => $method ) {
0 ignored issues
show
Bug introduced by
The expression $wc_shipping->get_shipping_methods() of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
165
					if ( $current_section === sanitize_title( get_class( $method ) ) ) {
166
						do_action( 'woocommerce_update_options_' . $this->id . '_' . $method->id );
167
					}
168
				}
169
			break;
170
		}
171
172
		// Increments the transient version to invalidate cache
173
		WC_Cache_Helper::get_transient_version( 'shipping', true );
174
	}
175
176
	/**
177
	 * Handles output of the reports page in admin.
178
	 */
179
	private function output_zones_screen() {
180
		if ( isset( $_REQUEST['zone_id'] ) ) {
181
			$this->zone_methods_screen( absint( $_REQUEST['zone_id'] ) );
182
		} elseif ( isset( $_REQUEST['instance_id'] ) ) {
183
			$this->instance_settings_screen( absint( $_REQUEST['instance_id'] ) );
184
		} else {
185
			$this->zones_screen();
186
		}
187
	}
188
189
	/**
190
	 * Show method for a zone
191
	 * @param  int $zone_id
192
	 */
193
	private function zone_methods_screen( $zone_id ) {
194
		$wc_shipping      = WC_Shipping      ::instance();
195
		$zone             = WC_Shipping_Zones::get_zone( $zone_id );
196
		$shipping_methods = $wc_shipping ->get_shipping_methods();
1 ignored issue
show
Unused Code introduced by
$shipping_methods is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
197
198
		if ( ! $zone ) {
199
			wp_die( __( 'Zone does not exist!', 'woocommerce' ) );
200
		}
201
202
		wp_localize_script( 'wc-shipping-zone-methods', 'shippingZoneMethodsLocalizeScript', array(
203
            'methods'                 => $zone->get_shipping_methods(),
204
			'zone_id'                 => $zone->get_zone_id(),
205
			'wc_shipping_zones_nonce' => wp_create_nonce( 'wc_shipping_zones_nonce' ),
206
			'strings'                 => array(
207
				'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ),
208
				'save_failed'             => __( 'Your changes were not saved. Please retry.', 'woocommerce' ),
209
				'add_method_failed'       => __( 'Shipping method could not be added. Please retry.', 'woocommerce' ),
210
				'yes'                     => __( 'Yes', 'woocommerce' ),
211
			),
212
		) );
213
		wp_enqueue_script( 'wc-shipping-zone-methods' );
214
215
		include_once( 'views/html-admin-page-shipping-zone-methods.php' );
216
	}
217
218
	/**
219
	 * Show zones
220
	 */
221
	private function zones_screen() {
222
		$allowed_countries = WC()->countries->get_allowed_countries();
1 ignored issue
show
Unused Code introduced by
$allowed_countries is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
223
        $continents        = WC()->countries->get_continents();
1 ignored issue
show
Unused Code introduced by
$continents is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
224
225
		wp_localize_script( 'wc-shipping-zones', 'shippingZonesLocalizeScript', array(
226
            'zones'         => WC_Shipping_Zones::get_zones(),
227
            'default_zone'  => array(
228
				'zone_id'    => 0,
229
				'zone_name'  => '',
230
				'zone_order' => null,
231
			),
232
			'wc_shipping_zones_nonce'  => wp_create_nonce( 'wc_shipping_zones_nonce' ),
233
			'strings'       => array(
234
				'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ),
235
				'save_failed'             => __( 'Your changes were not saved. Please retry.', 'woocommerce' )
236
			),
237
		) );
238
		wp_enqueue_script( 'wc-shipping-zones' );
239
240
		include_once( 'views/html-admin-page-shipping-zones.php' );
241
	}
242
243
	/**
244
	 * Show instance settings
245
	 * @param  int $instance_id
246
	 */
247
	private function instance_settings_screen( $instance_id ) {
248
		$zone            = WC_Shipping_Zones::get_zone_by( 'instance_id', $instance_id );
249
		$shipping_method = WC_Shipping_Zones::get_shipping_method( $instance_id );
250
251
		if ( ! $shipping_method ) {
252
			wp_die( __( 'Invalid shipping method!', 'woocommerce' ) );
253
		}
254
		if ( ! $zone ) {
255
			wp_die( __( 'Zone does not exist!', 'woocommerce' ) );
256
		}
257
		if ( ! $shipping_method->has_settings() ) {
258
			wp_die( __( 'This shipping method does not have any settings to configure.', 'woocommerce' ) );
259
		}
260
261
		if ( ! empty( $_POST['save_method'] ) ) {
262
263
			if ( empty( $_POST['woocommerce_save_method_nonce'] ) || ! wp_verify_nonce( $_POST['woocommerce_save_method_nonce'], 'woocommerce_save_method' )) {
264
				echo '<div class="updated error"><p>' . __( 'Edit failed. Please try again.', 'woocommerce' ) . '</p></div>';
265
266
			}
267
268
			$shipping_method->process_admin_options();
269
			$shipping_method->display_errors();
270
		}
271
272
		include_once( 'views/html-admin-page-shipping-zones-instance.php' );
273
	}
274
}
275
276
endif;
277
278
return new WC_Settings_Shipping();
279