Completed
Push — master ( 1905c5...10f16f )
by Mike
07:40
created

WC_Settings_Shipping   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 286
Duplicated Lines 6.99 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 36
c 4
b 0
f 0
lcom 1
cbo 7
dl 20
loc 286
rs 8.8

11 Methods

Rating   Name   Duplication   Size   Complexity  
A add_settings_page() 0 3 2
A __construct() 8 8 1
B get_settings() 0 46 1
B get_sections() 12 22 5
B save() 0 24 6
C output() 0 22 7
A output_zones_screen() 0 13 3
B zone_methods_screen() 0 26 2
B zones_screen() 0 25 1
C instance_settings_screen() 0 26 7
A output_shipping_class_screen() 0 19 1

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
			'classes' => __( 'Shipping Classes', 'woocommerce' )
51
		);
52
53 View Code Duplication
		if ( ! defined( 'WC_INSTALLING' ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
54
			// Load shipping methods so we can show any global options they may have
55
			$shipping_methods = WC()->shipping->load_shipping_methods();
56
57
			foreach ( $shipping_methods as $method ) {
58
				if ( ! $method->has_settings() ) {
59
					continue;
60
				}
61
				$title = empty( $method->method_title ) ? ucfirst( $method->id ) : $method->method_title;
62
				$sections[ strtolower( $method->id ) ] = esc_html( $title );
63
			}
64
		}
65
66
		return apply_filters( 'woocommerce_get_sections_' . $this->id, $sections );
67
	}
68
69
	/**
70
	 * Get settings array.
71
	 *
72
	 * @return array
73
	 */
74
	public function get_settings() {
75
		$settings = apply_filters( 'woocommerce_shipping_settings', array(
76
77
			array( 'title' => __( 'Shipping Options', 'woocommerce' ), 'type' => 'title', 'id' => 'shipping_options' ),
78
79
			array(
80
				'title'         => __( 'Calculations', 'woocommerce' ),
81
				'desc'          => __( 'Enable the shipping calculator on the cart page', 'woocommerce' ),
82
				'id'            => 'woocommerce_enable_shipping_calc',
83
				'default'       => 'yes',
84
				'type'          => 'checkbox',
85
				'checkboxgroup' => 'start',
86
				'autoload'      => false
87
			),
88
89
			array(
90
				'desc'          => __( 'Hide shipping costs until an address is entered', 'woocommerce' ),
91
				'id'            => 'woocommerce_shipping_cost_requires_address',
92
				'default'       => 'no',
93
				'type'          => 'checkbox',
94
				'checkboxgroup' => 'end',
95
				'autoload'      => false
96
			),
97
98
			array(
99
				'title'   => __( 'Shipping Destination', 'woocommerce' ),
100
				'desc'    => __( 'This controls which shipping address is used by default.', 'woocommerce' ),
101
				'id'      => 'woocommerce_ship_to_destination',
102
				'default' => 'billing',
103
				'type'    => 'radio',
104
				'options' => array(
105
					'shipping'     => __( 'Default to customer shipping address', 'woocommerce' ),
106
					'billing'      => __( 'Default to customer billing address', 'woocommerce' ),
107
					'billing_only' => __( 'Force shipping to the customer billing address', 'woocommerce' ),
108
				),
109
				'autoload'        => false,
110
				'desc_tip'        =>  true,
111
				'show_if_checked' => 'option',
112
			),
113
114
			array( 'type' => 'sectionend', 'id' => 'shipping_options' ),
115
116
		) );
117
118
		return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings );
119
	}
120
121
	/**
122
	 * Output the settings.
123
	 */
124
	public function output() {
125
		global $current_section, $hide_save_button;
126
127
		// Load shipping methods so we can show any global options they may have
128
		$shipping_methods = WC()->shipping->load_shipping_methods();
129
130
		if ( '' == $current_section ) {
131
			$this->output_zones_screen();
132
		} elseif ( 'options' === $current_section ) {
133
			$settings = $this->get_settings();
134
			WC_Admin_Settings::output_fields( $settings );
135
		} elseif ( 'classes' === $current_section ) {
136
			$hide_save_button = true;
137
			$this->output_shipping_class_screen();
138
		} else {
139
			foreach ( $shipping_methods as $method ) {
140
				if ( in_array( $current_section, array( $method->id, sanitize_title( get_class( $method ) ) ) ) && $method->has_settings() ) {
141
					$method->admin_options();
142
				}
143
			}
144
		}
145
	}
146
147
	/**
148
	 * Save settings.
149
	 */
150
	public function save() {
151
		global $current_section;
152
153
		switch ( $current_section ) {
154
			case 'options' :
155
				WC_Admin_Settings::save_fields( $this->get_settings() );
156
			break;
157
			case 'classes' :
158
			case '' :
159
			break;
160
			default :
161
				$wc_shipping = WC_Shipping::instance();
162
163
				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...
164
					if ( in_array( $current_section, array( $method->id, sanitize_title( get_class( $method ) ) ) ) ) {
165
						do_action( 'woocommerce_update_options_' . $this->id . '_' . $method->id );
166
					}
167
				}
168
			break;
169
		}
170
171
		// Increments the transient version to invalidate cache
172
		WC_Cache_Helper::get_transient_version( 'shipping', true );
173
	}
174
175
	/**
176
	 * Handles output of the shipping zones page in admin.
177
	 */
178
	protected function output_zones_screen() {
179
		global $hide_save_button;
180
181
		if ( isset( $_REQUEST['zone_id'] ) ) {
182
			$hide_save_button = true;
183
			$this->zone_methods_screen( absint( $_REQUEST['zone_id'] ) );
184
		} elseif ( isset( $_REQUEST['instance_id'] ) ) {
185
			$this->instance_settings_screen( absint( $_REQUEST['instance_id'] ) );
186
		} else {
187
			$hide_save_button = true;
188
			$this->zones_screen();
189
		}
190
	}
191
192
	/**
193
	 * Show method for a zone
194
	 * @param  int $zone_id
195
	 */
196
	protected function zone_methods_screen( $zone_id ) {
197
		$wc_shipping      = WC_Shipping      ::instance();
198
		$zone             = WC_Shipping_Zones::get_zone( $zone_id );
199
		$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...
200
201
		if ( ! $zone ) {
202
			wp_die( __( 'Zone does not exist!', 'woocommerce' ) );
203
		}
204
205
		wp_localize_script( 'wc-shipping-zone-methods', 'shippingZoneMethodsLocalizeScript', array(
206
			'methods'                 => $zone->get_shipping_methods(),
207
			'zone_id'                 => $zone->get_zone_id(),
208
			'wc_shipping_zones_nonce' => wp_create_nonce( 'wc_shipping_zones_nonce' ),
209
			'strings'                 => array(
210
				'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ),
211
				'save_changes_prompt'     => __( 'Do you wish to save your changes first? Your changed data will be discarded if you choose to cancel.', 'woocommerce' ),
212
				'save_failed'             => __( 'Your changes were not saved. Please retry.', 'woocommerce' ),
213
				'add_method_failed'       => __( 'Shipping method could not be added. Please retry.', 'woocommerce' ),
214
				'yes'                     => __( 'Yes', 'woocommerce' ),
215
				'no'                      => __( 'No', 'woocommerce' ),
216
			),
217
		) );
218
		wp_enqueue_script( 'wc-shipping-zone-methods' );
219
220
		include_once( 'views/html-admin-page-shipping-zone-methods.php' );
221
	}
222
223
	/**
224
	 * Show zones
225
	 */
226
	protected function zones_screen() {
227
		global $wpdb;
228
229
		$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...
230
		$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...
231
		$method_count      = absint( $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}woocommerce_shipping_zone_methods" ) );
1 ignored issue
show
Unused Code introduced by
$method_count 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...
232
233
		wp_localize_script( 'wc-shipping-zones', 'shippingZonesLocalizeScript', array(
234
			'zones'         => WC_Shipping_Zones::get_zones(),
235
			'default_zone'  => array(
236
				'zone_id'    => 0,
237
				'zone_name'  => '',
238
				'zone_order' => null,
239
			),
240
			'wc_shipping_zones_nonce'  => wp_create_nonce( 'wc_shipping_zones_nonce' ),
241
			'strings'       => array(
242
				'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ),
243
				'save_failed'             => __( 'Your changes were not saved. Please retry.', 'woocommerce' ),
244
				'default_zone_name'       => __( 'Zone', 'woocommerce' ),
245
			),
246
		) );
247
		wp_enqueue_script( 'wc-shipping-zones' );
248
249
		include_once( 'views/html-admin-page-shipping-zones.php' );
250
	}
251
252
	/**
253
	 * Show instance settings
254
	 * @param  int $instance_id
255
	 */
256
	protected function instance_settings_screen( $instance_id ) {
257
		$zone            = WC_Shipping_Zones::get_zone_by( 'instance_id', $instance_id );
258
		$shipping_method = WC_Shipping_Zones::get_shipping_method( $instance_id );
259
260
		if ( ! $shipping_method ) {
261
			wp_die( __( 'Invalid shipping method!', 'woocommerce' ) );
262
		}
263
		if ( ! $zone ) {
264
			wp_die( __( 'Zone does not exist!', 'woocommerce' ) );
265
		}
266
		if ( ! $shipping_method->has_settings() ) {
267
			wp_die( __( 'This shipping method does not have any settings to configure.', 'woocommerce' ) );
268
		}
269
270
		if ( ! empty( $_POST['save'] ) ) {
271
272
			if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'woocommerce-settings' ) ) {
273
				echo '<div class="updated error"><p>' . __( 'Edit failed. Please try again.', 'woocommerce' ) . '</p></div>';
274
			}
275
276
			$shipping_method->process_admin_options();
277
			$shipping_method->display_errors();
278
		}
279
280
		include_once( 'views/html-admin-page-shipping-zones-instance.php' );
281
	}
282
283
	/**
284
	 * Handles output of the shipping class settings screen.
285
	 */
286
	protected function output_shipping_class_screen() {
287
		$wc_shipping = WC_Shipping::instance();
288
		wp_localize_script( 'wc-shipping-classes', 'shippingClassesLocalizeScript', array(
289
			'classes'         => $wc_shipping->get_shipping_classes(),
290
			'default_shipping_class'  => array(
291
				'term_id'     => 0,
292
				'name'        => '',
293
				'description' => '',
294
			),
295
			'wc_shipping_classes_nonce'  => wp_create_nonce( 'wc_shipping_classes_nonce' ),
296
			'strings'       => array(
297
				'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ),
298
				'save_failed'             => __( 'Your changes were not saved. Please retry.', 'woocommerce' )
299
			),
300
		) );
301
		wp_enqueue_script( 'wc-shipping-classes' );
302
303
		include_once( 'views/html-admin-page-shipping-classes.php' );
304
	}
305
}
306
307
endif;
308
309
return new WC_Settings_Shipping();
310