Completed
Pull Request — master (#9826)
by Mike
10:01
created

WC_Shipping_Zone::location_is_state()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 3
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
1 ignored issue
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 16 and the first side effect is on line 4.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
if ( ! defined( 'ABSPATH' ) ) {
4
	exit;
5
}
6
7
/**
8
 * Represents a single shipping zone
9
 *
10
 * @class 		WC_Shipping_Zone
11
 * @version		2.5.0
12
 * @package		WooCommerce/Classes
13
 * @category	Class
14
 * @author 		WooThemes
15
 */
16
class WC_Shipping_Zone {
17
18
	/**
19
	 * Zone Data
20
	 * @var array
21
	 */
22
    private $data = array(
23
		'zone_id'        => 0,
24
		'zone_name'      => '',
25
		'zone_order'     => 0,
26
		'zone_locations' => array()
27
	);
28
29
	/**
30
	 * True when location data needs to be re-saved
31
	 * @var bool
32
	 */
33
	private $_locations_changed = false;
34
35
	/**
36
	 * Constructor for zones
37
	 * @param int|object $zone Zone ID to load from the DB (optional) or already queried data.
38
	 */
39
    public function __construct( $zone = 0 ) {
40
		if ( is_numeric( $zone ) && ! empty( $zone ) ) {
41
        	$this->read( $zone );
42
		} elseif ( is_object( $zone ) ) {
43
			$this->set_zone_id( $zone->zone_id );
44
			$this->set_zone_name( $zone->zone_name );
45
			$this->set_zone_order( $zone->zone_order );
46
			$this->read_zone_locations( $zone->zone_id );
47
		}
48
    }
49
50
	/**
51
	 * Get class data array
52
	 * @return array
53
	 */
54
	public function get_data() {
55
		return $this->data;
56
	}
57
58
	/**
59
	 * Get zone ID
60
	 * @return int
61
	 */
62
    public function get_zone_id() {
63
        return absint( $this->data['zone_id'] );
64
    }
65
66
	/**
67
	 * Get zone name
68
	 * @return string
69
	 */
70
    public function get_zone_name() {
71
        return $this->data['zone_name'];
72
    }
73
74
	/**
75
	 * Get zone order
76
	 * @return int
77
	 */
78
	public function get_zone_order() {
79
        return absint( $this->data['zone_order'] );
80
    }
81
82
	/**
83
	 * Get zone locations
84
	 * @return array of zone objects
85
	 */
86
	public function get_zone_locations() {
87
        return $this->data['zone_locations'];
88
    }
89
90
	/**
91
	 * Return a text string representing what this zone is for.
92
	 * @return string
93
	 */
94
	public function get_formatted_location( $max = 10 ) {
95
		$location_parts = array();
96
		$all_continents = WC()->countries->get_continents();
97
		$all_countries  = WC()->countries->get_countries();
98
		$all_states     = WC()->countries->get_states();
99
		$locations      = $this->get_zone_locations();
100
		$continents     = array_filter( $locations, array( $this, 'location_is_continent' ) );
101
		$countries      = array_filter( $locations, array( $this, 'location_is_country' ) );
102
		$states         = array_filter( $locations, array( $this, 'location_is_state' ) );
103
		$postcodes      = array_filter( $locations, array( $this, 'location_is_postcode' ) );
104
105
		foreach ( $continents as $location ) {
106
			$location_parts[] = $all_continents[ $location->code ]['name'];
107
		}
108
109
		foreach ( $countries as $location ) {
110
			$location_parts[] = $all_countries[ $location->code ];
111
		}
112
113
		foreach ( $states as $location ) {
114
			$location_codes = explode( ':', $location->code );
115
			$location_parts[] = $all_states[ $location_codes[ 0 ] ][ $location_codes[ 1 ] ];
116
		}
117
118
		foreach ( $postcodes as $location ) {
119
			$location_parts[] = $location->code;
120
		}
121
122
		if ( sizeof( $location_parts ) > $max ) {
123
			$remaining = sizeof( $location_parts ) - $max;
124
			return sprintf( _n( '%s and %d other region', '%s and %d other regions', $remaining, 'woocommerce' ), implode( ', ', array_splice( $location_parts, 0, $max ) ), $remaining );
125
		} else {
126
			return implode( ', ', $location_parts );
127
		}
128
	}
129
130
	/**
131
	 * Get shipping methods linked to this zone
132
	 * @return array of objects
133
	 */
134
	public function get_shipping_methods() {
135
		global $wpdb;
136
137
        $raw_methods     = $wpdb->get_results( $wpdb->prepare( "SELECT method_id, method_order, instance_id FROM {$wpdb->prefix}woocommerce_shipping_zone_methods WHERE zone_id = %d order by method_order ASC;", $this->get_zone_id() ) );
138
		$wc_shipping     = WC_Shipping::instance();
139
		$allowed_classes = $wc_shipping->get_shipping_method_class_names();
140
		$methods         = array();
141
142
		foreach ( $raw_methods as $raw_method ) {
143 View Code Duplication
			if ( in_array( $raw_method->method_id, array_keys( $allowed_classes ) ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
144
				$class_name                          = $allowed_classes[ $raw_method->method_id ];
145
				$methods[ $raw_method->instance_id ] = new $class_name( $raw_method->instance_id );
146
			}
147
		}
148
149
		return $methods;
150
	}
151
152
	/**
153
	 * Location type detection
154
	 * @param  object  $location
155
	 * @return boolean
156
	 */
157
	private function location_is_continent( $location ) {
158
		return 'continent' === $location->type;
159
	}
160
161
	/**
162
	 * Location type detection
163
	 * @param  object  $location
164
	 * @return boolean
165
	 */
166
	private function location_is_country( $location ) {
167
		return 'country' === $location->type;
168
	}
169
170
	/**
171
	 * Location type detection
172
	 * @param  object  $location
173
	 * @return boolean
174
	 */
175
	private function location_is_state( $location ) {
176
		return 'state' === $location->type;
177
	}
178
179
	/**
180
	 * Location type detection
181
	 * @param  object  $location
182
	 * @return boolean
183
	 */
184
	private function location_is_postcode( $location ) {
185
		return 'postcode' === $location->type;
186
	}
187
188
	/**
189
	 * Set zone ID
190
	 * @access private
191
	 * @param int $set
192
	 */
193
    private function set_zone_id( $set ) {
194
        $this->data['zone_id'] = absint( $set );
195
    }
196
197
	/**
198
	 * Set zone name
199
	 * @param string $set
200
	 */
201
    public function set_zone_name( $set ) {
202
		$this->data['zone_name'] = wc_clean( $set );
203
    }
204
205
	/**
206
	 * Set zone order
207
	 * @param int $set
208
	 */
209
	public function set_zone_order( $set ) {
210
        $this->data['zone_order'] = absint( $set );
211
    }
212
213
	/**
214
     * Insert zone into the database
215
     * @access private
216
     * @param int Read zone data from DB
217
     */
218
    private function read( $zone_id ) {
219
		global $wpdb;
220
221
		if ( $zone_data = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zones WHERE zone_id = %d LIMIT 1;", $zone_id ) ) ) {
222
			$this->set_zone_id( $zone_data->zone_id );
223
			$this->set_zone_name( $zone_data->zone_name );
224
			$this->set_zone_order( $zone_data->zone_order );
225
			$this->read_zone_locations( $zone_data->zone_id );
226
		}
227
	}
228
229
	/**
230
	 * Is passed location type valid?
231
	 * @param  string  $type
232
	 * @return boolean
233
	 */
234
	public function is_valid_location_type( $type ) {
235
		return in_array( $type, array( 'postcode', 'state', 'country', 'continent' ) );
236
	}
237
238
	/**
239
	 * Add location (state or postcode) to a zone.
240
	 * @param string $code
241
	 * @param string $type state or postcode
242
	 */
243
	public function add_location( $code, $type ) {
244
		if ( $this->is_valid_location_type( $type ) ) {
245
			$location = array(
246
				'code' => wc_clean( $code ),
247
				'type' => wc_clean( $type )
248
			);
249
			$this->data['zone_locations'][] = (object) $location;
250
			$this->_locations_changed = true;
251
		}
252
	}
253
254
	/**
255
	 * Clear all locations for this zone.
256
	 */
257
	public function clear_locations() {
258
		$this->data['zone_locations'] = array();
259
		$this->_locations_changed = true;
260
	}
261
262
	/**
263
	 * Set locations
264
	 * @param array $locations Array of locations
265
	 */
266
	public function set_locations( $locations = array() ) {
267
		$this->clear_locations();
268
269
		foreach ( $locations as $location ) {
270
			$this->add_location( $location['code'], $location['type'] );
271
		}
272
273
		$this->_locations_changed = true;
274
	}
275
276
	/**
277
	 * Read location data from the database
278
	 * @param  int $zone_id
279
	 */
280
	private function read_zone_locations( $zone_id ) {
281
		global $wpdb;
282
283
		if ( $locations = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zone_locations WHERE zone_id = %d;", $zone_id ) ) ) {
284
			foreach ( $locations as $location ) {
285
				$this->add_location( $location->location_code, $location->location_type );
286
			}
287
		}
288
		$this->_locations_changed = false;
289
	}
290
291
	/**
292
     * Save zone data to the database
293
     * @param array data to save for this zone
294
     */
295
    public function save() {
296
		$data = array(
297
			'zone_name'  => $this->get_zone_name(),
298
			'zone_order' => $this->get_zone_order(),
299
		);
300
301
        if ( ! $this->get_zone_id() ) {
302
			$this->create( $data );
303
        } else {
304
            $this->update( $data );
305
        }
306
307
		$this->save_locations();
308
	}
309
310
	/**
311
	 * Save locations to the DB
312
	 *
313
	 * This function clears old locations, then re-inserts new if any changes are found.
314
	 */
315
	private function save_locations() {
316
		if ( ! $this->get_zone_id() || ! $this->_locations_changed ) {
317
			return false;
318
		}
319
		global $wpdb;
320
		$wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zone_locations', array( 'zone_id' => $this->get_zone_id() ) );
321
322
		foreach ( $this->get_zone_locations() as $location ) {
323
			$wpdb->insert( $wpdb->prefix . 'woocommerce_shipping_zone_locations', array(
324
				'zone_id'       => $this->get_zone_id(),
325
				'location_code' => $location->code,
326
				'location_type' => $location->type
327
			) );
328
		}
329
	}
330
331
	/**
332
     * Insert zone into the database
333
     * @access private
334
     * @param array $zone_data data to save for this zone
335
     */
336
    private function create( $zone_data ) {
337
		global $wpdb;
338
		$wpdb->insert( $wpdb->prefix . 'woocommerce_shipping_zones', $zone_data );
339
		$this->set_zone_id( $wpdb->insert_id );
340
	}
341
342
    /**
343
     * Update zone in the database
344
	 * @access private
345
     * @param array $zone_data data to save for this zone
346
     */
347
    public function update( $zone_data ) {
348
        global $wpdb;
349
		$wpdb->update( $wpdb->prefix . 'woocommerce_shipping_zones', $zone_data, array( 'zone_id' => $this->get_zone_id() ) );
350
    }
351
}
352