Completed
Pull Request — master (#11082)
by Jeff
07:32
created

WC_Rest_Settings_Controller::update_item()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 1
Metric Value
cc 2
eloc 9
c 4
b 0
f 1
nc 2
nop 1
dl 0
loc 16
rs 9.4285
1
<?php
2
if ( ! defined( 'ABSPATH' ) ) {
3
	exit;
4
}
5
6
/**
7
 * REST API Settings Controller.
8
 * Handles requests to the /settings/$group/$setting endpoints.
9
 *
10
 * @author   WooThemes
11
 * @category API
12
 * @package  WooCommerce/API
13
 * @version  2.7.0
14
 * @since    2.7.0
15
 */
16
class WC_Rest_Settings_Controller extends WC_REST_Settings_API_Controller {
17
18
	/**
19
	 * WP REST API namespace/version.
20
	 */
21
	protected $namespace = 'wc/v1';
22
23
	/**
24
	 * Register routes.
25
	 * @since 2.7.0
26
	 */
27
	public function register_routes() {
28
		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<group>[\w-]+)', array(
29
			array(
30
				'methods'             => WP_REST_Server::READABLE,
31
				'callback'            => array( $this, 'get_items' ),
32
				'permission_callback' => array( $this, 'permissions_check' ),
33
			),
34
			'schema' => array( $this, 'get_public_item_schema' ),
35
		) );
36
37
		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<group>[\w-]+)/batch', array(
38
			array(
39
				'methods'             => WP_REST_Server::EDITABLE,
40
				'callback'            => array( $this, 'batch_items' ),
41
				'permission_callback' => array( $this, 'permissions_check' ),
42
				'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
43
			),
44
			'schema' => array( $this, 'get_public_batch_schema' ),
45
		) );
46
47
		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<group>[\w-]+)/(?P<id>[\w-]+)', array(
48
			array(
49
				'methods'             => WP_REST_Server::READABLE,
50
				'callback'            => array( $this, 'get_item' ),
51
				'permission_callback' => array( $this, 'permissions_check' ),
52
			),
53
			array(
54
				'methods'             => WP_REST_Server::EDITABLE,
55
				'callback'            => array( $this, 'update_item' ),
56
				'permission_callback' => array( $this, 'permissions_check' ),
57
				'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
58
			),
59
			'schema' => array( $this, 'get_public_item_schema' ),
60
		) );
61
	}
62
63
	/**
64
	 * Return a single setting.
65
	 * @since  2.7.0
66
	 * @param  WP_REST_Request $request
67
	 * @return WP_Error|WP_REST_Response
68
	 */
69
	public function get_item( $request ) {
70
		$setting = $this->get_setting( $request['group'], $request['id'] );
71
72
		if ( is_wp_error( $setting ) ) {
73
			return $setting;
74
		}
75
76
		$response = $this->prepare_item_for_response( $setting, $request );
77
78
		return rest_ensure_response( $response );
79
	}
80
81
	/**
82
	 * Return all settings in a group.
83
	 * @since  2.7.0
84
	 * @param  WP_REST_Request $request
85
	 * @return WP_Error|WP_REST_Response
86
	 */
87
	public function get_items( $request ) {
88
		$settings = $this->get_group_settings( $request['group'] );
89
90
		if ( is_wp_error( $settings ) ) {
91
			return $settings;
92
		}
93
94
		$data = array();
95
96
		foreach ( $settings as $setting_obj ) {
97
			$setting = $this->prepare_item_for_response( $setting_obj, $request );
98
			$setting = $this->prepare_response_for_collection( $setting );
99
			$data[]  = $setting;
100
		}
101
102
		return rest_ensure_response( $data );
103
	}
104
105
	/**
106
	 * Get all settings in a group.
107
	 *
108
	 * @param string $group_id Group ID.
109
	 *
110
	 * @return array|WP_Error
111
	 */
112
	public function get_group_settings( $group_id ) {
113
		if ( empty( $group_id ) ) {
114
			return new WP_Error( 'rest_setting_setting_invalid', __( 'Invalid setting.', 'woocommerce' ), array( 'status' => 404 ) );
115
		}
116
117
		$settings = apply_filters( 'woocommerce_settings-' . $group_id, array() );
118
119
		if ( empty( $settings ) ) {
120
			return new WP_Error( 'rest_setting_setting_invalid', __( 'Invalid setting.', 'woocommerce' ), array( 'status' => 404 ) );
121
		}
122
123
		$filtered_settings = array();
124
125
		foreach ( $settings as $setting ) {
126
			$setting = $this->filter_setting( $setting );
127
			if ( $this->is_setting_type_valid( $setting['type'] ) ) {
128
				$setting['value']    = WC_Admin_Settings::get_option( $setting['id'] );
129
				$filtered_settings[] = $setting;
130
			}
131
		}
132
133
		return $filtered_settings;
134
	}
135
136
	/**
137
	 * Get setting data.
138
	 *
139
	 * @param string $group_id Group ID.
140
	 * @param string $setting_id Setting ID.
141
	 *
142
	 * @return stdClass|WP_Error
143
	 */
144
	public function get_setting( $group_id, $setting_id ) {
145
		if ( empty( $setting_id ) ) {
146
			return new WP_Error( 'rest_setting_setting_invalid', __( 'Invalid setting.', 'woocommerce' ), array( 'status' => 404 ) );
147
		}
148
149
		$settings = $this->get_group_settings( $group_id );
150
151
		if ( is_wp_error( $settings ) ) {
152
			return $settings;
153
		}
154
155
		$array_key = array_keys( wp_list_pluck( $settings, 'id' ), $setting_id );
156
157
		if ( empty( $array_key ) ) {
158
			return new WP_Error( 'rest_setting_setting_invalid', __( 'Invalid setting.', 'woocommerce' ), array( 'status' => 404 ) );
159
		}
160
161
		$setting = $settings[ $array_key[0] ];
162
163
		if ( ! $this->is_setting_type_valid( $setting['type'] ) ) {
164
			return new WP_Error( 'rest_setting_setting_invalid', __( 'Invalid setting.', 'woocommerce' ), array( 'status' => 404 ) );
165
		}
166
167
		return $setting;
168
	}
169
170
	/**
171
	 * Bulk create, update and delete items.
172
	 *
173
	 * @param WP_REST_Request $request Full details about the request.
174
	 * @return array Of WP_Error or WP_REST_Response.
175
	 */
176
	public function batch_items( $request ) {
177
		// Get the request params.
178
		$items = array_filter( $request->get_params() );
179
180
		/*
181
		 * Since our batch settings update is group-specific and matches based on the route,
182
		 * we inject the URL parameters (containing group) into the batch items
183
		 */
184
		if ( ! empty( $items['update'] ) ) {
185
			$to_update = array();
186
			foreach ( $items['update'] as $item ) {
187
				$to_update[] = array_merge( $request->get_url_params(), $item );
188
			}
189
			$request = new WP_REST_Request( $request->get_method() );
190
			$request->set_body_params( array( 'update' => $to_update ) );
191
		}
192
193
		return parent::batch_items( $request );
194
	}
195
196
	/**
197
	 * Update a single setting in a group.
198
	 * @since  2.7.0
199
	 * @param  WP_REST_Request $request
200
	 * @return WP_Error|WP_REST_Response
201
	 */
202
	public function update_item( $request ) {
203
		$setting = $this->get_setting( $request['group'], $request['id'] );
204
205
		if ( is_wp_error( $setting ) ) {
206
			return $setting;
207
		}
208
209
		$update_data = array();
210
		$update_data[ $setting['id'] ] = $request['value'];
211
212
		WC_Admin_Settings::save_fields( array( $setting ), $update_data );
213
214
		$response = $this->prepare_item_for_response( $setting, $request );
215
216
		return rest_ensure_response( $response );
217
	}
218
219
	/**
220
	 * Prepare a single setting object for response.
221
	 *
222
	 * @param object $item Setting object.
223
	 * @param WP_REST_Request $request Request object.
224
	 * @return WP_REST_Response $response Response data.
225
	 */
226
	public function prepare_item_for_response( $item, $request ) {
227
		$data          = $this->filter_setting( $item );
0 ignored issues
show
Documentation introduced by
$item is of type object, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
228
		$data['value'] = WC_Admin_Settings::get_option( $data['id'] );
229
230
		$context = empty( $request['context'] ) ? 'view' : $request['context'];
231
		$data    = $this->add_additional_fields_to_object( $data, $request );
232
		$data    = $this->filter_response_by_context( $data, $context );
233
234
		$response = rest_ensure_response( $data );
235
236
		$response->add_links( $this->prepare_links( $data['id'], $request['group'] ) );
237
238
		return $response;
239
	}
240
241
	/**
242
	 * Prepare links for the request.
243
	 *
244
	 * @param string $setting_id Setting ID.
245
	 * @param string $group_id Group ID.
246
	 * @return array Links for the given setting.
247
	 */
248
	protected function prepare_links( $setting_id, $group_id ) {
249
		$base  = '/' . $this->namespace . '/' . $this->rest_base . '/' . $group_id;
250
		$links = array(
251
			'self' => array(
252
				'href' => rest_url( trailingslashit( $base ) . $setting_id ),
253
			),
254
			'collection' => array(
255
				'href' => rest_url( $base ),
256
			),
257
		);
258
259
		return $links;
260
	}
261
262
	/**
263
	 * Get the settings schema, conforming to JSON Schema.
264
	 *
265
	 * @since 2.7.0
266
	 * @return array
267
	 */
268
	public function get_item_schema() {
269
		$schema = array(
270
			'$schema'              => 'http://json-schema.org/draft-04/schema#',
271
			'title'                => 'settings',
272
			'type'                 => 'object',
273
			'properties'           => array(
274
				'id'               => array(
275
					'description'  => __( 'A unique identifier for the setting.', 'woocommerce' ),
276
					'type'         => 'string',
277
					'arg_options'  => array(
278
						'sanitize_callback' => 'sanitize_title',
279
					),
280
				),
281
				'label'            => array(
282
					'description'  => __( 'A human readable label. This is a translated string that can be used in interfaces.', 'woocommerce' ),
283
					'type'         => 'string',
284
					'arg_options'  => array(
285
						'sanitize_callback' => 'sanitize_text_field',
286
					),
287
				),
288
				'description'      => array(
289
					'description'  => __( 'A human readable description. This is a translated string that can be used in interfaces.', 'woocommerce' ),
290
					'type'         => 'string',
291
					'arg_options'  => array(
292
						'sanitize_callback' => 'sanitize_text_field',
293
					),
294
				),
295
				'default'          => array(
296
					'description'  => __( 'Default value for the setting.', 'woocommerce' ),
297
					'type'         => 'mixed',
298
				),
299
				'tip'              => array(
300
					'description'  => __( 'Extra help text explaining the setting.', 'woocommerce' ),
301
					'type'         => 'string',
302
					'arg_options'  => array(
303
						'sanitize_callback' => 'sanitize_text_field',
304
					),
305
				),
306
				'placeholder'      => array(
307
					'description'  => __( 'Placeholder text to be displayed in text inputs.', 'woocommerce' ),
308
					'type'         => 'string',
309
					'arg_options'  => array(
310
						'sanitize_callback' => 'sanitize_text_field',
311
					),
312
				),
313
				'type'             => array(
314
					'description'  => __( 'Type of setting. Allowed values: text, email, number, color, password, textarea, select, multiselect, radio, image_width, checkbox.', 'woocommerce' ),
315
					'type'         => 'string',
316
					'arg_options'  => array(
317
						'sanitize_callback' => 'sanitize_text_field',
318
					),
319
				),
320
				'options'          => array(
321
					'description'  => __( 'Array of options (key value pairs) for inputs such as select, multiselect, and radio buttons.', 'woocommerce' ),
322
					'type'         => 'array',
323
				),
324
			),
325
		);
326
327
		return $this->add_additional_fields_schema( $schema );
328
	}
329
}
330