Completed
Pull Request — master (#11846)
by Justin
14:20
created

WC_REST_Payment_Gateways_Controller::update_item()   C

Complexity

Conditions 7
Paths 9

Size

Total Lines 40
Code Lines 25

Duplication

Lines 8
Ratio 20 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 25
c 1
b 0
f 0
nc 9
nop 1
dl 8
loc 40
rs 6.7272
1
<?php
2
/**
3
 * REST API WC Payment gateways controller
4
 *
5
 * Handles requests to the /payment_gateways 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
 * @package WooCommerce/API
19
 * @extends WC_REST_Controller
20
 */
21
class WC_REST_Payment_Gateways_Controller extends WC_REST_Controller {
22
23
	/**
24
	 * Endpoint namespace.
25
	 *
26
	 * @var string
27
	 */
28
	protected $namespace = 'wc/v1';
29
30
	/**
31
	 * Route base.
32
	 *
33
	 * @var string
34
	 */
35
	protected $rest_base = 'payment_gateways';
36
37
	/**
38
	 * Register the route for /payment_gateways and /payment_gateways/<id>
39
	 */
40
	public function register_routes() {
41
		register_rest_route( $this->namespace, '/' . $this->rest_base, array(
42
			array(
43
				'methods'             => WP_REST_Server::READABLE,
44
				'callback'            => array( $this, 'get_items' ),
45
				'permission_callback' => array( $this, 'get_items_permissions_check' ),
46
				'args'                => $this->get_collection_params(),
47
			),
48
			'schema' => array( $this, 'get_public_item_schema' ),
49
		) );
50
		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\w-]+)', array(
51
			array(
52
				'methods'             => WP_REST_Server::READABLE,
53
				'callback'            => array( $this, 'get_item' ),
54
				'permission_callback' => array( $this, 'get_item_permissions_check' ),
55
				'args'                => array(
56
					'context' => $this->get_context_param( array( 'default' => 'view' ) ),
57
				),
58
			),
59
			array(
60
				'methods'             => WP_REST_Server::EDITABLE,
61
				'callback'            => array( $this, 'update_item' ),
62
				'permission_callback' => array( $this, 'update_items_permissions_check' ),
63
				'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
64
			),
65
			'schema' => array( $this, 'get_public_item_schema' ),
66
		) );
67
	}
68
69
	/**
70
	 * Check whether a given request has permission to view payment gateways.
71
	 *
72
	 * @param  WP_REST_Request $request Full details about the request.
73
	 * @return WP_Error|boolean
74
	 */
75
	public function get_items_permissions_check( $request ) {
76
		if ( ! wc_rest_check_manager_permissions( 'payment_gateways', 'read' ) ) {
77
			return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
78
		}
79
		return true;
80
	}
81
82
	/**
83
	 * Check if a given request has access to read a payment gateway.
84
	 *
85
	 * @param  WP_REST_Request $request Full details about the request.
86
	 * @return WP_Error|boolean
87
	 */
88
	public function get_item_permissions_check( $request ) {
89
		if ( ! wc_rest_check_manager_permissions( 'payment_gateways', 'read' ) ) {
90
			return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
91
		}
92
		return true;
93
	}
94
95
	/**
96
	 * Check whether a given request has permission to edit payment gateways.
97
	 *
98
	 * @param  WP_REST_Request $request Full details about the request.
99
	 * @return WP_Error|boolean
100
	 */
101
	public function update_items_permissions_check( $request ) {
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
102
		if ( ! wc_rest_check_manager_permissions( 'payment_gateways', 'edit' ) ) {
103
			return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you are not allowed to edit this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
104
		}
105
		return true;
106
	}
107
108
	/**
109
	 * Get payment gateways.
110
	 *
111
	 * @param WP_REST_Request $request Full details about the request.
112
	 * @return WP_Error|WP_REST_Response
113
	 */
114
	public function get_items( $request ) {
115
		$this->maybe_define_wp_admin();
116
		$payment_gateways = WC()->payment_gateways->payment_gateways();
117
		$response         = array();
118
		foreach ( $payment_gateways as $payment_gateway_id => $payment_gateway ) {
119
			$payment_gateway->id = $payment_gateway_id;
120
			$gateway             = $this->prepare_item_for_response( $payment_gateway, $request );
121
			$gateway             = $this->prepare_response_for_collection( $gateway );
122
			$response[]          = $gateway;
123
		}
124
		return rest_ensure_response( $response );
125
	}
126
127
	/**
128
	 * Get a single payment gateway.
129
	 *
130
	 * @param WP_REST_Request $request
131
	 * @return WP_REST_Response|WP_Error
132
	 */
133
	public function get_item( $request ) {
134
		$this->maybe_define_wp_admin();
135
		$gateway = $this->get_gateway( $request );
136
137 View Code Duplication
		if ( is_null( $gateway ) ) {
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...
138
			return new WP_Error( 'woocommerce_rest_payment_gateway_invalid', __( "Resource does not exist.", 'woocommerce' ), array( 'status' => 404 ) );
139
		}
140
141
		$gateway = $this->prepare_item_for_response( $gateway, $request );
142
		return rest_ensure_response( $gateway );
143
	}
144
145
	/**
146
	 * Update A Single Shipping Zone Method.
147
	 *
148
	 * @param WP_REST_Request $request
149
	 * @return WP_REST_Response|WP_Error
150
	 */
151
	public function update_item( $request ) {
152
		$this->maybe_define_wp_admin();
153
		$gateway = $this->get_gateway( $request );
154
155 View Code Duplication
		if ( is_null( $gateway ) ) {
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...
156
			return new WP_Error( 'woocommerce_rest_payment_gateway_invalid', __( "Resource does not exist.", 'woocommerce' ), array( 'status' => 404 ) );
157
		}
158
159
		// Update settings if present
160
		if ( isset( $request['settings'] ) ) {
161
			$gateway->init_form_fields();
162
			$settings = $gateway->settings;
163 View Code Duplication
			foreach ( $gateway->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...
164
				if ( isset( $request['settings'][ $key ] ) ) {
165
					$settings[ $key ] = $request['settings'][ $key ];
166
				}
167
			}
168
			$gateway->settings = $settings;
169
			update_option( $gateway->get_option_key(), apply_filters( 'woocommerce_gateway_' . $gateway->id . '_settings_values', $settings, $gateway ) );
170
		}
171
172
		// Update order
173
		if ( isset( $request['order'] ) ) {
174
			$order  = (array) get_option( 'woocommerce_gateway_order' );
175
			$order[ $gateway->id ] = $request['order'];
176
			update_option( 'woocommerce_gateway_order', $order );
177
			$gateway->order = absint( $request['order'] );
178
		}
179
180
		// Update if this method is enabled or not.
181
		if ( isset( $request['enabled'] ) ) {
182
			$settings        = $gateway->settings;
183
			$gateway->enabled = $settings['enabled'] = (bool) $request['enabled'];
184
			update_option( $gateway->get_option_key(), apply_filters( 'woocommerce_gateway_' . $gateway->id . '_settings_values', $settings, $gateway ) );
185
			$gateway->settings = $settings;
186
		}
187
188
		$gateway = $this->prepare_item_for_response( $gateway, $request );
189
		return rest_ensure_response( $gateway );
190
	}
191
192
	/**
193
	 * Get a gateway based on the current request object.
194
	 *
195
	 * @param  WC_Payment_Gateway $gateway Payment gateway object.
0 ignored issues
show
Bug introduced by
There is no parameter named $gateway. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
196
	 * @return WP_REST_Response|null
197
	 */
198
	public function get_gateway( $request ) {
199
		$gateway          = null;
200
		$payment_gateways = WC()->payment_gateways->payment_gateways();
201
		foreach ( $payment_gateways as $payment_gateway_id => $payment_gateway ) {
202
			if ( $request['id'] !== $payment_gateway_id ) {
203
				continue;
204
			}
205
			$payment_gateway->id = $payment_gateway_id;
206
			$gateway             = $payment_gateway;
207
		}
208
		return $gateway;
209
	}
210
211
	/**
212
	 * Prepare a payment gateway for response.
213
	 *
214
	 * @param  WC_Payment_Gateway $gateway    Payment gateway object.
215
	 * @param  WP_REST_Request    $request    Request object.
216
	 * @return WP_REST_Response   $response   Response data.
217
	 */
218
	public function prepare_item_for_response( $gateway, $request ) {
219
		$order  = (array) get_option( 'woocommerce_gateway_order' );
220
		$item = array(
221
			'id'                 => $gateway->id,
222
			'title'              => $gateway->title,
223
			'description'        => $gateway->description,
224
			'order'              => isset( $order[ $gateway->id ] ) ? $order[ $gateway->id ] : '',
225
			'enabled'            => ( 'yes' === $gateway->enabled ),
226
			'method_title'       => $gateway->get_method_title(),
227
			'method_description' => $gateway->get_method_description(),
228
			'settings'           => $this->get_settings( $gateway ),
229
		);
230
231
		$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
232
		$data    = $this->add_additional_fields_to_object( $item, $request );
0 ignored issues
show
Unused Code introduced by
$data 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...
233
		$data    = $this->filter_response_by_context( $item, $context );
0 ignored issues
show
Unused Code introduced by
$data 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...
234
235
		$response = rest_ensure_response( $item );
236
		$response->add_links( $this->prepare_links( $gateway, $request ) );
237
238
		/**
239
		 * Filter payment gateway objects returned from the REST API.
240
		 *
241
		 * @param WP_REST_Response   $response The response object.
242
		 * @param WC_Payment_Gateway $gateway  Payment gateway object.
243
		 * @param WP_REST_Request    $request  Request object.
244
		 */
245
		return apply_filters( 'woocommerce_rest_prepare_payment_gateway', $response, $gateway, $request );
246
	}
247
248
	/**
249
	 * Return settings associated with this payment gateway.
250
	 */
251
	public function get_settings( $gateway ) {
252
		$settings = array();
253
		$gateway->init_form_fields();
254
		foreach ( $gateway->form_fields as $id => $field ) {
255
			// Make sure we at least have a title and type
256
			if ( empty( $field['title'] ) || empty( $field['type'] ) ) {
257
				continue;
258
			}
259
			// Ignore 'title' settings/fields -- they are UI only
260
			if ( 'title' === $field['type'] ) {
261
				continue;
262
			}
263
			$data = array(
264
				'id'          => $id,
265
				'label'       => empty( $field['label'] ) ? $field['title'] : $field['label'],
266
				'description' => empty( $field['description'] ) ? '' : $field['description'],
267
				'type'        => $field['type'],
268
				'value'       => $gateway->settings[ $id ],
269
				'default'     => empty( $field['default'] ) ? '' : $field['default'],
270
				'tip'         => empty( $field['description'] ) ? '' : $field['description'],
271
				'placeholder' => empty( $field['placeholder'] ) ? '' : $field['placeholder'],
272
			);
273
			if ( ! empty( $field['options'] ) ) {
274
				$data['options'] = $field['options'];
275
			}
276
			$settings[ $id ] = $data;
277
		}
278
		return $settings;
279
	}
280
281
	/**
282
	 * Some form fields (like COD) have a setting to limit to specific shipping
283
	 * methods. Some of the code for loading these into settings is behind an
284
	 * is_admin check. To work correctly with methods that do this, we can
285
	 * define the constant here and act as wp-admin (since these settings are
286
	 * shown to managers and admins only anyway).
287
	 */
288
	protected function maybe_define_wp_admin() {
289
		if ( ! defined( 'WP_ADMIN' ) ) {
290
			define( 'WP_ADMIN', true );
291
		}
292
	}
293
294
	/**
295
	 * Prepare links for the request.
296
	 *
297
	 * @param  WC_Payment_Gateway $gateway    Payment gateway object.
298
	 * @param  WP_REST_Request    $request    Request object.
299
	 * @return array
300
	 */
301
	protected function prepare_links( $gateway, $request ) {
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
302
		$links      = array(
303
			'self' => array(
304
				'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $gateway->id ) ),
305
			),
306
			'collection' => array(
307
				'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
308
			),
309
		);
310
311
		return $links;
312
	}
313
314
    /**
315
	 * Get the payment gateway schema, conforming to JSON Schema.
316
	 *
317
	 * @return array
318
	 */
319
	public function get_item_schema() {
320
		$schema = array(
321
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
322
			'title'      => 'payment_gateway',
323
			'type'       => 'object',
324
			'properties' => array(
325
				'id' => array(
326
					'description' => __( 'Payment gateway ID.', 'woocommerce' ),
327
					'type'        => 'string',
328
					'context'     => array( 'view' ),
329
				),
330
				'title' => array(
331
					'description' => __( 'Payment gateway title on checkout.', 'woocommerce' ),
332
					'type'        => 'string',
333
					'context'     => array( 'view', 'edit' ),
334
				),
335
				'description' => array(
336
					'description' => __( 'Payment gateway description on checkout.', 'woocommerce' ),
337
					'type'        => 'string',
338
					'context'     => array( 'view', 'edit' ),
339
				),
340
				'order' => array(
341
					'description' => __( 'Payment gateway sort order.', 'woocommerce' ),
342
					'type'        => 'integer',
343
					'context'     => array( 'view', 'edit' ),
344
					'arg_options' => array(
345
						'sanitize_callback' => 'absint',
346
					),
347
				),
348
				'enabled' => array(
349
					'description' => __( 'Payment gateway enabled status.', 'woocommerce' ),
350
					'type'        => 'boolean',
351
					'context'     => array( 'view', 'edit' ),
352
				),
353
				'method_title' => array(
354
					'description' => __( 'Payment gateway method title.', 'woocommerce' ),
355
					'type'        => 'string',
356
					'context'     => array( 'view' ),
357
				),
358
				'method_description' => array(
359
					'description' => __( 'Payment gateway method description.', 'woocommerce' ),
360
					'type'        => 'string',
361
					'context'     => array( 'view' ),
362
				),
363
				'settings' => array(
364
					'description' => __( 'Payment gateway settings.', 'woocommerce' ),
365
					'type'        => 'array',
366
					'context'     => array( 'view', 'edit' ),
367
				),
368
			),
369
		);
370
371
		return $this->add_additional_fields_schema( $schema );
372
	}
373
374
	/**
375
	 * Get any query params needed.
376
	 *
377
	 * @return array
378
	 */
379
	public function get_collection_params() {
380
		return array(
381
			'context' => $this->get_context_param( array( 'default' => 'view' ) ),
382
		);
383
	}
384
385
}
386