Passed
Push — master ( 6176aa...f7c939 )
by Mike
03:08
created

PaymentGateways   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 420
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 230
dl 0
loc 420
rs 9.36
c 0
b 0
f 0
wmc 38

10 Methods

Rating   Name   Duplication   Size   Complexity  
A prepare_item_for_response() 0 29 3
A get_collection_params() 0 3 1
C update_item() 0 66 12
A prepare_links() 0 11 1
A get_gateway() 0 11 3
A get_item() 0 9 2
A register_routes() 0 42 1
A get_items() 0 10 2
C get_settings() 0 30 12
B get_item_schema() 0 115 1
1
<?php
2
/**
3
 * REST API WC Payment gateways controller
4
 *
5
 * Handles requests to the /payment_gateways endpoint.
6
 *
7
 * @package WooCommerce/RestApi
8
 */
9
10
namespace WooCommerce\RestApi\Controllers\Version4;
11
12
defined( 'ABSPATH' ) || exit;
13
14
use \WooCommerce\RestApi\Controllers\Version4\Utilities\SettingsTrait;
15
16
/**
17
 * Payment gateways controller class.
18
 */
19
class PaymentGateways extends AbstractController {
20
	use SettingsTrait;
21
22
	/**
23
	 * Route base.
24
	 *
25
	 * @var string
26
	 */
27
	protected $rest_base = 'payment_gateways';
28
29
	/**
30
	 * Permission to check.
31
	 *
32
	 * @var string
33
	 */
34
	protected $resource_type = 'payment_gateways';
35
36
	/**
37
	 * Register the route for /payment_gateways and /payment_gateways/<id>
38
	 */
39
	public function register_routes() {
40
		register_rest_route(
41
			$this->namespace,
42
			'/' . $this->rest_base,
43
			array(
44
				array(
45
					'methods'             => \WP_REST_Server::READABLE,
46
					'callback'            => array( $this, 'get_items' ),
47
					'permission_callback' => array( $this, 'get_items_permissions_check' ),
48
					'args'                => $this->get_collection_params(),
49
				),
50
				'schema' => array( $this, 'get_public_item_schema' ),
51
			),
52
			true
53
		);
54
		register_rest_route(
55
			$this->namespace,
56
			'/' . $this->rest_base . '/(?P<id>[\w-]+)',
57
			array(
58
				'args'   => array(
59
					'id' => array(
60
						'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
61
						'type'        => 'string',
62
					),
63
				),
64
				array(
65
					'methods'             => \WP_REST_Server::READABLE,
66
					'callback'            => array( $this, 'get_item' ),
67
					'permission_callback' => array( $this, 'get_item_permissions_check' ),
68
					'args'                => array(
69
						'context' => $this->get_context_param( array( 'default' => 'view' ) ),
70
					),
71
				),
72
				array(
73
					'methods'             => \WP_REST_Server::EDITABLE,
74
					'callback'            => array( $this, 'update_item' ),
75
					'permission_callback' => array( $this, 'update_item_permissions_check' ),
76
					'args'                => $this->get_endpoint_args_for_item_schema( \WP_REST_Server::EDITABLE ),
77
				),
78
				'schema' => array( $this, 'get_public_item_schema' ),
79
			),
80
			true
81
		);
82
	}
83
84
	/**
85
	 * Get payment gateways.
86
	 *
87
	 * @param \WP_REST_Request $request Full details about the request.
88
	 * @return \WP_Error|\WP_REST_Response
89
	 */
90
	public function get_items( $request ) {
91
		$payment_gateways = WC()->payment_gateways->payment_gateways();
0 ignored issues
show
Bug introduced by
The method payment_gateways() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

91
		/** @scrutinizer ignore-call */ 
92
  $payment_gateways = WC()->payment_gateways->payment_gateways();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
92
		$response         = array();
93
		foreach ( $payment_gateways as $payment_gateway_id => $payment_gateway ) {
94
			$payment_gateway->id = $payment_gateway_id;
95
			$gateway             = $this->prepare_item_for_response( $payment_gateway, $request );
96
			$gateway             = $this->prepare_response_for_collection( $gateway );
97
			$response[]          = $gateway;
98
		}
99
		return rest_ensure_response( $response );
100
	}
101
102
	/**
103
	 * Get a single payment gateway.
104
	 *
105
	 * @param \WP_REST_Request $request Request data.
106
	 * @return \WP_REST_Response|\WP_Error
107
	 */
108
	public function get_item( $request ) {
109
		$gateway = $this->get_gateway( $request );
110
111
		if ( is_null( $gateway ) ) {
112
			return new \WP_Error( 'woocommerce_rest_payment_gateway_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
113
		}
114
115
		$gateway = $this->prepare_item_for_response( $gateway, $request );
116
		return rest_ensure_response( $gateway );
117
	}
118
119
	/**
120
	 * Update A Single Payment Method.
121
	 *
122
	 * @param \WP_REST_Request $request Request data.
123
	 * @return \WP_REST_Response|\WP_Error
124
	 */
125
	public function update_item( $request ) {
126
		$gateway = $this->get_gateway( $request );
127
128
		if ( is_null( $gateway ) ) {
129
			return new \WP_Error( 'woocommerce_rest_payment_gateway_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
130
		}
131
132
		// Get settings.
133
		$gateway->init_form_fields();
0 ignored issues
show
Bug introduced by
The method init_form_fields() does not exist on WP_REST_Response. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

133
		$gateway->/** @scrutinizer ignore-call */ 
134
            init_form_fields();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
134
		$settings = $gateway->settings;
0 ignored issues
show
Bug introduced by
The property settings does not seem to exist on WP_REST_Response.
Loading history...
135
136
		// Update settings.
137
		if ( isset( $request['settings'] ) ) {
138
			$errors_found = false;
139
			foreach ( $gateway->form_fields as $key => $field ) {
0 ignored issues
show
Bug introduced by
The property form_fields does not seem to exist on WP_REST_Response.
Loading history...
140
				if ( isset( $request['settings'][ $key ] ) ) {
141
					if ( is_callable( array( $this, 'validate_setting_' . $field['type'] . '_field' ) ) ) {
142
						$value = $this->{'validate_setting_' . $field['type'] . '_field'}( $request['settings'][ $key ], $field );
143
					} else {
144
						$value = $this->validate_setting_text_field( $request['settings'][ $key ], $field );
145
					}
146
					if ( is_wp_error( $value ) ) {
147
						$errors_found = true;
148
						break;
149
					}
150
					$settings[ $key ] = $value;
151
				}
152
			}
153
154
			if ( $errors_found ) {
155
				return new \WP_Error( 'rest_setting_value_invalid', __( 'An invalid setting value was passed.', 'woocommerce' ), array( 'status' => 400 ) );
156
			}
157
		}
158
159
		// Update if this method is enabled or not.
160
		if ( isset( $request['enabled'] ) ) {
161
			$settings['enabled'] = wc_bool_to_string( $request['enabled'] );
162
			$gateway->enabled    = $settings['enabled'];
0 ignored issues
show
Bug introduced by
The property enabled does not seem to exist on WP_REST_Response.
Loading history...
163
		}
164
165
		// Update title.
166
		if ( isset( $request['title'] ) ) {
167
			$settings['title'] = $request['title'];
168
			$gateway->title    = $settings['title'];
0 ignored issues
show
Bug introduced by
The property title does not seem to exist on WP_REST_Response.
Loading history...
169
		}
170
171
		// Update description.
172
		if ( isset( $request['description'] ) ) {
173
			$settings['description'] = $request['description'];
174
			$gateway->description    = $settings['description'];
0 ignored issues
show
Bug introduced by
The property description does not seem to exist on WP_REST_Response.
Loading history...
175
		}
176
177
		// Update options.
178
		$gateway->settings = $settings;
179
		update_option( $gateway->get_option_key(), apply_filters( 'woocommerce_gateway_' . $gateway->id . '_settings_values', $settings, $gateway ) );
0 ignored issues
show
Bug introduced by
The method get_option_key() does not exist on WP_REST_Response. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

179
		update_option( $gateway->/** @scrutinizer ignore-call */ get_option_key(), apply_filters( 'woocommerce_gateway_' . $gateway->id . '_settings_values', $settings, $gateway ) );

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The property id does not seem to exist on WP_REST_Response.
Loading history...
180
181
		// Update order.
182
		if ( isset( $request['order'] ) ) {
183
			$order                 = (array) get_option( 'woocommerce_gateway_order' );
184
			$order[ $gateway->id ] = $request['order'];
185
			update_option( 'woocommerce_gateway_order', $order );
186
			$gateway->order = absint( $request['order'] );
0 ignored issues
show
Bug introduced by
The property order does not seem to exist on WP_REST_Response.
Loading history...
187
		}
188
189
		$gateway = $this->prepare_item_for_response( $gateway, $request );
190
		return rest_ensure_response( $gateway );
191
	}
192
193
	/**
194
	 * Get a gateway based on the current request object.
195
	 *
196
	 * @param \WP_REST_Request $request Request data.
197
	 * @return \WP_REST_Response|null
198
	 */
199
	public function get_gateway( $request ) {
200
		$gateway          = null;
201
		$payment_gateways = WC()->payment_gateways->payment_gateways();
202
		foreach ( $payment_gateways as $payment_gateway_id => $payment_gateway ) {
203
			if ( $request['id'] !== $payment_gateway_id ) {
204
				continue;
205
			}
206
			$payment_gateway->id = $payment_gateway_id;
207
			$gateway             = $payment_gateway;
208
		}
209
		return $gateway;
210
	}
211
212
	/**
213
	 * Prepare a payment gateway for response.
214
	 *
215
	 * @param  WC_Payment_Gateway $gateway    Payment gateway object.
0 ignored issues
show
Bug introduced by
The type WooCommerce\RestApi\Cont...ion4\WC_Payment_Gateway was not found. Did you mean WC_Payment_Gateway? If so, make sure to prefix the type with \.
Loading history...
216
	 * @param  \WP_REST_Request    $request    Request object.
217
	 * @return \WP_REST_Response   $response   Response data.
218
	 */
219
	public function prepare_item_for_response( $gateway, $request ) {
220
		$order = (array) get_option( 'woocommerce_gateway_order' );
221
		$item  = array(
222
			'id'                 => $gateway->id,
223
			'title'              => $gateway->title,
224
			'description'        => $gateway->description,
225
			'order'              => isset( $order[ $gateway->id ] ) ? $order[ $gateway->id ] : '',
226
			'enabled'            => ( 'yes' === $gateway->enabled ),
227
			'method_title'       => $gateway->get_method_title(),
228
			'method_description' => $gateway->get_method_description(),
229
			'method_supports'    => $gateway->supports,
230
			'settings'           => $this->get_settings( $gateway ),
231
		);
232
233
		$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
234
		$data    = $this->add_additional_fields_to_object( $item, $request );
235
		$data    = $this->filter_response_by_context( $data, $context );
236
237
		$response = rest_ensure_response( $data );
238
		$response->add_links( $this->prepare_links( $gateway, $request ) );
239
240
		/**
241
		 * Filter payment gateway objects returned from the REST API.
242
		 *
243
		 * @param \WP_REST_Response   $response The response object.
244
		 * @param WC_Payment_Gateway $gateway  Payment gateway object.
245
		 * @param \WP_REST_Request    $request  Request object.
246
		 */
247
		return apply_filters( 'woocommerce_rest_prepare_payment_gateway', $response, $gateway, $request );
248
	}
249
250
	/**
251
	 * Return settings associated with this payment gateway.
252
	 *
253
	 * @param WC_Payment_Gateway $gateway Gateway instance.
254
	 *
255
	 * @return array
256
	 */
257
	public function get_settings( $gateway ) {
258
		$settings = array();
259
		$gateway->init_form_fields();
260
		foreach ( $gateway->form_fields as $id => $field ) {
261
			// Make sure we at least have a title and type.
262
			if ( empty( $field['title'] ) || empty( $field['type'] ) ) {
263
				continue;
264
			}
265
266
			// Ignore 'enabled' and 'description' which get included elsewhere.
267
			if ( in_array( $id, array( 'enabled', 'description' ), true ) ) {
268
				continue;
269
			}
270
271
			$data = array(
272
				'id'          => $id,
273
				'label'       => empty( $field['label'] ) ? $field['title'] : $field['label'],
274
				'description' => empty( $field['description'] ) ? '' : $field['description'],
275
				'type'        => $field['type'],
276
				'value'       => empty( $gateway->settings[ $id ] ) ? '' : $gateway->settings[ $id ],
277
				'default'     => empty( $field['default'] ) ? '' : $field['default'],
278
				'tip'         => empty( $field['description'] ) ? '' : $field['description'],
279
				'placeholder' => empty( $field['placeholder'] ) ? '' : $field['placeholder'],
280
			);
281
			if ( ! empty( $field['options'] ) ) {
282
				$data['options'] = $field['options'];
283
			}
284
			$settings[ $id ] = $data;
285
		}
286
		return $settings;
287
	}
288
289
	/**
290
	 * Prepare links for the request.
291
	 *
292
	 * @param  WC_Payment_Gateway $gateway    Payment gateway object.
293
	 * @param  \WP_REST_Request    $request    Request object.
294
	 * @return array
295
	 */
296
	protected function prepare_links( $gateway, $request ) {
297
		$links = array(
298
			'self'       => array(
299
				'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $gateway->id ) ),
300
			),
301
			'collection' => array(
302
				'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
303
			),
304
		);
305
306
		return $links;
307
	}
308
309
	/**
310
	 * Get the payment gateway schema, conforming to JSON Schema.
311
	 *
312
	 * @return array
313
	 */
314
	public function get_item_schema() {
315
		$schema = array(
316
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
317
			'title'      => 'payment_gateway',
318
			'type'       => 'object',
319
			'properties' => array(
320
				'id'                 => array(
321
					'description' => __( 'Payment gateway ID.', 'woocommerce' ),
322
					'type'        => 'string',
323
					'context'     => array( 'view', 'edit' ),
324
					'readonly'    => true,
325
				),
326
				'title'              => array(
327
					'description' => __( 'Payment gateway title on checkout.', 'woocommerce' ),
328
					'type'        => 'string',
329
					'context'     => array( 'view', 'edit' ),
330
				),
331
				'description'        => array(
332
					'description' => __( 'Payment gateway description on checkout.', 'woocommerce' ),
333
					'type'        => 'string',
334
					'context'     => array( 'view', 'edit' ),
335
				),
336
				'order'              => array(
337
					'description' => __( 'Payment gateway sort order.', 'woocommerce' ),
338
					'type'        => 'integer',
339
					'context'     => array( 'view', 'edit' ),
340
					'arg_options' => array(
341
						'sanitize_callback' => 'absint',
342
					),
343
				),
344
				'enabled'            => array(
345
					'description' => __( 'Payment gateway enabled status.', 'woocommerce' ),
346
					'type'        => 'boolean',
347
					'context'     => array( 'view', 'edit' ),
348
				),
349
				'method_title'       => array(
350
					'description' => __( 'Payment gateway method title.', 'woocommerce' ),
351
					'type'        => 'string',
352
					'context'     => array( 'view', 'edit' ),
353
					'readonly'    => true,
354
				),
355
				'method_description' => array(
356
					'description' => __( 'Payment gateway method description.', 'woocommerce' ),
357
					'type'        => 'string',
358
					'context'     => array( 'view', 'edit' ),
359
					'readonly'    => true,
360
				),
361
				'method_supports'    => array(
362
					'description' => __( 'Supported features for this payment gateway.', 'woocommerce' ),
363
					'type'        => 'array',
364
					'context'     => array( 'view', 'edit' ),
365
					'readonly'    => true,
366
					'items'       => array(
367
						'type' => 'string',
368
					),
369
				),
370
				'settings'           => array(
371
					'description' => __( 'Payment gateway settings.', 'woocommerce' ),
372
					'type'        => 'object',
373
					'context'     => array( 'view', 'edit' ),
374
					'properties'  => array(
375
						'id'          => array(
376
							'description' => __( 'A unique identifier for the setting.', 'woocommerce' ),
377
							'type'        => 'string',
378
							'context'     => array( 'view', 'edit' ),
379
							'readonly'    => true,
380
						),
381
						'label'       => array(
382
							'description' => __( 'A human readable label for the setting used in interfaces.', 'woocommerce' ),
383
							'type'        => 'string',
384
							'context'     => array( 'view', 'edit' ),
385
							'readonly'    => true,
386
						),
387
						'description' => array(
388
							'description' => __( 'A human readable description for the setting used in interfaces.', 'woocommerce' ),
389
							'type'        => 'string',
390
							'context'     => array( 'view', 'edit' ),
391
							'readonly'    => true,
392
						),
393
						'type'        => array(
394
							'description' => __( 'Type of setting.', 'woocommerce' ),
395
							'type'        => 'string',
396
							'context'     => array( 'view', 'edit' ),
397
							'enum'        => array( 'text', 'email', 'number', 'color', 'password', 'textarea', 'select', 'multiselect', 'radio', 'image_width', 'checkbox' ),
398
							'readonly'    => true,
399
						),
400
						'value'       => array(
401
							'description' => __( 'Setting value.', 'woocommerce' ),
402
							'type'        => 'string',
403
							'context'     => array( 'view', 'edit' ),
404
						),
405
						'default'     => array(
406
							'description' => __( 'Default value for the setting.', 'woocommerce' ),
407
							'type'        => 'string',
408
							'context'     => array( 'view', 'edit' ),
409
							'readonly'    => true,
410
						),
411
						'tip'         => array(
412
							'description' => __( 'Additional help text shown to the user about the setting.', 'woocommerce' ),
413
							'type'        => 'string',
414
							'context'     => array( 'view', 'edit' ),
415
							'readonly'    => true,
416
						),
417
						'placeholder' => array(
418
							'description' => __( 'Placeholder text to be displayed in text inputs.', 'woocommerce' ),
419
							'type'        => 'string',
420
							'context'     => array( 'view', 'edit' ),
421
							'readonly'    => true,
422
						),
423
					),
424
				),
425
			),
426
		);
427
428
		return $this->add_additional_fields_schema( $schema );
429
	}
430
431
	/**
432
	 * Get any query params needed.
433
	 *
434
	 * @return array
435
	 */
436
	public function get_collection_params() {
437
		return array(
438
			'context' => $this->get_context_param( array( 'default' => 'view' ) ),
439
		);
440
	}
441
442
}
443