Completed
Push — master ( a60b03...41517c )
by Claudio
27:03
created

WC_API_Coupons   C

Complexity

Total Complexity 72

Size/Duplication

Total Lines 229
Duplicated Lines 8.3 %

Coupling/Cohesion

Components 2
Dependencies 4
Metric Value
wmc 72
lcom 2
cbo 4
dl 19
loc 229
rs 5.5667

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like WC_API_Coupons often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use WC_API_Coupons, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * WooCommerce API Coupons Class
4
 *
5
 * Handles requests to the /coupons endpoint
6
 *
7
 * @author      WooThemes
8
 * @category    API
9
 * @package     WooCommerce/API
10
 * @since       2.1
11
 * @version     2.1
12
 */
13
14
if ( ! defined( 'ABSPATH' ) ) {
15
	exit; // Exit if accessed directly
16
}
17
18
class WC_API_Coupons extends WC_API_Resource {
19
20
	/** @var string $base the route base */
21
	protected $base = '/coupons';
22
23
	/**
24
	 * Register the routes for this class
25
	 *
26
	 * GET /coupons
27
	 * GET /coupons/count
28
	 * GET /coupons/<id>
29
	 *
30
	 * @since 2.1
31
	 * @param array $routes
32
	 * @return array
33
	 */
34
	public function register_routes( $routes ) {
35
36
		# GET /coupons
37
		$routes[ $this->base ] = array(
38
			array( array( $this, 'get_coupons' ),     WC_API_Server::READABLE ),
39
		);
40
41
		# GET /coupons/count
42
		$routes[ $this->base . '/count'] = array(
43
			array( array( $this, 'get_coupons_count' ), WC_API_Server::READABLE ),
44
		);
45
46
		# GET /coupons/<id>
47
		$routes[ $this->base . '/(?P<id>\d+)' ] = array(
48
			array( array( $this, 'get_coupon' ),  WC_API_Server::READABLE ),
49
		);
50
51
		# GET /coupons/code/<code>, note that coupon codes can contain spaces, dashes and underscores
52
		$routes[ $this->base . '/code/(?P<code>\w[\w\s\-]*)' ] = array(
53
			array( array( $this, 'get_coupon_by_code' ), WC_API_Server::READABLE ),
54
		);
55
56
		return $routes;
57
	}
58
59
	/**
60
	 * Get all coupons
61
	 *
62
	 * @since 2.1
63
	 * @param string $fields
64
	 * @param array $filter
65
	 * @param int $page
66
	 * @return array
67
	 */
68
	public function get_coupons( $fields = null, $filter = array(), $page = 1 ) {
69
70
		$filter['page'] = $page;
71
72
		$query = $this->query_coupons( $filter );
73
74
		$coupons = array();
75
76
		foreach( $query->posts as $coupon_id ) {
77
78
			if ( ! $this->is_readable( $coupon_id ) )
79
				continue;
80
81
			$coupons[] = current( $this->get_coupon( $coupon_id, $fields ) );
82
		}
83
84
		$this->server->add_pagination_headers( $query );
85
86
		return array( 'coupons' => $coupons );
87
	}
88
89
	/**
90
	 * Get the coupon for the given ID
91
	 *
92
	 * @since 2.1
93
	 * @param int $id the coupon ID
94
	 * @param string $fields fields to include in response
95
	 * @return array|WP_Error
96
	 */
97
	public function get_coupon( $id, $fields = null ) {
98
		global $wpdb;
99
100
		$id = $this->validate_request( $id, 'shop_coupon', 'read' );
101
102
		if ( is_wp_error( $id ) )
103
			return $id;
104
105
		// get the coupon code
106
		$code = $wpdb->get_var( $wpdb->prepare( "SELECT post_title FROM $wpdb->posts WHERE id = %s AND post_type = 'shop_coupon' AND post_status = 'publish'", $id ) );
107
108
		if ( is_null( $code ) )
109
			return new WP_Error( 'woocommerce_api_invalid_coupon_id', __( 'Invalid coupon ID', 'woocommerce' ), array( 'status' => 404 ) );
110
111
		$coupon = new WC_Coupon( $code );
112
113
		$coupon_post = get_post( $coupon->id );
114
115
		$coupon_data = array(
116
			'id'                           => $coupon->id,
117
			'code'                         => $coupon->code,
118
			'type'                         => $coupon->type,
119
			'created_at'                   => $this->server->format_datetime( $coupon_post->post_date_gmt ),
120
			'updated_at'                   => $this->server->format_datetime( $coupon_post->post_modified_gmt ),
121
			'amount'                       => wc_format_decimal( $coupon->amount, 2 ),
122
			'individual_use'               => ( 'yes' === $coupon->individual_use ),
123
			'product_ids'                  => array_map( 'absint', (array) $coupon->product_ids ),
124
			'exclude_product_ids'          => array_map( 'absint', (array) $coupon->exclude_product_ids ),
125
			'usage_limit'                  => ( ! empty( $coupon->usage_limit ) ) ? $coupon->usage_limit : null,
126
			'usage_limit_per_user'         => ( ! empty( $coupon->usage_limit_per_user ) ) ? $coupon->usage_limit_per_user : null,
127
			'limit_usage_to_x_items'       => (int) $coupon->limit_usage_to_x_items,
128
			'usage_count'                  => (int) $coupon->usage_count,
129
			'expiry_date'                  => $this->server->format_datetime( $coupon->expiry_date ),
130
			'enable_free_shipping'         => $coupon->enable_free_shipping(),
131
			'product_category_ids'         => array_map( 'absint', (array) $coupon->product_categories ),
132
			'exclude_product_category_ids' => array_map( 'absint', (array) $coupon->exclude_product_categories ),
133
			'exclude_sale_items'           => $coupon->exclude_sale_items(),
134
			'minimum_amount'               => wc_format_decimal( $coupon->minimum_amount, 2 ),
135
			'customer_emails'              => $coupon->customer_email,
136
		);
137
138
		return array( 'coupon' => apply_filters( 'woocommerce_api_coupon_response', $coupon_data, $coupon, $fields, $this->server ) );
139
	}
140
141
	/**
142
	 * Get the total number of coupons
143
	 *
144
	 * @since 2.1
145
	 * @param array $filter
146
	 * @return array
147
	 */
148
	public function get_coupons_count( $filter = array() ) {
149
150
		$query = $this->query_coupons( $filter );
151
152
		if ( ! current_user_can( 'read_private_shop_coupons' ) )
153
			return new WP_Error( 'woocommerce_api_user_cannot_read_coupons_count', __( 'You do not have permission to read the coupons count', 'woocommerce' ), array( 'status' => 401 ) );
154
155
		return array( 'count' => (int) $query->found_posts );
156
	}
157
158
	/**
159
	 * Get the coupon for the given code
160
	 *
161
	 * @since 2.1
162
	 * @param string $code the coupon code
163
	 * @param string $fields fields to include in response
164
	 * @return int|WP_Error
165
	 */
166
	public function get_coupon_by_code( $code, $fields = null ) {
167
		global $wpdb;
168
169
		$id = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM $wpdb->posts WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' ORDER BY post_date DESC LIMIT 1;", $code ) );
170
171
		if ( is_null( $id ) )
172
			return new WP_Error( 'woocommerce_api_invalid_coupon_code', __( 'Invalid coupon code', 'woocommerce' ), array( 'status' => 404 ) );
173
174
		return $this->get_coupon( $id, $fields );
175
	}
176
177
	/**
178
	 * Create a coupon
179
	 *
180
	 * @TODO implement in 2.2
181
	 * @param array $data
182
	 * @return array
183
	 */
184
	public function create_coupon( $data ) {
185
186
		return array();
187
	}
188
189
	/**
190
	 * Edit a coupon
191
	 *
192
	 * @TODO implement in 2.2
193
	 * @param int $id the coupon ID
194
	 * @param array $data
195
	 * @return array
196
	 */
197
	public function edit_coupon( $id, $data ) {
198
199
		$id = $this->validate_request( $id, 'shop_coupon', 'edit' );
200
201
		if ( is_wp_error( $id ) )
202
			return $id;
203
204
		return $this->get_coupon( $id );
205
	}
206
207
	/**
208
	 * Delete a coupon
209
	 *
210
	 * @TODO enable along with PUT/POST in 2.2
211
	 * @param int $id the coupon ID
212
	 * @param bool $force true to permanently delete coupon, false to move to trash
213
	 * @return array
214
	 */
215
	public function delete_coupon( $id, $force = false ) {
216
217
		$id = $this->validate_request( $id, 'shop_coupon', 'delete' );
218
219
		if ( is_wp_error( $id ) )
220
			return $id;
221
222
		return $this->delete( $id, 'shop_coupon', ( 'true' === $force ) );
223
	}
224
225
	/**
226
	 * Helper method to get coupon post objects
227
	 *
228
	 * @since 2.1
229
	 * @param array $args request arguments for filtering query
230
	 * @return WP_Query
231
	 */
232
	private function query_coupons( $args ) {
233
234
		// set base query arguments
235
		$query_args = array(
236
			'fields'      => 'ids',
237
			'post_type'   => 'shop_coupon',
238
			'post_status' => 'publish',
239
		);
240
241
		$query_args = $this->merge_query_args( $query_args, $args );
242
243
		return new WP_Query( $query_args );
244
	}
245
246
}
247