Completed
Pull Request — master (#9826)
by Mike
07:48
created

WC_Settings_Shipping::zones_screen()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 17

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 23
rs 9.0856
cc 1
eloc 17
nc 1
nop 0
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
		if ( ! defined( 'WC_INSTALLING' ) ) {
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( get_class( $method ) ) ] = 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 ( 'options' === $current_section ) {
131
			$settings = $this->get_settings();
132
			WC_Admin_Settings::output_fields( $settings );
133
			return;
134
		} elseif ( 'classes' === $current_section ) {
135
			$hide_save_button = true;
136
			$this->output_shipping_class_screen();
137
			return;
138
		} else {
139
			foreach ( $shipping_methods as $method ) {
140
				if ( strtolower( get_class( $method ) ) === strtolower( $current_section ) && $method->has_settings() ) {
141
					$method->admin_options();
142
					return;
143
				}
144
			}
145
		}
146
147
		// Default to zones screen
148
		$hide_save_button = true;
149
		$this->output_zones_screen();
150
	}
151
152
	/**
153
	 * Save settings.
154
	 */
155
	public function save() {
156
		global $current_section;
157
158
		switch ( $current_section ) {
159
			case 'options' :
160
				WC_Admin_Settings::save_fields( $this->get_settings() );
161
			break;
162
			case 'classes' :
163
			case '' :
164
			break;
165
			default :
166
				$wc_shipping = WC_Shipping::instance();
167
168
				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...
169
					if ( $current_section === sanitize_title( get_class( $method ) ) ) {
170
						do_action( 'woocommerce_update_options_' . $this->id . '_' . $method->id );
171
					}
172
				}
173
			break;
174
		}
175
176
		// Increments the transient version to invalidate cache
177
		WC_Cache_Helper::get_transient_version( 'shipping', true );
178
	}
179
180
	/**
181
	 * Handles output of the shipping zones page in admin.
182
	 */
183
	private function output_zones_screen() {
184
		if ( isset( $_REQUEST['zone_id'] ) ) {
185
			$this->zone_methods_screen( absint( $_REQUEST['zone_id'] ) );
186
		} elseif ( isset( $_REQUEST['instance_id'] ) ) {
187
			$this->instance_settings_screen( absint( $_REQUEST['instance_id'] ) );
188
		} else {
189
			$this->zones_screen();
190
		}
191
	}
192
193
	/**
194
	 * Show method for a zone
195
	 * @param  int $zone_id
196
	 */
197
	private function zone_methods_screen( $zone_id ) {
198
		$wc_shipping      = WC_Shipping      ::instance();
199
		$zone             = WC_Shipping_Zones::get_zone( $zone_id );
200
		$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...
201
202
		if ( ! $zone ) {
203
			wp_die( __( 'Zone does not exist!', 'woocommerce' ) );
204
		}
205
206
		wp_localize_script( 'wc-shipping-zone-methods', 'shippingZoneMethodsLocalizeScript', array(
207
			'methods'                 => $zone->get_shipping_methods(),
208
			'zone_id'                 => $zone->get_zone_id(),
209
			'wc_shipping_zones_nonce' => wp_create_nonce( 'wc_shipping_zones_nonce' ),
210
			'strings'                 => array(
211
				'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', '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
			),
216
		) );
217
		wp_enqueue_script( 'wc-shipping-zone-methods' );
218
219
		include_once( 'views/html-admin-page-shipping-zone-methods.php' );
220
	}
221
222
	/**
223
	 * Show zones
224
	 */
225
	private function zones_screen() {
226
		$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...
227
        $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...
228
229
		wp_localize_script( 'wc-shipping-zones', 'shippingZonesLocalizeScript', array(
230
            'zones'         => WC_Shipping_Zones::get_zones(),
231
            'default_zone'  => array(
232
				'zone_id'    => 0,
233
				'zone_name'  => '',
234
				'zone_order' => null,
235
			),
236
			'wc_shipping_zones_nonce'  => wp_create_nonce( 'wc_shipping_zones_nonce' ),
237
			'strings'       => array(
238
				'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ),
239
				'save_failed'             => __( 'Your changes were not saved. Please retry.', 'woocommerce' ),
240
				'no_methods'              => '<a href="#" class="add_shipping_method button">' . __( 'Add Shipping Method', 'woocommerce' ) . '</a>',
241
				'add_another_method'      => '<a href="#" class="add_shipping_method button">' . __( 'Add Shipping Method', 'woocommerce' ) . '</a>'
242
			),
243
		) );
244
		wp_enqueue_script( 'wc-shipping-zones' );
245
246
		include_once( 'views/html-admin-page-shipping-zones.php' );
247
	}
248
249
	/**
250
	 * Show instance settings
251
	 * @param  int $instance_id
252
	 */
253
	private function instance_settings_screen( $instance_id ) {
254
		$zone            = WC_Shipping_Zones::get_zone_by( 'instance_id', $instance_id );
255
		$shipping_method = WC_Shipping_Zones::get_shipping_method( $instance_id );
256
257
		if ( ! $shipping_method ) {
258
			wp_die( __( 'Invalid shipping method!', 'woocommerce' ) );
259
		}
260
		if ( ! $zone ) {
261
			wp_die( __( 'Zone does not exist!', 'woocommerce' ) );
262
		}
263
		if ( ! $shipping_method->has_settings() ) {
264
			wp_die( __( 'This shipping method does not have any settings to configure.', 'woocommerce' ) );
265
		}
266
267
		if ( ! empty( $_POST['save_method'] ) ) {
268
269
			if ( empty( $_POST['woocommerce_save_method_nonce'] ) || ! wp_verify_nonce( $_POST['woocommerce_save_method_nonce'], 'woocommerce_save_method' )) {
270
				echo '<div class="updated error"><p>' . __( 'Edit failed. Please try again.', 'woocommerce' ) . '</p></div>';
271
			}
272
273
			$shipping_method->process_admin_options();
274
			$shipping_method->display_errors();
275
		}
276
277
		include_once( 'views/html-admin-page-shipping-zones-instance.php' );
278
	}
279
280
	/**
281
	 * Handles output of the shipping class settings screen.
282
	 */
283
	private function output_shipping_class_screen() {
284
		$wc_shipping = WC_Shipping::instance();
285
		wp_localize_script( 'wc-shipping-classes', 'shippingClassesLocalizeScript', array(
286
            'classes'         => $wc_shipping->get_shipping_classes(),
287
            'default_shipping_class'  => array(
288
				'term_id'     => 0,
289
				'name'        => '',
290
				'description' => '',
291
			),
292
			'wc_shipping_classes_nonce'  => wp_create_nonce( 'wc_shipping_classes_nonce' ),
293
			'strings'       => array(
294
				'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ),
295
				'save_failed'             => __( 'Your changes were not saved. Please retry.', 'woocommerce' )
296
			),
297
		) );
298
		wp_enqueue_script( 'wc-shipping-classes' );
299
300
		include_once( 'views/html-admin-page-shipping-classes.php' );
301
	}
302
}
303
304
endif;
305
306
return new WC_Settings_Shipping();
307