Completed
Pull Request — master (#9826)
by Mike
21:27
created

WC_Shipping_Zone::set_zone_id()   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.6.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
		} elseif ( 0 === $zone ) {
48
			$this->set_zone_name( __( 'Worldwide', 'woocommerce' ) );
49
			$this->read_zone_locations( 0 );
50
		}
51
    }
52
53
	/**
54
	 * Get class data array
55
	 * @return array
56
	 */
57
	public function get_data() {
58
		return $this->data;
59
	}
60
61
	/**
62
	 * Get zone ID
63
	 * @return int
64
	 */
65
    public function get_zone_id() {
66
        return absint( $this->data['zone_id'] );
67
    }
68
69
	/**
70
	 * Get zone name
71
	 * @return string
72
	 */
73
    public function get_zone_name() {
74
        return $this->data['zone_name'];
75
    }
76
77
	/**
78
	 * Get zone order
79
	 * @return int
80
	 */
81
	public function get_zone_order() {
82
        return absint( $this->data['zone_order'] );
83
    }
84
85
	/**
86
	 * Get zone locations
87
	 * @return array of zone objects
88
	 */
89
	public function get_zone_locations() {
90
        return $this->data['zone_locations'];
91
    }
92
93
	/**
94
	 * Return a text string representing what this zone is for.
95
	 * @return string
96
	 */
97
	public function get_formatted_location( $max = 10 ) {
98
		$location_parts = array();
99
		$all_continents = WC()->countries->get_continents();
100
		$all_countries  = WC()->countries->get_countries();
101
		$all_states     = WC()->countries->get_states();
102
		$locations      = $this->get_zone_locations();
103
		$continents     = array_filter( $locations, array( $this, 'location_is_continent' ) );
104
		$countries      = array_filter( $locations, array( $this, 'location_is_country' ) );
105
		$states         = array_filter( $locations, array( $this, 'location_is_state' ) );
106
		$postcodes      = array_filter( $locations, array( $this, 'location_is_postcode' ) );
107
108
		foreach ( $continents as $location ) {
109
			$location_parts[] = $all_continents[ $location->code ]['name'];
110
		}
111
112
		foreach ( $countries as $location ) {
113
			$location_parts[] = $all_countries[ $location->code ];
114
		}
115
116
		foreach ( $states as $location ) {
117
			$location_codes = explode( ':', $location->code );
118
			$location_parts[] = $all_states[ $location_codes[ 0 ] ][ $location_codes[ 1 ] ];
119
		}
120
121
		foreach ( $postcodes as $location ) {
122
			$location_parts[] = $location->code;
123
		}
124
125
		if ( sizeof( $location_parts ) > $max ) {
126
			$remaining = sizeof( $location_parts ) - $max;
127
			return sprintf( _n( '%s and %d other region', '%s and %d other regions', $remaining, 'woocommerce' ), implode( ', ', array_splice( $location_parts, 0, $max ) ), $remaining );
128
		} else {
129
			return implode( ', ', $location_parts );
130
		}
131
	}
132
133
	/**
134
	 * Get shipping methods linked to this zone
135
	 * @return array of objects
136
	 */
137
	public function get_shipping_methods() {
138
		global $wpdb;
139
140
        $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() ) );
141
		$wc_shipping     = WC_Shipping::instance();
142
		$allowed_classes = $wc_shipping->get_shipping_method_class_names();
143
		$methods         = array();
144
145
		foreach ( $raw_methods as $raw_method ) {
146
			if ( in_array( $raw_method->method_id, array_keys( $allowed_classes ) ) ) {
147
				$class_name                          = $allowed_classes[ $raw_method->method_id ];
148
				$methods[ $raw_method->instance_id ] = new $class_name( $raw_method->instance_id );
149
				$methods[ $raw_method->instance_id ]->method_order = absint( $raw_method->method_order );
150
			}
151
		}
152
153
		return $methods;
154
	}
155
156
	/**
157
	 * Location type detection
158
	 * @param  object  $location
159
	 * @return boolean
160
	 */
161
	private function location_is_continent( $location ) {
162
		return 'continent' === $location->type;
163
	}
164
165
	/**
166
	 * Location type detection
167
	 * @param  object  $location
168
	 * @return boolean
169
	 */
170
	private function location_is_country( $location ) {
171
		return 'country' === $location->type;
172
	}
173
174
	/**
175
	 * Location type detection
176
	 * @param  object  $location
177
	 * @return boolean
178
	 */
179
	private function location_is_state( $location ) {
180
		return 'state' === $location->type;
181
	}
182
183
	/**
184
	 * Location type detection
185
	 * @param  object  $location
186
	 * @return boolean
187
	 */
188
	private function location_is_postcode( $location ) {
189
		return 'postcode' === $location->type;
190
	}
191
192
	/**
193
	 * Set zone ID
194
	 * @access private
195
	 * @param int $set
196
	 */
197
    private function set_zone_id( $set ) {
198
        $this->data['zone_id'] = absint( $set );
199
    }
200
201
	/**
202
	 * Set zone name
203
	 * @param string $set
204
	 */
205
    public function set_zone_name( $set ) {
206
		$this->data['zone_name'] = wc_clean( $set );
207
    }
208
209
	/**
210
	 * Set zone order
211
	 * @param int $set
212
	 */
213
	public function set_zone_order( $set ) {
214
        $this->data['zone_order'] = absint( $set );
215
    }
216
217
	/**
218
     * Insert zone into the database
219
     * @access private
220
     * @param int Read zone data from DB
221
     */
222
    private function read( $zone_id ) {
223
		global $wpdb;
224
225
		if ( $zone_data = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zones WHERE zone_id = %d LIMIT 1;", $zone_id ) ) ) {
226
			$this->set_zone_id( $zone_data->zone_id );
227
			$this->set_zone_name( $zone_data->zone_name );
228
			$this->set_zone_order( $zone_data->zone_order );
229
			$this->read_zone_locations( $zone_data->zone_id );
230
		}
231
	}
232
233
	/**
234
	 * Is passed location type valid?
235
	 * @param  string  $type
236
	 * @return boolean
237
	 */
238
	public function is_valid_location_type( $type ) {
239
		return in_array( $type, array( 'postcode', 'state', 'country', 'continent' ) );
240
	}
241
242
	/**
243
	 * Add location (state or postcode) to a zone.
244
	 * @param string $code
245
	 * @param string $type state or postcode
246
	 */
247
	public function add_location( $code, $type ) {
248
		if ( $this->is_valid_location_type( $type ) ) {
249
			$location = array(
250
				'code' => wc_clean( $code ),
251
				'type' => wc_clean( $type )
252
			);
253
			$this->data['zone_locations'][] = (object) $location;
254
			$this->_locations_changed = true;
255
		}
256
	}
257
258
	/**
259
	 * Clear all locations for this zone.
260
	 */
261
	public function clear_locations() {
262
		$this->data['zone_locations'] = array();
263
		$this->_locations_changed = true;
264
	}
265
266
	/**
267
	 * Set locations
268
	 * @param array $locations Array of locations
269
	 */
270
	public function set_locations( $locations = array() ) {
271
		$this->clear_locations();
272
273
		foreach ( $locations as $location ) {
274
			$this->add_location( $location['code'], $location['type'] );
275
		}
276
277
		$this->_locations_changed = true;
278
	}
279
280
	/**
281
	 * Read location data from the database
282
	 * @param  int $zone_id
283
	 */
284
	private function read_zone_locations( $zone_id ) {
285
		global $wpdb;
286
287
		if ( $locations = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zone_locations WHERE zone_id = %d;", $zone_id ) ) ) {
288
			foreach ( $locations as $location ) {
289
				$this->add_location( $location->location_code, $location->location_type );
290
			}
291
		}
292
		$this->_locations_changed = false;
293
	}
294
295
	/**
296
     * Save zone data to the database
297
     * @param array data to save for this zone
298
     */
299
    public function save() {
300
		$data = array(
301
			'zone_name'  => $this->get_zone_name(),
302
			'zone_order' => $this->get_zone_order(),
303
		);
304
305
        if ( ! $this->get_zone_id() ) {
306
			$this->create( $data );
307
        } else {
308
            $this->update( $data );
309
        }
310
311
		$this->save_locations();
312
		WC_Cache_Helper::incr_cache_prefix( 'shipping_zones' );
313
	}
314
315
	/**
316
	 * Save locations to the DB
317
	 *
318
	 * This function clears old locations, then re-inserts new if any changes are found.
319
	 */
320
	private function save_locations() {
321
		if ( ! $this->get_zone_id() || ! $this->_locations_changed ) {
322
			return false;
323
		}
324
		global $wpdb;
325
		$wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zone_locations', array( 'zone_id' => $this->get_zone_id() ) );
326
327
		foreach ( $this->get_zone_locations() as $location ) {
328
			$wpdb->insert( $wpdb->prefix . 'woocommerce_shipping_zone_locations', array(
329
				'zone_id'       => $this->get_zone_id(),
330
				'location_code' => $location->code,
331
				'location_type' => $location->type
332
			) );
333
		}
334
	}
335
336
	/**
337
     * Insert zone into the database
338
     * @access private
339
     * @param array $zone_data data to save for this zone
340
     */
341
    private function create( $zone_data ) {
342
		global $wpdb;
343
		$wpdb->insert( $wpdb->prefix . 'woocommerce_shipping_zones', $zone_data );
344
		$this->set_zone_id( $wpdb->insert_id );
345
	}
346
347
    /**
348
     * Update zone in the database
349
	 * @access private
350
     * @param array $zone_data data to save for this zone
351
     */
352
    public function update( $zone_data ) {
353
        global $wpdb;
354
		$wpdb->update( $wpdb->prefix . 'woocommerce_shipping_zones', $zone_data, array( 'zone_id' => $this->get_zone_id() ) );
355
    }
356
357
	/**
358
	 * Add a shipping method to this zone.
359
	 * @param string $type shipping method type
360
	 * @return int new instance_id, 0 on failure
361
	 */
362
	public function add_shipping_method( $type ) {
363
		global $wpdb;
364
365
		$instance_id     = 0;
366
		$wc_shipping     = WC_Shipping::instance();
367
		$allowed_classes = $wc_shipping->get_shipping_method_class_names();
368
369
		if ( in_array( $type, array_keys( $allowed_classes ) ) ) {
370
			$wpdb->insert(
371
				$wpdb->prefix . 'woocommerce_shipping_zone_methods',
372
				array(
373
					'method_id'    => $type,
374
					'zone_id'      => $this->get_zone_id(),
375
					'method_order' => 0
376
				),
377
				array(
378
					'%s',
379
					'%d',
380
					'%d'
381
				)
382
			);
383
			$instance_id = $wpdb->insert_id;
384
		}
385
386
		return $instance_id;
387
	}
388
}
389