Completed
Pull Request — master (#10259)
by Mike
09:41
created

WC_Order_Item::__construct()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 9
rs 9.6666
cc 3
eloc 6
nc 3
nop 1
1
<?php
2
/**
3
 * Order Item
4
 *
5
 * A class which represents an item within an order and handles CRUD.
6
 * Uses ArrayAccess to be BW compatible with WC_Orders::get_items().
7
 *
8
 * @class 		WC_Order_Item
9
 * @version		2.6.0
10
 * @since       2.6.0
11
 * @package		WooCommerce/Classes
12
 * @author 		WooThemes
13
 */
14
class WC_Order_Item implements ArrayAccess {
15
16
    /**
17
	 * Data array, with defaults.
18
	 * @since 2.6.0
19
	 * @var array
20
	 */
21
    protected $data = array(
22
		'order_id'      => 0,
23
		'order_item_id' => 0,
24
		'name'          => '',
25
		'type'          => '',
26
        'meta_data'     => array(),
27
	);
28
29
    /**
30
     * offsetSet for ArrayAccess
31
     * @param string $offset
32
     * @param mixed $value
33
     */
34
    public function offsetSet( $offset, $value ) {
35
        if ( 'item_meta_array' === $offset ) {
36
            $offset = 'meta_data';
37
        }
38
        $this->data[ $offset ] = $value;
39
    }
40
41
    /**
42
     * offsetUnset for ArrayAccess
43
     * @param string $offset
44
     */
45
    public function offsetUnset( $offset ) {
46
        if ( 'item_meta_array' === $offset || 'item_meta' === $offset ) {
47
            $this->data['meta_data'] = array();
48
        }
49
        unset( $this->data[ $offset ] );
50
    }
51
52
    /**
53
     * offsetExists for ArrayAccess
54
     * @param string $offset
55
     * @return bool
56
     */
57
    public function offsetExists( $offset ) {
58
        if ( 'item_meta_array' === $offset || 'item_meta' === $offset ) {
59
            return true;
60
        }
61
        return isset( $this->data[ $offset ] );
62
    }
63
64
    /**
65
     * offsetGet for ArrayAccess
66
     * @param string $offset
67
     * @return mixed
68
     */
69
    public function offsetGet( $offset ) {
70
        if( 'item_meta_array' === $offset ) {
71
            $offset = 'meta_data';
72
        }
73
        elseif( 'item_meta' === $offset ) {
74
            $meta_values = wp_list_pluck( $this->data['meta_data'], 'value', 'key' );
75
            return $meta_values;
76
        }
77
        return isset( $this->data[ $offset ] ) ? $this->data[ $offset ] : null;
78
    }
79
80
    /**
81
	 * Constructor.
82
	 * @param int|object $order_item ID to load from the DB (optional) or already queried data.
0 ignored issues
show
Bug introduced by
There is no parameter named $order_item. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
83
	 */
84
    public function __construct( $item = 0 ) {
85
		if ( $item instanceof WC_Order_Item ) {
86
            if ( $this->is_type( $item->get_type() ) ) {
87
                $this->set_all( $item );
88
            }
89
		} else {
90
            $this->read( $item );
91
        }
92
    }
93
94
    /**
95
     * Set data based on input item.
96
     * @access private
97
     */
98
    private function set_all( $item ) {
99
        foreach ( $item->get_data() as $key => $value ) {
100
            $this->data[ $key ] = $value;
101
        }
102
    }
103
104
    /**
105
     * Change data to JSON format.
106
     * @return string Data in JSON format.
107
     */
108
    public function __toString() {
109
        return json_encode( $this->get_data() );
110
    }
111
112
    /**
113
     * Type checking
114
     * @param  string  $Type
0 ignored issues
show
Bug introduced by
There is no parameter named $Type. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
115
     * @return boolean
116
     */
117
    public function is_type( $type ) {
118
        return $type === $this->get_type();
119
    }
120
121
    /**
122
     * Internal meta keys we don't want exposed as part of meta_data.
123
     * @return array()
0 ignored issues
show
Documentation introduced by
The doc-type array() could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
124
     */
125
    protected function get_internal_meta_keys() {
126
        return array();
127
    }
128
129
    /**
130
     * Get qty.
131
     * @return int
132
     */
133
    public function get_qty() {
134
        return 1;
135
    }
136
137
    /*
138
	|--------------------------------------------------------------------------
139
	| Getters
140
	|--------------------------------------------------------------------------
141
	*/
142
143
    /**
144
	 * Get all class data in array format.
145
	 * @since 2.6.0
146
	 * @return array
147
	 */
148
	public function get_data() {
149
		return $this->data;
150
	}
151
152
    /**
153
     * Get order ID this meta belongs to.
154
     * @return int
155
     */
156
    public function get_id() {
157
        return absint( $this->data['order_id'] );
158
    }
159
160
    /**
161
     * Get order item ID.
162
     * @return int
163
     */
164
    public function get_order_item_id() {
165
        return absint( $this->data['order_item_id'] );
166
    }
167
168
    /**
169
     * Get order item name.
170
     * @return string
171
     */
172
    public function get_name() {
173
        return $this->data['name'];
174
    }
175
176
    /**
177
     * Get order item type.
178
     * @return string
179
     */
180
    public function get_type() {
181
        return $this->data['type'];
182
    }
183
184
    /**
185
     * Get meta data
186
     * @return array
187
     */
188
    public function get_meta_data() {
189
        return $this->data['meta_data'];
190
    }
191
192
    /*
193
	|--------------------------------------------------------------------------
194
	| Setters
195
	|--------------------------------------------------------------------------
196
	*/
197
198
    /**
199
     * Set order ID.
200
     * @param int $value
201
     */
202
    public function set_order_id( $value ) {
203
        $this->data['order_id'] = absint( $value );
204
    }
205
206
    /**
207
     * Set order item ID.
208
     * @param int $value
209
     */
210
    public function set_order_item_id( $value ) {
211
        $this->data['order_item_id'] = absint( $value );
212
    }
213
214
    /**
215
     * Set order item name.
216
     * @param string $value
217
     */
218
    public function set_name( $value ) {
219
        $this->data['name'] = wc_clean( $value );
220
    }
221
222
    /**
223
     * Set order item type.
224
     * @param string $value
225
     */
226
    public function set_type( $value ) {
227
        $this->data['type'] = wc_clean( $value );
228
229
    }
230
231
    /**
232
     * Set meta data.
233
     * @param array $data Key/Value pairs
234
     */
235
    public function set_meta_data( $data ) {
236
        foreach ( $data as $key => $value ) {
237
            $this->data['meta_data'][ $key ] = $value;
238
        }
239
    }
240
241
    /**
242
     * Set meta data.
243
     * @param array $data Key/Value pairs
0 ignored issues
show
Bug introduced by
There is no parameter named $data. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
244
     */
245
    public function add_meta_data( $key, $value, $unique = false ) {
246
        if ( $unique ) {
247
            $meta_ids = array_keys( wp_list_pluck( $this->data['meta_data'], 'key' ), $key );
248
            $this->data['meta_data'] = array_diff_key( $this->data['meta_data'], array_fill_keys( $meta_ids, '' ) );
249
        }
250
        $this->data['meta_data'][] = array(
251
            'key'   => $key,
252
            'value' => $value
253
        );
254
    }
255
256
    /**
257
     * Update meta data by key or ID, if provided.
258
     * @param  string $key
259
     * @param  string $value
260
     * @param  int $meta_id
261
     */
262
    public function update_meta_data( $key, $value, $meta_id = '' ) {
263
        if ( $meta_id && isset( $this->data['meta_data'][ $meta_id ] ) ) {
264
            $this->data['meta_data'][ $meta_id ] = array(
265
                'key'   => $key,
266
                'value' => $value
267
            );
268
        } else {
269
            $this->add_meta_data( $key, $value, true );
270
        }
271
    }
272
273
    /*
274
	|--------------------------------------------------------------------------
275
	| CRUD methods
276
	|--------------------------------------------------------------------------
277
	|
278
	| Methods which create, read, update and delete data from the database.
279
	|
280
	*/
281
282
    /**
283
     * Insert data into the database.
284
	 * @since 2.6.0
285
     * @access private
286
     */
287 View Code Duplication
    private function create() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
288
        global $wpdb;
289
		$wpdb->insert( $wpdb->prefix . 'woocommerce_order_items', array(
290
            'order_item_name' => $this->get_name(),
291
            'order_item_type' => $this->get_type(),
292
            'order_id'        => $this->get_id()
293
        ) );
294
		$this->set_item_id( $wpdb->insert_id );
0 ignored issues
show
Bug introduced by
The method set_item_id() does not seem to exist on object<WC_Order_Item>.

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...
295
	}
296
297
    /**
298
     * Update data in the database.
299
	 * @since 2.6.0
300
	 * @access private
301
     */
302 View Code Duplication
    private function update() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
303
        global $wpdb;
304
		$wpdb->update( $wpdb->prefix . 'woocommerce_order_items', array(
305
            'order_item_name' => $this->get_name(),
306
            'order_item_type' => $this->get_type(),
307
            'order_id'        => $this->get_id()
308
        ), array( 'order_item_id' => $this->get_order_item_id() ) );
309
    }
310
311
	/**
312
     * Read from the database.
313
	 * @since 2.6.0
314
     * @access protected
315
     * @param int|object $item ID of object to read, or already queried object.
316
     */
317
    protected function read( $item ) {
318
		global $wpdb;
319
320
        if ( is_numeric( $item ) && ! empty( $item ) ) {
321
            $data = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_order_items WHERE order_item_id = %d LIMIT 1;", $item ) );
322
        } elseif ( ! empty( $item->order_item_id ) ) {
323
            $data = $item;
324
        } else {
325
            $data = false;
326
        }
327
328
		if ( $data ) {
329
			$this->set_order_id( $data->order_id );
330
			$this->set_order_item_id( $data->order_item_id );
331
			$this->set_name( $data->order_item_name );
332
            $this->set_type( $data->order_item_type );
333
            $this->read_meta_data();
334
		}
335
	}
336
337
    /**
338
     * Read Meta Data from the database. Ignore any internal properties.
339
     */
340
    protected function read_meta_data() {
341
        $this->data['meta_data'] = array();
342
343
        if ( $this->get_order_item_id() ) {
344
            // Get cache key - uses get_cache_prefix to invalidate when needed
345
            $cache_key       = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'meta_data_' . $this->get_order_item_id();
346
            $item_meta_array = wp_cache_get( $cache_key, 'orders' );
347
348
            if ( false === $item_meta_array ) {
349
                global $wpdb;
350
351
                $metadata = $wpdb->get_results( $wpdb->prepare( "SELECT meta_id, meta_key, meta_value FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id = %d ORDER BY meta_id", $this->get_order_item_id() ) );
352
                foreach ( $metadata as $metadata_row ) {
353
                    if ( in_array( $metadata_row->meta_key, $this->get_internal_meta_keys() ) ) {
354
                        continue;
355
                    }
356
                    $this->data['meta_data'][ $metadata_row->meta_id ] = (object) array( 'key' => $metadata_row->meta_key, 'value' => $metadata_row->meta_value );
357
                }
358
                wp_cache_set( $cache_key, $item_meta_array, 'orders' );
359
            }
360
        }
361
    }
362
363
    /**
364
     * Save data to the database.
365
	 * @since 2.6.0
366
     * @access protected
367
     */
368
    protected function save() {
369
        if ( ! $this->get_order_item_id() ) {
370
			$this->create();
371
        } else {
372
            $this->update();
373
        }
374
	}
375
376
    /**
377
     * Delte data from the database.
378
	 * @since 2.6.0
379
	 * @access protected
380
     */
381
    protected function delete() {
382
        global $wpdb;
383
		$wpdb->delete( $wpdb->prefix . 'woocommerce_order_items', array( 'order_item_id' => $this->get_order_item_id() ) );
384
    }
385
}
386