Completed
Pull Request — master (#11082)
by Jeff
09:19
created

WC_Rest_Settings_Options_Controller::get_setting()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 25
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 13
nc 5
nop 2
dl 0
loc 25
rs 8.439
c 1
b 0
f 0
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_Options_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 View Code Duplication
	protected function prepare_links( $setting_id, $group_id ) {
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...
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