Completed
Push — master ( 31131b...6176aa )
by Mike
15:27
created

ProductResponse::prepare_response()   B

Complexity

Conditions 6
Paths 32

Size

Total Lines 97
Code Lines 82

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 82
nc 32
nop 2
dl 0
loc 97
rs 7.7705
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Convert a product object to the product schema format.
4
 *
5
 * @package WooCommerce/RestApi
6
 */
7
8
namespace WooCommerce\RestApi\Controllers\Version4\Responses;
9
10
defined( 'ABSPATH' ) || exit;
11
12
/**
13
 * ProductResponse class.
14
 */
15
class ProductResponse extends AbstractObjectResponse {
16
17
	/**
18
	 * Convert object to match data in the schema.
19
	 *
20
	 * @param \WC_Product_Simple|\WC_Product_Grouped|\WC_Product_Variable|\WC_Product_External $object Product data.
21
	 * @param string                                                                           $context Request context. Options: 'view' and 'edit'.
22
	 * @return array
23
	 */
24
	public function prepare_response( $object, $context ) {
25
		$data = array(
26
			'id'                    => $object->get_id(),
27
			'name'                  => $object->get_name( $context ),
28
			'slug'                  => $object->get_slug( $context ),
29
			'permalink'             => $object->get_permalink(),
30
			'date_created'          => wc_rest_prepare_date_response( $object->get_date_created( $context ), false ),
31
			'date_created_gmt'      => wc_rest_prepare_date_response( $object->get_date_created( $context ) ),
32
			'date_modified'         => wc_rest_prepare_date_response( $object->get_date_modified( $context ), false ),
33
			'date_modified_gmt'     => wc_rest_prepare_date_response( $object->get_date_modified( $context ) ),
34
			'type'                  => $object->get_type(),
35
			'status'                => $object->get_status( $context ),
36
			'featured'              => $object->is_featured(),
37
			'catalog_visibility'    => $object->get_catalog_visibility( $context ),
38
			'description'           => $object->get_description( $context ),
39
			'short_description'     => $object->get_short_description( $context ),
40
			'sku'                   => $object->get_sku( $context ),
41
			'price'                 => $object->get_price( $context ),
42
			'regular_price'         => $object->get_regular_price( $context ),
43
			'sale_price'            => $object->get_sale_price( $context ) ? $object->get_sale_price( $context ) : '',
44
			'date_on_sale_from'     => wc_rest_prepare_date_response( $object->get_date_on_sale_from( $context ), false ),
45
			'date_on_sale_from_gmt' => wc_rest_prepare_date_response( $object->get_date_on_sale_from( $context ) ),
46
			'date_on_sale_to'       => wc_rest_prepare_date_response( $object->get_date_on_sale_to( $context ), false ),
47
			'date_on_sale_to_gmt'   => wc_rest_prepare_date_response( $object->get_date_on_sale_to( $context ) ),
48
			'price_html'            => $object->get_price_html(),
49
			'on_sale'               => $object->is_on_sale( $context ),
50
			'purchasable'           => $object->is_purchasable(),
51
			'total_sales'           => $object->get_total_sales( $context ),
52
			'virtual'               => $object->is_virtual(),
53
			'downloadable'          => $object->is_downloadable(),
54
			'downloads'             => $this->prepare_downloads( $object ),
55
			'download_limit'        => $object->get_download_limit( $context ),
56
			'download_expiry'       => $object->get_download_expiry( $context ),
57
			'external_url'          => '',
58
			'button_text'           => '',
59
			'tax_status'            => $object->get_tax_status( $context ),
60
			'tax_class'             => $object->get_tax_class( $context ),
61
			'manage_stock'          => $object->managing_stock(),
62
			'stock_quantity'        => $object->get_stock_quantity( $context ),
63
			'stock_status'          => $object->get_stock_status( $context ),
64
			'backorders'            => $object->get_backorders( $context ),
65
			'backorders_allowed'    => $object->backorders_allowed(),
66
			'backordered'           => $object->is_on_backorder(),
67
			'sold_individually'     => $object->is_sold_individually(),
68
			'weight'                => $object->get_weight( $context ),
69
			'dimensions'            => array(
70
				'length' => $object->get_length( $context ),
71
				'width'  => $object->get_width( $context ),
72
				'height' => $object->get_height( $context ),
73
			),
74
			'shipping_required'     => $object->needs_shipping(),
75
			'shipping_taxable'      => $object->is_shipping_taxable(),
76
			'shipping_class'        => $object->get_shipping_class(),
77
			'shipping_class_id'     => $object->get_shipping_class_id( $context ),
78
			'reviews_allowed'       => $object->get_reviews_allowed( $context ),
79
			'average_rating'        => $object->get_average_rating( $context ),
80
			'rating_count'          => $object->get_rating_count(),
81
			'related_ids'           => wp_parse_id_list( wc_get_related_products( $object->get_id() ) ),
82
			'upsell_ids'            => wp_parse_id_list( $object->get_upsell_ids( $context ) ),
83
			'cross_sell_ids'        => wp_parse_id_list( $object->get_cross_sell_ids( $context ) ),
84
			'parent_id'             => $object->get_parent_id( $context ),
85
			'purchase_note'         => $object->get_purchase_note( $context ),
86
			'categories'            => $this->prepare_taxonomy_terms( $object ),
87
			'tags'                  => $this->prepare_taxonomy_terms( $object, 'tag' ),
88
			'images'                => $this->prepare_images( $object ),
89
			'attributes'            => $this->prepare_attributes( $object ),
90
			'default_attributes'    => $this->prepare_default_attributes( $object ),
91
			'variations'            => array(),
92
			'grouped_products'      => array(),
93
			'menu_order'            => $object->get_menu_order( $context ),
94
			'meta_data'             => $object->get_meta_data(),
95
		);
96
97
		// Add variations to variable products.
98
		if ( $object->is_type( 'variable' ) ) {
99
			$data['variations'] = $object->get_children();
100
		}
101
102
		// Add grouped products data.
103
		if ( $object->is_type( 'grouped' ) ) {
104
			$data['grouped_products'] = $object->get_children();
105
		}
106
107
		// Add external product data.
108
		if ( $object->is_type( 'external' ) ) {
109
			$data['external_url'] = $object->get_product_url( $context );
0 ignored issues
show
Bug introduced by
The method get_product_url() does not exist on WC_Product_Simple. ( Ignorable by Annotation )

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

109
			/** @scrutinizer ignore-call */ 
110
   $data['external_url'] = $object->get_product_url( $context );

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 method get_product_url() does not exist on WC_Product_Variable. ( Ignorable by Annotation )

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

109
			/** @scrutinizer ignore-call */ 
110
   $data['external_url'] = $object->get_product_url( $context );

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 method get_product_url() does not exist on WC_Product_Grouped. ( Ignorable by Annotation )

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

109
			/** @scrutinizer ignore-call */ 
110
   $data['external_url'] = $object->get_product_url( $context );

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...
110
			$data['button_text']  = $object->get_button_text( $context );
0 ignored issues
show
Bug introduced by
The method get_button_text() does not exist on WC_Product_Variable. ( Ignorable by Annotation )

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

110
			/** @scrutinizer ignore-call */ 
111
   $data['button_text']  = $object->get_button_text( $context );

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 method get_button_text() does not exist on WC_Product_Simple. ( Ignorable by Annotation )

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

110
			/** @scrutinizer ignore-call */ 
111
   $data['button_text']  = $object->get_button_text( $context );

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 method get_button_text() does not exist on WC_Product_Grouped. ( Ignorable by Annotation )

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

110
			/** @scrutinizer ignore-call */ 
111
   $data['button_text']  = $object->get_button_text( $context );

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...
111
		}
112
113
		if ( 'view' === $context ) {
114
			$data['description']       = wpautop( do_shortcode( $data['description'] ) );
115
			$data['short_description'] = apply_filters( 'woocommerce_short_description', $data['short_description'] );
116
			$data['average_rating']    = wc_format_decimal( $data['average_rating'], 2 );
117
			$data['purchase_note']     = wpautop( do_shortcode( $data['purchase_note'] ) );
118
		}
119
120
		return $data;
121
	}
122
123
	/**
124
	 * Get the downloads for a product or product variation.
125
	 *
126
	 * @param \WC_Product|\WC_Product_Variation $object Product instance.
127
	 *
128
	 * @return array
129
	 */
130
	protected function prepare_downloads( $object ) {
131
		$downloads = array();
132
133
		if ( $object->is_downloadable() ) {
134
			foreach ( $object->get_downloads() as $file_id => $file ) {
135
				$downloads[] = array(
136
					'id'   => $file_id, // MD5 hash.
137
					'name' => $file['name'],
138
					'file' => $file['file'],
139
				);
140
			}
141
		}
142
143
		return $downloads;
144
	}
145
146
	/**
147
	 * Get taxonomy terms.
148
	 *
149
	 * @param \WC_Product $object  Product instance.
150
	 * @param string      $taxonomy Taxonomy slug.
151
	 *
152
	 * @return array
153
	 */
154
	protected function prepare_taxonomy_terms( $object, $taxonomy = 'cat' ) {
155
		$terms = array();
156
157
		foreach ( wc_get_object_terms( $object->get_id(), 'product_' . $taxonomy ) as $term ) {
158
			$terms[] = array(
159
				'id'   => $term->term_id,
160
				'name' => $term->name,
161
				'slug' => $term->slug,
162
			);
163
		}
164
165
		return $terms;
166
	}
167
168
	/**
169
	 * Get the images for a product or product variation.
170
	 *
171
	 * @param \WC_Product|\WC_Product_Variation $object Product instance.
172
	 * @return array
173
	 */
174
	protected function prepare_images( $object ) {
175
		$images         = array();
176
		$attachment_ids = array();
177
178
		// Add featured image.
179
		if ( $object->get_image_id() ) {
180
			$attachment_ids[] = $object->get_image_id();
181
		}
182
183
		// Add gallery images.
184
		$attachment_ids = array_merge( $attachment_ids, $object->get_gallery_image_ids() );
185
186
		// Build image data.
187
		foreach ( $attachment_ids as $attachment_id ) {
188
			$attachment_post = get_post( $attachment_id );
189
			if ( is_null( $attachment_post ) ) {
190
				continue;
191
			}
192
193
			$attachment = wp_get_attachment_image_src( $attachment_id, 'full' );
194
			if ( ! is_array( $attachment ) ) {
195
				continue;
196
			}
197
198
			$images[] = array(
199
				'id'                => (int) $attachment_id,
200
				'date_created'      => wc_rest_prepare_date_response( $attachment_post->post_date, false ),
201
				'date_created_gmt'  => wc_rest_prepare_date_response( strtotime( $attachment_post->post_date_gmt ) ),
202
				'date_modified'     => wc_rest_prepare_date_response( $attachment_post->post_modified, false ),
203
				'date_modified_gmt' => wc_rest_prepare_date_response( strtotime( $attachment_post->post_modified_gmt ) ),
204
				'src'               => current( $attachment ),
205
				'name'              => get_the_title( $attachment_id ),
206
				'alt'               => get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ),
207
			);
208
		}
209
210
		return $images;
211
	}
212
213
	/**
214
	 * Get default attributes.
215
	 *
216
	 * @param \WC_Product $object Product instance.
217
	 *
218
	 * @return array
219
	 */
220
	protected function prepare_default_attributes( $object ) {
221
		$default = array();
222
223
		if ( $object->is_type( 'variable' ) ) {
224
			foreach ( array_filter( (array) $object->get_default_attributes(), 'strlen' ) as $key => $value ) {
225
				if ( 0 === strpos( $key, 'pa_' ) ) {
226
					$default[] = array(
227
						'id'     => wc_attribute_taxonomy_id_by_name( $key ),
228
						'name'   => $this->get_attribute_taxonomy_name( $key, $object ),
229
						'option' => $value,
230
					);
231
				} else {
232
					$default[] = array(
233
						'id'     => 0,
234
						'name'   => $this->get_attribute_taxonomy_name( $key, $object ),
235
						'option' => $value,
236
					);
237
				}
238
			}
239
		}
240
241
		return $default;
242
	}
243
244
	/**
245
	 * Get the attributes for a product or product variation.
246
	 *
247
	 * @param \WC_Product|\WC_Product_Variation $object Product instance.
248
	 *
249
	 * @return array
250
	 */
251
	protected function prepare_attributes( $object ) {
252
		$attributes = array();
253
254
		if ( $object->is_type( 'variation' ) ) {
255
			$_product = wc_get_product( $object->get_parent_id() );
256
			foreach ( $object->get_variation_attributes() as $attribute_name => $attribute ) {
0 ignored issues
show
Bug introduced by
The method get_variation_attributes() does not exist on WC_Product. Did you maybe mean get_variation_id()? ( Ignorable by Annotation )

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

256
			foreach ( $object->/** @scrutinizer ignore-call */ get_variation_attributes() as $attribute_name => $attribute ) {

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...
257
				$name = str_replace( 'attribute_', '', $attribute_name );
258
259
				if ( empty( $attribute ) && '0' !== $attribute ) {
260
					continue;
261
				}
262
263
				// Taxonomy-based attributes are prefixed with `pa_`, otherwise simply `attribute_`.
264
				if ( 0 === strpos( $attribute_name, 'attribute_pa_' ) ) {
265
					$option_term  = get_term_by( 'slug', $attribute, $name );
266
					$attributes[] = array(
267
						'id'     => wc_attribute_taxonomy_id_by_name( $name ),
268
						'name'   => $this->get_attribute_taxonomy_name( $name, $_product ),
269
						'option' => $option_term && ! is_wp_error( $option_term ) ? $option_term->name : $attribute,
270
					);
271
				} else {
272
					$attributes[] = array(
273
						'id'     => 0,
274
						'name'   => $this->get_attribute_taxonomy_name( $name, $_product ),
275
						'option' => $attribute,
276
					);
277
				}
278
			}
279
		} else {
280
			foreach ( $object->get_attributes() as $attribute ) {
281
				$attributes[] = array(
282
					'id'        => $attribute['is_taxonomy'] ? wc_attribute_taxonomy_id_by_name( $attribute['name'] ) : 0,
283
					'name'      => $this->get_attribute_taxonomy_name( $attribute['name'], $object ),
284
					'position'  => (int) $attribute['position'],
285
					'visible'   => (bool) $attribute['is_visible'],
286
					'variation' => (bool) $attribute['is_variation'],
287
					'options'   => $this->get_attribute_options( $object->get_id(), $attribute ),
288
				);
289
			}
290
		}
291
292
		return $attributes;
293
	}
294
295
	/**
296
	 * Get product attribute taxonomy name.
297
	 *
298
	 * @param string      $slug   Taxonomy name.
299
	 * @param \WC_Product $object Product data.
300
	 *
301
	 * @since  3.0.0
302
	 * @return string
303
	 */
304
	protected function get_attribute_taxonomy_name( $slug, $object ) {
305
		// Format slug so it matches attributes of the product.
306
		$slug       = wc_attribute_taxonomy_slug( $slug );
307
		$attributes = $object->get_attributes();
308
		$attribute  = false;
309
310
		// pa_ attributes.
311
		if ( isset( $attributes[ wc_attribute_taxonomy_name( $slug ) ] ) ) {
312
			$attribute = $attributes[ wc_attribute_taxonomy_name( $slug ) ];
313
		} elseif ( isset( $attributes[ $slug ] ) ) {
314
			$attribute = $attributes[ $slug ];
315
		}
316
317
		if ( ! $attribute ) {
318
			return $slug;
319
		}
320
321
		// Taxonomy attribute name.
322
		if ( $attribute->is_taxonomy() ) {
323
			$taxonomy = $attribute->get_taxonomy_object();
324
			return $taxonomy->attribute_label;
325
		}
326
327
		// Custom product attribute name.
328
		return $attribute->get_name();
329
	}
330
331
	/**
332
	 * Get attribute options.
333
	 *
334
	 * @param int   $object_id Product ID.
335
	 * @param array $attribute  Attribute data.
336
	 *
337
	 * @return array
338
	 */
339
	protected function get_attribute_options( $object_id, $attribute ) {
340
		if ( isset( $attribute['is_taxonomy'] ) && $attribute['is_taxonomy'] ) {
341
			return wc_get_product_terms(
342
				$object_id,
343
				$attribute['name'],
344
				array(
345
					'fields' => 'names',
346
				)
347
			);
348
		} elseif ( isset( $attribute['value'] ) ) {
349
			return array_map( 'trim', explode( '|', $attribute['value'] ) );
350
		}
351
352
		return array();
353
	}
354
}
355