Passed
Push — master ( 5bd17a...71a32c )
by Mike
04:53
created

Continents::get_data_for_response()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * REST API Data continents controller.
4
 *
5
 * Handles requests to the /data/continents endpoint.
6
 *
7
 * @package WooCommerce/RestApi
8
 */
9
10
namespace WooCommerce\RestApi\Controllers\Version4\Data;
11
12
defined( 'ABSPATH' ) || exit;
13
14
use \WooCommerce\RestApi\Controllers\Version4\Data as DataController;
15
16
/**
17
 * REST API Data Continents controller class.
18
 */
19
class Continents extends DataController {
20
21
	/**
22
	 * Route base.
23
	 *
24
	 * @var string
25
	 */
26
	protected $rest_base = 'data/continents';
27
28
	/**
29
	 * Register routes.
30
	 *
31
	 * @since 3.5.0
32
	 */
33
	public function register_routes() {
34
		register_rest_route(
35
			$this->namespace,
36
			'/' . $this->rest_base,
37
			array(
38
				array(
39
					'methods'             => \WP_REST_Server::READABLE,
40
					'callback'            => array( $this, 'get_items' ),
41
					'permission_callback' => array( $this, 'get_items_permissions_check' ),
42
				),
43
				'schema' => array( $this, 'get_public_item_schema' ),
44
			)
45
		);
46
		register_rest_route(
47
			$this->namespace,
48
			'/' . $this->rest_base . '/(?P<location>[\w-]+)',
49
			array(
50
				array(
51
					'methods'             => \WP_REST_Server::READABLE,
52
					'callback'            => array( $this, 'get_item' ),
53
					'permission_callback' => array( $this, 'get_items_permissions_check' ),
54
					'args'                => array(
55
						'continent' => array(
56
							'description' => __( '2 character continent code.', 'woocommerce' ),
57
							'type'        => 'string',
58
						),
59
					),
60
				),
61
				'schema' => array( $this, 'get_public_item_schema' ),
62
			)
63
		);
64
	}
65
66
	/**
67
	 * Return the list of countries and states for a given continent.
68
	 *
69
	 * @since  3.5.0
70
	 * @param  string           $continent_code Continent code.
71
	 * @param  \WP_REST_Request $request        Request data.
72
	 * @return array|mixed Response data, ready for insertion into collection data.
73
	 */
74
	public function get_continent( $continent_code = false, $request ) {
75
		$continents  = WC()->countries->get_continents();
76
		$countries   = WC()->countries->get_countries();
77
		$states      = WC()->countries->get_states();
78
		$locale_info = include WC()->plugin_path() . '/i18n/locale-info.php';
79
		$data        = array();
80
81
		if ( ! array_key_exists( $continent_code, $continents ) ) {
82
			return false;
83
		}
84
85
		$continent_list = $continents[ $continent_code ];
86
87
		$continent = array(
88
			'code' => $continent_code,
89
			'name' => $continent_list['name'],
90
		);
91
92
		$local_countries = array();
93
		foreach ( $continent_list['countries'] as $country_code ) {
94
			if ( isset( $countries[ $country_code ] ) ) {
95
				$country = array(
96
					'code' => $country_code,
97
					'name' => $countries[ $country_code ],
98
				);
99
100
				// If we have detailed locale information include that in the response.
101
				if ( array_key_exists( $country_code, $locale_info ) ) {
102
					// Defensive programming against unexpected changes in locale-info.php.
103
					$country_data = wp_parse_args(
104
						$locale_info[ $country_code ],
105
						array(
106
							'currency_code'  => 'USD',
107
							'currency_pos'   => 'left',
108
							'decimal_sep'    => '.',
109
							'dimension_unit' => 'in',
110
							'num_decimals'   => 2,
111
							'thousand_sep'   => ',',
112
							'weight_unit'    => 'lbs',
113
						)
114
					);
115
116
					$country = array_merge( $country, $country_data );
117
				}
118
119
				$local_states = array();
120
				if ( isset( $states[ $country_code ] ) ) {
121
					foreach ( $states[ $country_code ] as $state_code => $state_name ) {
122
						$local_states[] = array(
123
							'code' => $state_code,
124
							'name' => $state_name,
125
						);
126
					}
127
				}
128
				$country['states'] = $local_states;
129
130
				// Allow only desired keys (e.g. filter out tax rates).
131
				$allowed = array(
132
					'code',
133
					'currency_code',
134
					'currency_pos',
135
					'decimal_sep',
136
					'dimension_unit',
137
					'name',
138
					'num_decimals',
139
					'states',
140
					'thousand_sep',
141
					'weight_unit',
142
				);
143
				$country = array_intersect_key( $country, array_flip( $allowed ) );
144
145
				$local_countries[] = $country;
146
			}
147
		}
148
149
		$continent['countries'] = $local_countries;
150
		return $continent;
151
	}
152
153
	/**
154
	 * Return the list of states for all continents.
155
	 *
156
	 * @since  3.5.0
157
	 * @param  \WP_REST_Request $request Request data.
158
	 * @return \WP_Error|\WP_REST_Response
159
	 */
160
	public function get_items( $request ) {
161
		$continents = WC()->countries->get_continents();
162
		$data       = array();
163
164
		foreach ( array_keys( $continents ) as $continent_code ) {
165
			$continent = $this->get_continent( $continent_code, $request );
166
			$response  = $this->prepare_item_for_response( $continent, $request );
167
			$data[]    = $this->prepare_response_for_collection( $response );
168
		}
169
170
		return rest_ensure_response( $data );
171
	}
172
173
	/**
174
	 * Return the list of locations for a given continent.
175
	 *
176
	 * @since  3.5.0
177
	 * @param  \WP_REST_Request $request Request data.
178
	 * @return \WP_Error|\WP_REST_Response
179
	 */
180
	public function get_item( $request ) {
181
		$data = $this->get_continent( strtoupper( $request['location'] ), $request );
182
		if ( empty( $data ) ) {
183
			return new \WP_Error( 'woocommerce_rest_data_invalid_location', __( 'There are no locations matching these parameters.', 'woocommerce' ), array( 'status' => 404 ) );
184
		}
185
		return $this->prepare_item_for_response( $data, $request );
186
	}
187
188
	/**
189
	 * Get data for this object in the format of this endpoint's schema.
190
	 *
191
	 * @param mixed            $object Object to prepare.
192
	 * @param \WP_REST_Request $request Request object.
193
	 * @return mixed Array of data in the correct format.
194
	 */
195
	protected function get_data_for_response( $object, $request ) {
196
		return $object;
197
	}
198
199
	/**
200
	 * Prepare links for the request.
201
	 *
202
	 * @param mixed            $item Object to prepare.
203
	 * @param \WP_REST_Request $request Request object.
204
	 * @return array
205
	 */
206
	protected function prepare_links( $item, $request ) {
207
		$continent_code = strtolower( $item['code'] );
208
		$links          = array(
209
			'self'       => array(
210
				'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $continent_code ) ),
211
			),
212
			'collection' => array(
213
				'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
214
			),
215
		);
216
		return $links;
217
	}
218
219
	/**
220
	 * Get the location schema, conforming to JSON Schema.
221
	 *
222
	 * @since  3.5.0
223
	 * @return array
224
	 */
225
	public function get_item_schema() {
226
		$schema = array(
227
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
228
			'title'      => 'continent',
229
			'type'       => 'object',
230
			'properties' => array(
231
				'code'      => array(
232
					'type'        => 'string',
233
					'description' => __( '2 character continent code.', 'woocommerce' ),
234
					'context'     => array( 'view' ),
235
					'readonly'    => true,
236
				),
237
				'name'      => array(
238
					'type'        => 'string',
239
					'description' => __( 'Full name of continent.', 'woocommerce' ),
240
					'context'     => array( 'view' ),
241
					'readonly'    => true,
242
				),
243
				'countries' => array(
244
					'type'        => 'array',
245
					'description' => __( 'List of countries on this continent.', 'woocommerce' ),
246
					'context'     => array( 'view' ),
247
					'readonly'    => true,
248
					'items'       => array(
249
						'type'       => 'object',
250
						'context'    => array( 'view' ),
251
						'readonly'   => true,
252
						'properties' => array(
253
							'code'           => array(
254
								'type'        => 'string',
255
								'description' => __( 'ISO3166 alpha-2 country code.', 'woocommerce' ),
256
								'context'     => array( 'view' ),
257
								'readonly'    => true,
258
							),
259
							'currency_code'  => array(
260
								'type'        => 'string',
261
								'description' => __( 'Default ISO4127 alpha-3 currency code for the country.', 'woocommerce' ),
262
								'context'     => array( 'view' ),
263
								'readonly'    => true,
264
							),
265
							'currency_pos'   => array(
266
								'type'        => 'string',
267
								'description' => __( 'Currency symbol position for this country.', 'woocommerce' ),
268
								'context'     => array( 'view' ),
269
								'readonly'    => true,
270
							),
271
							'decimal_sep'    => array(
272
								'type'        => 'string',
273
								'description' => __( 'Decimal separator for displayed prices for this country.', 'woocommerce' ),
274
								'context'     => array( 'view' ),
275
								'readonly'    => true,
276
							),
277
							'dimension_unit' => array(
278
								'type'        => 'string',
279
								'description' => __( 'The unit lengths are defined in for this country.', 'woocommerce' ),
280
								'context'     => array( 'view' ),
281
								'readonly'    => true,
282
							),
283
							'name'           => array(
284
								'type'        => 'string',
285
								'description' => __( 'Full name of country.', 'woocommerce' ),
286
								'context'     => array( 'view' ),
287
								'readonly'    => true,
288
							),
289
							'num_decimals'   => array(
290
								'type'        => 'integer',
291
								'description' => __( 'Number of decimal points shown in displayed prices for this country.', 'woocommerce' ),
292
								'context'     => array( 'view' ),
293
								'readonly'    => true,
294
							),
295
							'states'         => array(
296
								'type'        => 'array',
297
								'description' => __( 'List of states in this country.', 'woocommerce' ),
298
								'context'     => array( 'view' ),
299
								'readonly'    => true,
300
								'items'       => array(
301
									'type'       => 'object',
302
									'context'    => array( 'view' ),
303
									'readonly'   => true,
304
									'properties' => array(
305
										'code' => array(
306
											'type'        => 'string',
307
											'description' => __( 'State code.', 'woocommerce' ),
308
											'context'     => array( 'view' ),
309
											'readonly'    => true,
310
										),
311
										'name' => array(
312
											'type'        => 'string',
313
											'description' => __( 'Full name of state.', 'woocommerce' ),
314
											'context'     => array( 'view' ),
315
											'readonly'    => true,
316
										),
317
									),
318
								),
319
							),
320
							'thousand_sep'   => array(
321
								'type'        => 'string',
322
								'description' => __( 'Thousands separator for displayed prices in this country.', 'woocommerce' ),
323
								'context'     => array( 'view' ),
324
								'readonly'    => true,
325
							),
326
							'weight_unit'    => array(
327
								'type'        => 'string',
328
								'description' => __( 'The unit weights are defined in for this country.', 'woocommerce' ),
329
								'context'     => array( 'view' ),
330
								'readonly'    => true,
331
							),
332
						),
333
					),
334
				),
335
			),
336
		);
337
338
		return $this->add_additional_fields_schema( $schema );
339
	}
340
}
341