Completed
Push — master ( 9a3784...c8ddca )
by Justin
22:39
created

delete_item()   C

Complexity

Conditions 7
Paths 13

Size

Total Lines 51
Code Lines 26

Duplication

Lines 8
Ratio 15.69 %

Importance

Changes 3
Bugs 1 Features 3
Metric Value
cc 7
eloc 26
nc 13
nop 1
dl 8
loc 51
rs 6.9743
c 3
b 1
f 3

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * REST API Shipping Zone Methods controller
4
 *
5
 * Handles requests to the /shipping/zones/<id>/methods endpoint.
6
 *
7
 * @author   WooThemes
8
 * @category API
9
 * @package  WooCommerce/API
10
 * @since    2.7.0
11
 */
12
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * REST API Shipping Zone Methods class.
19
 *
20
 * @package WooCommerce/API
21
 * @extends WC_REST_Shipping_Zones_Controller_Base
22
 */
23
class WC_REST_Shipping_Zone_Methods_Controller extends WC_REST_Shipping_Zones_Controller_Base {
24
25
	/**
26
	 * Register the routes for Shipping Zone Methods.
27
	 */
28 View Code Duplication
	public function register_routes() {
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...
29
		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<zone_id>[\d-]+)/methods', array(
30
			array(
31
				'methods'             => WP_REST_Server::READABLE,
32
				'callback'            => array( $this, 'get_items' ),
33
				'permission_callback' => array( $this, 'get_items_permissions_check' ),
34
			),
35
			array(
36
				'methods'             => WP_REST_Server::CREATABLE,
37
				'callback'            => array( $this, 'create_item' ),
38
				'permission_callback' => array( $this, 'create_item_permissions_check' ),
39
				'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),
40
			),
41
			'schema' => array( $this, 'get_public_item_schema' ),
42
		) );
43
44
		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<zone_id>[\d-]+)/methods/(?P<instance_id>[\d-]+)', array(
45
			array(
46
				'methods'             => WP_REST_Server::READABLE,
47
				'callback'            => array( $this, 'get_item' ),
48
				'permission_callback' => array( $this, 'get_items_permissions_check' ),
49
			),
50
			array(
51
				'methods'             => WP_REST_Server::EDITABLE,
52
				'callback'            => array( $this, 'update_item' ),
53
				'permission_callback' => array( $this, 'update_items_permissions_check' ),
54
				'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
55
			),
56
			array(
57
				'methods'             => WP_REST_Server::DELETABLE,
58
				'callback'            => array( $this, 'delete_item' ),
59
				'permission_callback' => array( $this, 'delete_items_permissions_check' ),
60
				'args'                => array(
61
					'force' => array(
62
						'default'     => false,
63
						'description' => __( 'Whether to bypass trash and force deletion.', 'woocommerce' ),
64
					),
65
				),
66
			),
67
			'schema' => array( $this, 'get_public_item_schema' ),
68
		) );
69
	}
70
71
	/**
72
	 * Get a single Shipping Zone Method.
73
	 *
74
	 * @param WP_REST_Request $request
75
	 * @return WP_REST_Response|WP_Error
76
	 */
77
	public function get_item( $request ) {
78
		$zone = $this->get_zone( $request['zone_id'] );
79
80
		if ( is_wp_error( $zone ) ) {
81
			return $zone;
82
		}
83
84
		$instance_id = (int) $request['instance_id'];
85
		$methods     = $zone->get_shipping_methods();
86
		$method      = false;
87
88
		foreach ( $methods as $method_obj ) {
89
			if ( $instance_id === $method_obj->instance_id ) {
90
				$method = $method_obj;
91
				break;
92
			}
93
		}
94
95 View Code Duplication
		if ( false === $method ) {
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...
96
			return new WP_Error( 'woocommerce_rest_shipping_zone_method_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
97
		}
98
99
		$data = $this->prepare_item_for_response( $method, $request );
100
101
		return rest_ensure_response( $data );
102
	}
103
104
	/**
105
	 * Get all Shipping Zone Methods.
106
	 *
107
	 * @param WP_REST_Request $request
108
	 * @return WP_REST_Response|WP_Error
109
	 */
110 View Code Duplication
	public function get_items( $request ) {
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...
111
		$zone = $this->get_zone( $request['zone_id'] );
112
113
		if ( is_wp_error( $zone ) ) {
114
			return $zone;
115
		}
116
117
		$methods = $zone->get_shipping_methods();
118
		$data    = array();
119
120
		foreach ( $methods as $method_obj ) {
121
			$method = $this->prepare_item_for_response( $method_obj, $request );
122
			$data[] = $method;
123
		}
124
125
		return rest_ensure_response( $data );
126
	}
127
128
	/**
129
	 * Create a new shipping zone method instance.
130
	 *
131
	 * @param WP_REST_Request $request Full details about the request.
132
	 * @return WP_REST_Request|WP_Error
133
	 */
134
	public function create_item( $request ) {
135
		global $wpdb;
136
137
		$method_id = $request['method_id'];
138
		$zone      = $this->get_zone( $request['zone_id'] );
139
		if ( is_wp_error( $zone ) ) {
140
			return $zone;
141
		}
142
143
		$instance_id = $zone->add_shipping_method( $method_id );
144
		$methods     = $zone->get_shipping_methods();
145
		$method      = false;
146
		foreach ( $methods as $method_obj ) {
147
			if ( $instance_id === $method_obj->instance_id ) {
148
				$method = $method_obj;
149
				break;
150
			}
151
		}
152
153 View Code Duplication
		if ( false === $method ) {
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...
154
			return new WP_Error( 'woocommerce_rest_shipping_zone_not_created', __( 'Resource cannot be created.', 'woocommerce' ), array( 'status' => 500 ) );
155
		}
156
157
		$method = $this->update_fields( $instance_id, $method, $request );
158
		if ( is_wp_error( $method ) ) {
159
			return $method;
160
		}
161
162
		$data = $this->prepare_item_for_response( $method, $request );
163
		return rest_ensure_response( $data );
164
	}
165
166
	/**
167
	 * Delete a shipping method instance.
168
	 *
169
	 * @param WP_REST_Request $request Full details about the request
170
	 * @return WP_Error|boolean
171
	 */
172
	public function delete_item( $request ) {
173
		global $wpdb;
174
175
		$zone = $this->get_zone( $request['zone_id'] );
176
		if ( is_wp_error( $zone ) ) {
177
			return $zone;
178
		}
179
180
		$instance_id = (int) $request['instance_id'];
181
		$force       = $request['force'];
182
183
		$methods     = $zone->get_shipping_methods();
184
		$method      = false;
185
186
		foreach ( $methods as $method_obj ) {
187
			if ( $instance_id === $method_obj->instance_id ) {
188
				$method = $method_obj;
189
				break;
190
			}
191
		}
192
193 View Code Duplication
		if ( false === $method ) {
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...
194
			return new WP_Error( 'woocommerce_rest_shipping_zone_method_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
195
		}
196
197
		$method = $this->update_fields( $instance_id, $method, $request );
198
		if ( is_wp_error( $method ) ) {
199
			return $method;
200
		}
201
202
		$request->set_param( 'context', 'view' );
203
		$response = $this->prepare_item_for_response( $method, $request );
204
205
		// Actually delete
206 View Code Duplication
		if ( $force ) {
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...
207
			$zone->delete_shipping_method( $instance_id );
208
		} else {
209
			return new WP_Error( 'rest_trash_not_supported', __( 'Shipping methods do not support trashing.' ), array( 'status' => 501 ) );
210
		}
211
212
		/**
213
		 * Fires after a product review is deleted via the REST API.
214
		 *
215
		 * @param object           $method
216
		 * @param WP_REST_Response $response        The response data.
217
		 * @param WP_REST_Request  $request         The request sent to the API.
218
		 */
219
		do_action( 'rest_delete_product_review', $method, $response, $request );
220
221
		return $response;
222
	}
223
224
	/**
225
	 * Update A Single Shipping Zone Method.
226
	 *
227
	 * @param WP_REST_Request $request
228
	 * @return WP_REST_Response|WP_Error
229
	 */
230
	public function update_item( $request ) {
231
		global $wpdb;
232
233
		$zone = $this->get_zone( $request['zone_id'] );
234
		if ( is_wp_error( $zone ) ) {
235
			return $zone;
236
		}
237
238
		$instance_id = (int) $request['instance_id'];
239
		$methods     = $zone->get_shipping_methods();
240
		$method      = false;
241
242
		foreach ( $methods as $method_obj ) {
243
			if ( $instance_id === $method_obj->instance_id ) {
244
				$method = $method_obj;
245
				break;
246
			}
247
		}
248
249 View Code Duplication
		if ( false === $method ) {
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...
250
			return new WP_Error( 'woocommerce_rest_shipping_zone_method_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
251
		}
252
253
		$method = $this->update_fields( $instance_id, $method, $request );
254
		if ( is_wp_error( $method ) ) {
255
			return $method;
256
		}
257
258
		$data = $this->prepare_item_for_response( $method, $request );
259
		return rest_ensure_response( $data );
260
	}
261
262
	/**
263
	 * Updates settings, order, and enabled status on create.
264
	 *
265
	 * @param $instance_id integer
266
	 * @param $method
267
	 * @param WP_REST_Request $request
268
	 * @return $method
0 ignored issues
show
Documentation introduced by
The doc-type $method could not be parsed: Unknown type name "$method" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
269
	 */
270
	public function update_fields( $instance_id, $method, $request ) {
271
		global $wpdb;
272
273
		// Update settings if present
274
		if ( isset( $request['settings'] ) ) {
275
			$method->init_instance_settings();
276
			$instance_settings = $method->instance_settings;
277
			$errors_found      = false;
278 View Code Duplication
			foreach ( $method->get_instance_form_fields() as $key => $field ) {
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...
279
				if ( isset( $request['settings'][ $key ] ) ) {
280
					if ( is_callable( array( $this, 'validate_setting_' . $field['type'] . '_field' ) ) ) {
281
						$value = $this->{'validate_setting_' . $field['type'] . '_field'}( $request['settings'][ $key ], $field );
282
					} else {
283
						$value = $this->validate_setting_text_field( $request['settings'][ $key ], $field );
284
					}
285
					if ( is_wp_error( $value ) ) {
286
						$errors_found = true;
287
						break;
288
					}
289
					$instance_settings[ $key ] = $value;
290
				}
291
			}
292
293
			if ( $errors_found ) {
294
				return new WP_Error( 'rest_setting_value_invalid', __( 'An invalid setting value was passed.', 'woocommerce' ), array( 'status' => 400 ) );
295
			}
296
297
			update_option( $method->get_instance_option_key(), apply_filters( 'woocommerce_shipping_' . $method->id . '_instance_settings_values', $instance_settings, $method ) );
298
		}
299
300
		// Update order
301
		if ( isset( $request['order'] ) ) {
302
			$wpdb->update( "{$wpdb->prefix}woocommerce_shipping_zone_methods", array( 'method_order' => absint( $request['order'] ) ), array( 'instance_id' => absint( $instance_id ) ) );
303
			$method->method_order = absint( $request['order'] );
304
		}
305
306
		// Update if this method is enabled or not.
307
		if ( isset( $request['enabled'] ) ) {
308
			if ( $wpdb->update( "{$wpdb->prefix}woocommerce_shipping_zone_methods", array( 'is_enabled' => $request['enabled'] ), array( 'instance_id' => absint( $instance_id ) ) ) ) {
309
				do_action( 'woocommerce_shipping_zone_method_status_toggled', $instance_id, $method->id, $request['zone_id'], $request['enabled'] );
310
				$method->enabled = ( true === $request['enabled'] ? 'yes' : 'no' );
311
			}
312
		}
313
314
		return $method;
315
	}
316
317
	/**
318
	 * Prepare the Shipping Zone Method for the REST response.
319
	 *
320
	 * @param array $item Shipping Zone Method.
321
	 * @param WP_REST_Request $request Request object.
322
	 * @return WP_REST_Response $response
323
	 */
324
	public function prepare_item_for_response( $item, $request ) {
325
		$method = array(
326
			'instance_id'        => $item->instance_id,
327
			'title'              => $item->instance_settings['title'],
328
			'order'              => $item->method_order,
329
			'enabled'            => ( 'yes' === $item->enabled ),
330
			'method_id'          => $item->id,
331
			'method_title'       => $item->method_title,
332
			'method_description' => $item->method_description,
333
			'settings'           => $this->get_settings( $item ),
334
		);
335
336
		$context = empty( $request['context'] ) ? 'view' : $request['context'];
337
		$data    = $this->add_additional_fields_to_object( $method, $request );
338
		$data    = $this->filter_response_by_context( $data, $context );
339
340
		// Wrap the data in a response object.
341
		$response = rest_ensure_response( $data );
342
343
		$response->add_links( $this->prepare_links( $request['zone_id'], $item->instance_id ) );
344
345
		$response = $this->prepare_response_for_collection( $response );
346
347
		return $response;
348
	}
349
350
	/**
351
	 * Return settings associated with this shipping zone method instance.
352
	 */
353
	public function get_settings( $item ) {
354
		$item->init_instance_settings();
355
		$settings = array();
356
		foreach ( $item->get_instance_form_fields() as $id => $field ) {
357
			$data = array(
358
				'id'          => $id,
359
				'label'       => $field['title'],
360
				'description' => empty( $field['description'] ) ? '' : $field['description'],
361
				'type'        => $field['type'],
362
				'value'       => $item->instance_settings[ $id ],
363
				'default'     => empty( $field['default'] ) ? '' : $field['default'],
364
				'tip'         => empty( $field['description'] ) ? '' : $field['description'],
365
				'placeholder' => empty( $field['placeholder'] ) ? '' : $field['placeholder'],
366
			);
367
			if ( ! empty( $field['options'] ) ) {
368
				$data['options'] = $field['options'];
369
			}
370
			$settings[ $id ] = $data;
371
		}
372
		return $settings;
373
	}
374
375
	/**
376
	 * Prepare links for the request.
377
	 *
378
	 * @param int $zone_id Given Shipping Zone ID.
379
	 * @param int $instance_id Given Shipping Zone Method Instance ID.
380
	 * @return array Links for the given Shipping Zone Method.
381
	 */
382
	protected function prepare_links( $zone_id, $instance_id ) {
383
		$base  = '/' . $this->namespace . '/' . $this->rest_base . '/' . $zone_id;
384
		$links = array(
385
			'self' => array(
386
				'href' => rest_url( $base . '/methods/' . $instance_id ),
387
			),
388
			'collection' => array(
389
				'href' => rest_url( $base . '/methods' ),
390
			),
391
			'describes'  => array(
392
				'href' => rest_url( $base ),
393
			),
394
		);
395
396
		return $links;
397
	}
398
399
	/**
400
	 * Get the Shipping Zone Methods schema, conforming to JSON Schema
401
	 *
402
	 * @return array
403
	 */
404
	public function get_item_schema() {
405
		$schema = array(
406
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
407
			'title'      => 'shipping_zone_method',
408
			'type'       => 'object',
409
			'properties' => array(
410
				'instance_id' => array(
411
					'description' => __( 'Shipping method instance ID.', 'woocommerce' ),
412
					'type'        => 'integer',
413
					'context'     => array( 'view', 'edit' ),
414
					'readonly'    => true,
415
				),
416
				'title' => array(
417
					'description' => __( 'Shipping method customer facing title.', 'woocommerce' ),
418
					'type'        => 'string',
419
					'context'     => array( 'view', 'edit' ),
420
					'readonly'    => true,
421
				),
422
				'order' => array(
423
					'description' => __( 'Shipping method sort order.', 'woocommerce' ),
424
					'type'        => 'integer',
425
					'context'     => array( 'view', 'edit' ),
426
					'required'    => false,
427
					'arg_options' => array(
428
						'sanitize_callback' => 'absint',
429
					),
430
				),
431
				'enabled' => array(
432
					'description' => __( 'Shipping method enabled status.', 'woocommerce' ),
433
					'type'        => 'boolean',
434
					'context'     => array( 'view', 'edit' ),
435
					'required'    => false,
436
				),
437
				'method_id' => array(
438
					'description' => __( 'Shipping method ID. Write on create only.', 'woocommerce' ),
439
					'type'        => 'string',
440
					'context'     => array( 'view', 'edit' ),
441
				),
442
				'method_title' => array(
443
					'description' => __( 'Shipping method title.', 'woocommerce' ),
444
					'type'        => 'string',
445
					'context'     => array( 'view', 'edit' ),
446
					'readonly'    => true,
447
				),
448
				'method_description' => array(
449
					'description' => __( 'Shipping method description.', 'woocommerce' ),
450
					'type'        => 'string',
451
					'context'     => array( 'view', 'edit' ),
452
					'readonly'    => true,
453
				),
454
				'settings' => array(
455
					'description' => __( 'Shipping method settings.', 'woocommerce' ),
456
					'type'        => 'array',
457
					'context'     => array( 'view', 'edit' ),
458
				),
459
			),
460
		);
461
462
		return $this->add_additional_fields_schema( $schema );
463
	}
464
}
465