Completed
Pull Request — master (#11781)
by
unknown
07:51
created

create_item()   B

Complexity

Conditions 7
Paths 25

Size

Total Lines 55
Code Lines 36

Duplication

Lines 19
Ratio 34.55 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 7
eloc 36
nc 25
nop 1
dl 19
loc 55
rs 7.8235
c 1
b 0
f 1

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
	public function register_routes() {
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, 'update_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 doesn't 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     = 0;
144
		$wc_shipping     = WC_Shipping::instance();
145
		$allowed_classes = $wc_shipping->get_shipping_method_class_names();
146
		$count           = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}woocommerce_shipping_zone_methods WHERE zone_id = %d", $zone->get_id() ) );
147 View Code Duplication
		if ( in_array( $method_id, array_keys( $allowed_classes ) ) ) {
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...
148
			$wpdb->insert(
149
				$wpdb->prefix . 'woocommerce_shipping_zone_methods',
150
				array(
151
					'method_id'    => $method_id ,
152
					'zone_id'      => $zone->get_id(),
153
					'method_order' => ( $count + 1 )
154
				),
155
				array(
156
					'%s',
157
					'%d',
158
					'%d'
159
				)
160
			);
161
			$instance_id = $wpdb->insert_id;
162
		}
163
164
		if ( $instance_id ) {
165
			do_action( 'woocommerce_shipping_zone_method_added', $instance_id, $method_id, $zone->get_id() );
166
		}
167
168
		WC_Cache_Helper::get_transient_version( 'shipping', true );
169
170
		$methods     = $zone->get_shipping_methods();
171
		$method      = false;
172
173
		foreach ( $methods as $method_obj ) {
174
			if ( $instance_id === $method_obj->instance_id ) {
175
				$method = $method_obj;
176
				break;
177
			}
178
		}
179
180 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...
181
			return new WP_Error( 'woocommerce_rest_shipping_zone_not_created', __( "Resource cannot be created.", 'woocommerce' ), array( 'status' => 500 ) );
182
		}
183
184
		$method = $this->update_fields( $instance_id, $method, $request );
185
186
		$data = $this->prepare_item_for_response( $method, $request );
187
		return rest_ensure_response( $data );
188
	}
189
190
	/**
191
	 * Delete a shipping method instance.
192
	 *
193
	 * @param WP_REST_Request $request Full details about the request
194
	 * @return WP_Error|boolean
195
	 */
196
	public function delete_item( $request ) {
197
		global $wpdb;
198
199
		$zone = $this->get_zone( $request['zone_id'] );
200
		if ( is_wp_error( $zone ) ) {
201
			return $zone;
202
		}
203
204
		$instance_id = (int) $request['instance_id'];
205
		$force       = $request['force'];
206
		$methods     = $zone->get_shipping_methods();
207
		$method      = false;
208
209
		foreach ( $methods as $method_obj ) {
210
			if ( $instance_id === $method_obj->instance_id ) {
211
				$method = $method_obj;
212
				break;
213
			}
214
		}
215
216 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...
217
			return new WP_Error( 'woocommerce_rest_shipping_zone_method_invalid', __( "Resource doesn't exist.", 'woocommerce' ), array( 'status' => 404 ) );
218
		}
219
220
		$method = $this->update_fields( $instance_id, $method, $request );
221
		$request->set_param( 'context', 'view' );
222
		$response = $this->prepare_item_for_response( $method, $request );
223
224
		if ( $force ) {
225
			$wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zone_methods', array( 'instance_id' => $instance_id ) );
226
		} else {
227
			return new WP_Error( 'rest_trash_not_supported', __( 'Shipping methods do not support trashing.' ), array( 'status' => 501 ) );
228
		}
229
230
		/**
231
		 * Fires after a product review is deleted via the REST API.
232
		 *
233
		 * @param object           $method
234
		 * @param WP_REST_Response $response        The response data.
235
		 * @param WP_REST_Request  $request         The request sent to the API.
236
		 */
237
		do_action( 'rest_delete_product_review', $method, $response, $request );
238
239
		return $response;
240
	}
241
242
	/**
243
	 * Update A Single Shipping Zone Method.
244
	 *
245
	 * @param WP_REST_Request $request
246
	 * @return WP_REST_Response|WP_Error
247
	 */
248
	public function update_item( $request ) {
249
		global $wpdb;
250
251
		$zone = $this->get_zone( $request['zone_id'] );
252
		if ( is_wp_error( $zone ) ) {
253
			return $zone;
254
		}
255
256
		$instance_id = (int) $request['instance_id'];
257
		$methods     = $zone->get_shipping_methods();
258
		$method      = false;
259
260
		foreach ( $methods as $method_obj ) {
261
			if ( $instance_id === $method_obj->instance_id ) {
262
				$method = $method_obj;
263
				break;
264
			}
265
		}
266
267 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...
268
			return new WP_Error( 'woocommerce_rest_shipping_zone_method_invalid', __( "Resource doesn't exist.", 'woocommerce' ), array( 'status' => 404 ) );
269
		}
270
271
		$method = $this->update_fields( $instance_id, $method, $request );
272
273
		$data = $this->prepare_item_for_response( $method, $request );
274
		return rest_ensure_response( $data );
275
	}
276
277
	/**
278
	 * Updates settings, order, and enabled status on create.
279
	 *
280
	 * @param $instance_id integer
281
	 * @param $method
282
	 * @param WP_REST_Request $request
283
	 * @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...
284
	 */
285
	public function update_fields( $instance_id, $method, $request ) {
286
		global $wpdb;
287
288
		// Update settings if present
289
		if ( isset( $request['settings'] ) ) {
290
			$method->init_instance_settings();
291
			$instance_settings = $method->instance_settings;
292
			foreach ( $method->get_instance_form_fields() as $key => $field ) {
293
				if ( isset( $request['settings'][ $key ] ) ) {
294
					$instance_settings[ $key ] = $request['settings'][ $key ];
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 View Code Duplication
	public function get_item_schema() {
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...
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' ),
414
				),
415
				'title' => array(
416
					'description' => __( 'Shipping method customer facing title.', 'woocommerce' ),
417
					'type'        => 'string',
418
					'context'     => array( 'view' ),
419
				),
420
				'order' => array(
421
					'description' => __( 'Shipping method sort order.', 'woocommerce' ),
422
					'type'        => 'integer',
423
					'context'     => array( 'view', 'edit' ),
424
					'required'    => false,
425
					'arg_options' => array(
426
						'sanitize_callback' => 'absint',
427
					),
428
				),
429
				'enabled' => array(
430
					'description' => __( 'Shipping method enabled status.', 'woocommerce' ),
431
					'type'        => 'boolean',
432
					'context'     => array( 'view', 'edit' ),
433
					'required'    => false,
434
				),
435
				'method_id' => array(
436
					'description' => __( 'Shipping method ID. Write on create only.', 'woocommerce' ),
437
					'type'        => 'string',
438
					'context'     => array( 'view', 'edit.' ),
439
				),
440
				'method_title' => array(
441
					'description' => __( 'Shipping method title.', 'woocommerce' ),
442
					'type'        => 'string',
443
					'context'     => array( 'view' ),
444
				),
445
				'method_description' => array(
446
					'description' => __( 'Shipping method description.', 'woocommerce' ),
447
					'type'        => 'string',
448
					'context'     => array( 'view' ),
449
				),
450
				'settings' => array(
451
					'description' => __( 'Shipping method settings.', 'woocommerce' ),
452
					'type'        => 'array',
453
					'context'     => array( 'view', 'edit' ),
454
				),
455
			),
456
		);
457
458
		return $this->add_additional_fields_schema( $schema );
459
	}
460
}
461