Completed
Pull Request — master (#11208)
by Mike
09:06
created

WC_Abstract_Legacy_Order::__get()   C

Complexity

Conditions 25
Paths 23

Size

Total Lines 51
Code Lines 48

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 25
eloc 48
c 1
b 0
f 0
nc 23
nop 1
dl 0
loc 51
rs 5.5218

How to fix   Long Method    Complexity   

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
if ( ! defined( 'ABSPATH' ) ) {
3
	exit;
4
}
5
6
/**
7
 * Legacy Abstract Order
8
 *
9
 * Legacy and deprecated functions are here to keep the WC_Abstract_Order clean.
10
 * This class will be removed in future versions.
11
 *
12
 * @version	 2.7.0
13
 * @package	 WooCommerce/Abstracts
14
 * @category	Abstract Class
15
 * @author	  WooThemes
16
 */
17
abstract class WC_Abstract_Legacy_Order extends WC_Data {
18
19
	/**
20
	 * Update a line item for the order.
21
	 *
22
	 * Note this does not update order totals.
23
	 *
24
	 * @since 2.2
25
	 * @param object|int $item order item ID or item object.
26
	 * @param WC_Product $product
27
	 * @param array $args data to update.
28
	 * @return int updated order item ID
29
	 */
30
	 public function update_product( $item, $product, $args ) {
31
		_deprecated_function( 'WC_Order::update_product', '2.7', 'Interact with WC_Order_Item_Product class' );
32
		if ( is_numeric( $item ) ) {
33
			$item = $this->get_item( $item );
0 ignored issues
show
Bug introduced by
The method get_item() does not exist on WC_Abstract_Legacy_Order. Did you maybe mean get_item_downloads()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
34
		}
35
		if ( ! is_object( $item ) || ! $item->is_type( 'line_item' ) ) {
36
			return false;
37
		}
38
		if ( ! $this->get_id() ) {
39
			$this->save(); // Order must exist
40
		}
41
42
		// BW compatibility with old args
43 View Code Duplication
		if ( isset( $args['totals'] ) ) {
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...
44
			foreach ( $args['totals'] as $key => $value ) {
45
				if ( 'tax' === $key ) {
46
					$args['total_tax'] = $value;
47
				} elseif ( 'tax_data' === $key ) {
48
					$args['taxes'] = $value;
49
				} else {
50
					$args[ $key ] = $value;
51
				}
52
			}
53
		}
54
55
		// Handly qty if set
56
		if ( isset( $args['qty'] ) ) {
57 View Code Duplication
			if ( $product->backorders_require_notification() && $product->is_on_backorder( $args['qty'] ) ) {
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...
58
				$item->add_meta_data( apply_filters( 'woocommerce_backordered_item_meta_name', __( 'Backordered', 'woocommerce' ) ), $args['qty'] - max( 0, $product->get_total_stock() ), true );
59
			}
60
			$args['subtotal'] = $args['subtotal'] ? $args['subtotal'] : $product->get_price_excluding_tax( $args['qty'] );
61
			$args['total']	= $args['total'] ? $args['total'] : $product->get_price_excluding_tax( $args['qty'] );
62
		}
63
64
		$item->set_order_id( $this->get_id() );
65
		$item->set_all( $args );
66
		$item->save();
67
		do_action( 'woocommerce_order_edit_product', $this->get_id(), $item->get_id(), $args, $product );
68
69
		return $item->get_id();
70
	}
71
72
	/**
73
	 * Update coupon for order. Note this does not update order totals.
74
	 * @since 2.2
75
	 * @param object|int $item
76
	 * @param array $args
77
	 * @return int updated order item ID
78
	 */
79
	public function update_coupon( $item, $args ) {
80
		_deprecated_function( 'WC_Order::update_coupon', '2.7', 'Interact with WC_Order_Item_Coupon class' );
81
		if ( is_numeric( $item ) ) {
82
			$item = $this->get_item( $item );
0 ignored issues
show
Bug introduced by
The method get_item() does not exist on WC_Abstract_Legacy_Order. Did you maybe mean get_item_downloads()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
83
		}
84
		if ( ! is_object( $item ) || ! $item->is_type( 'coupon' ) ) {
85
			return false;
86
		}
87
		if ( ! $this->get_id() ) {
88
			$this->save(); // Order must exist
89
		}
90
91
		// BW compatibility for old args
92
		if ( isset( $args['discount_amount'] ) ) {
93
			$args['discount'] = $args['discount_amount'];
94
		}
95
		if ( isset( $args['discount_amount_tax'] ) ) {
96
			$args['discount_tax'] = $args['discount_amount_tax'];
97
		}
98
99
		$item->set_order_id( $this->get_id() );
100
		$item->set_all( $args );
101
		$item->save();
102
103
		do_action( 'woocommerce_order_update_coupon', $this->get_id(), $item->get_id(), $args );
104
105
		return $item->get_id();
106
	}
107
108
	/**
109
	 * Update shipping method for order.
110
	 *
111
	 * Note this does not update the order total.
112
	 *
113
	 * @since 2.2
114
	 * @param object|int $item
115
	 * @param array $args
116
	 * @return int updated order item ID
117
	 */
118
	public function update_shipping( $item, $args ) {
119
		_deprecated_function( 'WC_Order::update_shipping', '2.7', 'Interact with WC_Order_Item_Shipping class' );
120
		if ( is_numeric( $item ) ) {
121
			$item = $this->get_item( $item );
0 ignored issues
show
Bug introduced by
The method get_item() does not exist on WC_Abstract_Legacy_Order. Did you maybe mean get_item_downloads()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
122
		}
123
		if ( ! is_object( $item ) || ! $item->is_type( 'shipping' ) ) {
124
			return false;
125
		}
126
		if ( ! $this->get_id() ) {
127
			$this->save(); // Order must exist
128
		}
129
130
		// BW compatibility for old args
131
		if ( isset( $args['cost'] ) ) {
132
			$args['total'] = $args['cost'];
133
		}
134
135
		$item->set_order_id( $this->get_id() );
136
		$item->set_all( $args );
137
		$item->save();
138
		$this->calculate_shipping();
139
140
		do_action( 'woocommerce_order_update_shipping', $this->get_id(), $item->get_id(), $args );
141
142
		return $item->get_id();
143
	}
144
145
	/**
146
	 * Update fee for order.
147
	 *
148
	 * Note this does not update order totals.
149
	 *
150
	 * @since 2.2
151
	 * @param object|int $item
152
	 * @param array $args
153
	 * @return int updated order item ID
154
	 */
155 View Code Duplication
	public function update_fee( $item, $args ) {
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...
156
		_deprecated_function( 'WC_Order::update_fee', '2.7', 'Interact with WC_Order_Item_Fee class' );
157
		if ( is_numeric( $item ) ) {
158
			$item = $this->get_item( $item );
0 ignored issues
show
Bug introduced by
The method get_item() does not exist on WC_Abstract_Legacy_Order. Did you maybe mean get_item_downloads()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
159
		}
160
		if ( ! is_object( $item ) || ! $item->is_type( 'fee' ) ) {
161
			return false;
162
		}
163
		if ( ! $this->get_id() ) {
164
			$this->save(); // Order must exist
165
		}
166
167
		$item->set_order_id( $this->get_id() );
168
		$item->set_all( $args );
169
		$item->save();
170
171
		do_action( 'woocommerce_order_update_fee', $this->get_id(), $item->get_id(), $args );
172
173
		return $item->get_id();
174
	}
175
176
	/**
177
	 * Update tax line on order.
178
	 * Note this does not update order totals.
179
	 *
180
	 * @since 2.7
181
	 * @param object|int $item
182
	 * @param array $args
183
	 * @return int updated order item ID
184
	 */
185 View Code Duplication
	public function update_tax( $item, $args ) {
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...
186
		_deprecated_function( 'WC_Order::update_tax', '2.7', 'Interact with WC_Order_Item_Tax class' );
187
		if ( is_numeric( $item ) ) {
188
			$item = $this->get_item( $item );
0 ignored issues
show
Bug introduced by
The method get_item() does not exist on WC_Abstract_Legacy_Order. Did you maybe mean get_item_downloads()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
189
		}
190
		if ( ! is_object( $item ) || ! $item->is_type( 'tax' ) ) {
191
			return false;
192
		}
193
		if ( ! $this->get_id() ) {
194
			$this->save(); // Order must exist
195
		}
196
197
		$item->set_order_id( $this->get_id() );
198
		$item->set_all( $args );
199
		$item->save();
200
201
		do_action( 'woocommerce_order_update_tax', $this->get_id(), $item->get_id(), $args );
202
203
		return $item->get_id();
204
	}
205
206
	/**
207
	 * Get a product (either product or variation).
208
	 * @deprecated Add deprecation notices in future release. Replaced with $item->get_product()
209
	 * @param object $item
210
	 * @return WC_Product|bool
211
	 */
212
	public function get_product_from_item( $item ) {
213
		if ( is_callable( array( $item, 'get_product' ) ) ) {
214
			$product = $item->get_product();
215
		} else {
216
			$product = false;
217
		}
218
		return apply_filters( 'woocommerce_get_product_from_item', $product, $item, $this );
219
	}
220
221
	/**
222
	 * Set the customer address.
223
	 * @since 2.2.0
224
	 * @param array $address Address data.
225
	 * @param string $type billing or shipping.
226
	 */
227
	public function set_address( $address, $type = 'billing' ) {
228
		foreach ( $address as $key => $value ) {
229
			update_post_meta( $this->get_id(), "_{$type}_" . $key, $value );
230 View Code Duplication
			if ( is_callable( array( $this, "set_{$type}_{$key}" ) ) ) {
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...
231
				$this->{"set_{$type}_{$key}"}( $value );
232
			}
233
		}
234
	}
235
236
	/**
237
	 * Set an order total.
238
	 * @since 2.2.0
239
	 * @param float $amount
240
	 * @param string $total_type
241
	 * @return bool
242
	 */
243
	public function legacy_set_total( $amount, $total_type = 'total' ) {
244
		if ( ! in_array( $total_type, array( 'shipping', 'tax', 'shipping_tax', 'total', 'cart_discount', 'cart_discount_tax' ) ) ) {
245
			return false;
246
		}
247
248
		switch ( $total_type ) {
249
			case 'total' :
250
				$amount = wc_format_decimal( $amount, wc_get_price_decimals() );
251
				$this->set_total( $amount );
0 ignored issues
show
Bug introduced by
The method set_total() does not exist on WC_Abstract_Legacy_Order. Did you maybe mean legacy_set_total()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
252
				update_post_meta( $this->get_id(), '_order_total', $amount );
253
				break;
254
			case 'cart_discount' :
255
				$amount = wc_format_decimal( $amount );
256
				$this->set_discount_total( $amount );
257
				update_post_meta( $this->get_id(), '_cart_discount', $amount );
258
				break;
259
			case 'cart_discount_tax' :
260
				$amount = wc_format_decimal( $amount );
261
				$this->set_discount_tax( $amount );
262
				update_post_meta( $this->get_id(), '_cart_discount_tax', $amount );
263
				break;
264
			case 'shipping' :
265
				$amount = wc_format_decimal( $amount );
266
				$this->set_shipping_total( $amount );
267
				update_post_meta( $this->get_id(), '_order_shipping', $amount );
268
				break;
269
			case 'shipping_tax' :
270
				$amount = wc_format_decimal( $amount );
271
				$this->set_shipping_tax( $amount );
272
				update_post_meta( $this->get_id(), '_order_shipping_tax', $amount );
273
				break;
274
			case 'tax' :
275
				$amount = wc_format_decimal( $amount );
276
				$this->set_cart_tax( $amount );
277
				update_post_meta( $this->get_id(), '_order_tax', $amount );
278
				break;
279
		}
280
281
		return true;
282
	}
283
284
	/**
285
	 * Magic __isset method for backwards compatibility.
286
	 * @param string $key
287
	 * @return bool
288
	 */
289
	public function __isset( $key ) {
290
		// Legacy properties which could be accessed directly in the past.
291
		$legacy_props = array( 'completed_date', 'id', 'order_type', 'post', 'status', 'post_status', 'customer_note', 'customer_message', 'user_id', 'customer_user', 'prices_include_tax', 'tax_display_cart', 'display_totals_ex_tax', 'display_cart_ex_tax', 'order_date', 'modified_date', 'cart_discount', 'cart_discount_tax', 'order_shipping', 'order_shipping_tax', 'order_total', 'order_tax', 'billing_first_name', 'billing_last_name', 'billing_company', 'billing_address_1', 'billing_address_2', 'billing_city', 'billing_state', 'billing_postcode', 'billing_country', 'billing_phone', 'billing_email', 'shipping_first_name', 'shipping_last_name', 'shipping_company', 'shipping_address_1', 'shipping_address_2', 'shipping_city', 'shipping_state', 'shipping_postcode', 'shipping_country', 'customer_ip_address', 'customer_user_agent', 'payment_method_title', 'payment_method', 'order_currency' );
292
		return $this->get_id() ? ( in_array( $key, $legacy_props ) || metadata_exists( 'post', $this->get_id(), '_' . $key ) ) : false;
293
	}
294
295
	/**
296
	 * Magic __get method for backwards compatibility.
297
	 * @param string $key
298
	 * @return mixed
299
	 */
300
	public function __get( $key ) {
301
		_doing_it_wrong( $key, 'Order properties should not be accessed directly.', '2.7' );
302
303
		if ( 'completed_date' === $key ) {
304
			return $this->get_date_completed();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class WC_Abstract_Legacy_Order as the method get_date_completed() does only exist in the following sub-classes of WC_Abstract_Legacy_Order: WC_Order. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
305
		} elseif ( 'paid_date' === $key ) {
306
			return $this->get_date_paid();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class WC_Abstract_Legacy_Order as the method get_date_paid() does only exist in the following sub-classes of WC_Abstract_Legacy_Order: WC_Order. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
307
		} elseif ( 'modified_date' === $key ) {
308
			return $this->get_date_modified();
309
		} elseif ( 'order_date' === $key ) {
310
			return $this->get_date_created();
0 ignored issues
show
Bug introduced by
The method get_date_created() does not exist on WC_Abstract_Legacy_Order. Did you maybe mean create()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
311
		} elseif ( 'id' === $key ) {
312
			return $this->get_id();
313
		} elseif ( 'post' === $key ) {
314
			return get_post( $this->get_id() );
315
		} elseif ( 'status' === $key || 'post_status' === $key ) {
316
			return $this->get_status();
317
		} elseif ( 'customer_message' === $key || 'customer_note' === $key ) {
318
			return $this->get_customer_note();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class WC_Abstract_Legacy_Order as the method get_customer_note() does only exist in the following sub-classes of WC_Abstract_Legacy_Order: WC_Order. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
319
		} elseif ( in_array( $key, array( 'user_id', 'customer_user' ) ) ) {
320
			return $this->get_customer_id();
321
		} elseif ( 'tax_display_cart' === $key ) {
322
			return get_option( 'woocommerce_tax_display_cart' );
323
		} elseif ( 'display_totals_ex_tax' === $key ) {
324
			return 'excl' === get_option( 'woocommerce_tax_display_cart' );
325
		} elseif ( 'display_cart_ex_tax' === $key ) {
326
			return 'excl' === get_option( 'woocommerce_tax_display_cart' );
327
		} elseif ( 'cart_discount' === $key ) {
328
			return $this->get_discount();
0 ignored issues
show
Bug introduced by
The method get_discount() does not seem to exist on object<WC_Abstract_Legacy_Order>.

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...
329
		} elseif ( 'cart_discount_tax' === $key ) {
330
			return $this->get_discount_tax();
331
		} elseif ( 'order_tax' === $key ) {
332
			return $this->get_cart_tax();
333
		} elseif ( 'order_shipping_tax' === $key ) {
334
			return $this->get_shipping_tax();
335
		} elseif ( 'order_shipping' === $key ) {
336
			return $this->get_shipping_total();
337
		} elseif ( 'order_total' === $key ) {
338
			return $this->get_total();
0 ignored issues
show
Bug introduced by
The method get_total() does not exist on WC_Abstract_Legacy_Order. Did you maybe mean get_total_shipping()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
339
		} elseif ( 'order_type' === $key ) {
340
			return $this->get_type();
341
		} elseif ( 'order_currency' === $key ) {
342
			return $this->get_currency();
343
		} elseif ( 'order_version' === $key ) {
344
			return $this->get_version();
345
	 	} elseif ( is_callable( array( $this, "get_{$key}" ) ) ) {
346
			return $this->{"get_{$key}"}();
347
		} else {
348
			return get_post_meta( $this->get_id(), '_' . $key, true );
349
		}
350
	}
351
352
	/**
353
	 * has_meta function for order items.
354
	 *
355
	 * @param string $order_item_id
356
	 * @return array of meta data.
357
	 */
358
	public function has_meta( $order_item_id ) {
359
		global $wpdb;
360
361
		_deprecated_function( 'has_meta', '2.7', 'WC_Order_item::get_meta_data' );
362
363
		return $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value, meta_id, order_item_id
364
			FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id = %d
365
			ORDER BY meta_id", absint( $order_item_id ) ), ARRAY_A );
366
	}
367
368
	/**
369
	 * Display meta data belonging to an item.
370
	 * @param  array $item
371
	 */
372
	public function display_item_meta( $item ) {
373
		_deprecated_function( 'get_item_meta', '2.7', 'wc_display_item_meta' );
374
		$product   = $item->get_product();
0 ignored issues
show
Bug introduced by
The method get_product cannot be called on $item (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
375
		$item_meta = new WC_Order_Item_Meta( $item, $product );
0 ignored issues
show
Deprecated Code introduced by
The class WC_Order_Item_Meta has been deprecated with message: 2.7.0 wc_display_item_meta function is used instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
376
		$item_meta->display();
377
	}
378
379
	/**
380
	 * Display download links for an order item.
381
	 * @param  array $item
382
	 */
383
	public function display_item_downloads( $item ) {
384
		$product   = $item->get_product();
0 ignored issues
show
Bug introduced by
The method get_product cannot be called on $item (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
385
386
		if ( $product && $product->exists() && $product->is_downloadable() && $this->is_download_permitted() ) {
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class WC_Abstract_Legacy_Order as the method is_download_permitted() does only exist in the following sub-classes of WC_Abstract_Legacy_Order: WC_Order. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
387
			$download_files = $this->get_item_downloads( $item );
388
			$i			  = 0;
389
			$links		  = array();
390
391
			foreach ( $download_files as $download_id => $file ) {
392
				$i++;
393
				$prefix  = count( $download_files ) > 1 ? sprintf( __( 'Download %d', 'woocommerce' ), $i ) : __( 'Download', 'woocommerce' );
394
				$links[] = '<small class="download-url">' . $prefix . ': <a href="' . esc_url( $file['download_url'] ) . '" target="_blank">' . esc_html( $file['name'] ) . '</a></small>' . "\n";
395
			}
396
397
			echo '<br/>' . implode( '<br/>', $links );
398
		}
399
	}
400
401
	/**
402
	 * Get the Download URL.
403
	 *
404
	 * @param  int $product_id
405
	 * @param  int $download_id
406
	 * @return string
407
	 */
408
	public function get_download_url( $product_id, $download_id ) {
409
		return add_query_arg( array(
410
			'download_file' => $product_id,
411
			'order'         => $this->get_order_key(),
0 ignored issues
show
Bug introduced by
The method get_order_key() does not exist on WC_Abstract_Legacy_Order. Did you maybe mean get_order()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
412
			'email'         => urlencode( $this->get_billing_email() ),
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class WC_Abstract_Legacy_Order as the method get_billing_email() does only exist in the following sub-classes of WC_Abstract_Legacy_Order: WC_Order. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
413
			'key'           => $download_id,
414
		), trailingslashit( home_url() ) );
415
	}
416
417
	/**
418
	 * Get the downloadable files for an item in this order.
419
	 *
420
	 * @param  array $item
421
	 * @return array
422
	 */
423
	public function get_item_downloads( $item ) {
424
		global $wpdb;
425
426
		$product = $item->get_product();
0 ignored issues
show
Bug introduced by
The method get_product cannot be called on $item (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
427
428
		if ( ! $product ) {
429
			/**
430
			 * $product can be `false`. Example: checking an old order, when a product or variation has been deleted.
431
			 * @see \WC_Product_Factory::get_product
432
			 */
433
			return array();
434
		}
435
		$download_ids = $wpdb->get_col( $wpdb->prepare("
436
			SELECT download_id
437
			FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions
438
			WHERE user_email = %s
439
			AND order_key = %s
440
			AND product_id = %d
441
			ORDER BY permission_id
442
		", $this->get_billing_email(), $this->get_order_key(), $product_id ) );
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class WC_Abstract_Legacy_Order as the method get_billing_email() does only exist in the following sub-classes of WC_Abstract_Legacy_Order: WC_Order. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
Bug introduced by
The method get_order_key() does not exist on WC_Abstract_Legacy_Order. Did you maybe mean get_order()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
443
444
		$files = array();
445
446
		foreach ( $download_ids as $download_id ) {
447
448
			if ( $product->has_file( $download_id ) ) {
449
				$files[ $download_id ]				 = $product->get_file( $download_id );
450
				$files[ $download_id ]['download_url'] = $this->get_download_url( $product_id, $download_id );
451
			}
452
		}
453
454
		return apply_filters( 'woocommerce_get_item_downloads', $files, $item, $this );
455
	}
456
457
	/**
458
	 * Gets shipping total. Alias of WC_Order::get_shipping_total().
459
	 * @deprecated 2.7.0 since this is an alias only.
460
	 * @return float
461
	 */
462
	public function get_total_shipping() {
463
		return $this->get_shipping_total();
464
	}
465
466
	/**
467
	 * Get order item meta.
468
	 * @deprecated 2.7.0
469
	 * @param mixed $order_item_id
470
	 * @param string $key (default: '')
471
	 * @param bool $single (default: false)
472
	 * @return array|string
473
	 */
474
	public function get_item_meta( $order_item_id, $key = '', $single = false ) {
475
		_deprecated_function( 'get_item_meta', '2.7', 'wc_get_order_item_meta' );
476
		return get_metadata( 'order_item', $order_item_id, $key, $single );
477
	}
478
479
	/**
480
	 * Get all item meta data in array format in the order it was saved. Does not group meta by key like get_item_meta().
481
	 *
482
	 * @param mixed $order_item_id
483
	 * @return array of objects
484
	 */
485
	public function get_item_meta_array( $order_item_id ) {
486
		_deprecated_function( 'get_item_meta_array', '2.7', 'WC_Order_Item::get_meta_data() (note the format has changed)' );
487
		$item            = $this->get_item( $order_item_id );
0 ignored issues
show
Bug introduced by
The method get_item() does not exist on WC_Abstract_Legacy_Order. Did you maybe mean get_item_downloads()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
488
		$meta_data       = $item->get_meta_data();
489
		$item_meta_array = array();
490
491
		foreach ( $meta_data as $meta ) {
492
			$item_meta_array[ $meta->meta_id ] = $meta;
493
		}
494
495
		return $item_meta_array;
496
	}
497
498
	/**
499
	 * Expand item meta into the $item array.
500
	 * @deprecated 2.7.0 Item meta no longer expanded due to new order item
501
	 *		classes. This function now does nothing to avoid data breakage.
502
	 * @since 2.4.0
503
	 * @param array $item before expansion.
504
	 * @return array
505
	 */
506
	public function expand_item_meta( $item ) {
507
		_deprecated_function( 'expand_item_meta', '2.7', '' );
508
		return $item;
509
	}
510
511
	/**
512
	 * Load the order object. Called from the constructor.
513
	 * @deprecated 2.7.0 Logic moved to constructor
514
	 * @param int|object|WC_Order $order Order to init.
515
	 */
516 View Code Duplication
	protected function init( $order ) {
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...
517
		_deprecated_function( 'init', '2.7', 'Logic moved to constructor' );
518
		if ( is_numeric( $order ) ) {
519
			$this->read( $order );
520
		} elseif ( $order instanceof WC_Order ) {
521
			$this->read( absint( $order->get_id() ) );
522
		} elseif ( isset( $order->ID ) ) {
523
			$this->read( absint( $order->ID ) );
524
		}
525
	}
526
527
	/**
528
	 * Gets an order from the database.
529
	 * @deprecated 2.7
530
	 * @param int $id (default: 0).
531
	 * @return bool
532
	 */
533 View Code Duplication
	public function get_order( $id = 0 ) {
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...
534
		_deprecated_function( 'get_order', '2.7', 'read' );
535
		if ( ! $id ) {
536
			return false;
537
		}
538
		if ( $result = get_post( $id ) ) {
539
			$this->populate( $result );
0 ignored issues
show
Deprecated Code introduced by
The method WC_Abstract_Legacy_Order::populate() has been deprecated with message: 2.7

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
540
			return true;
541
		}
542
		return false;
543
	}
544
545
	/**
546
	 * Populates an order from the loaded post data.
547
	 * @deprecated 2.7
548
	 * @param mixed $result
549
	 */
550
	public function populate( $result ) {
551
		_deprecated_function( 'populate', '2.7', 'read' );
552
		$this->read( $result->ID );
553
	}
554
555
	/**
556
	 * Cancel the order and restore the cart (before payment).
557
	 * @deprecated 2.7.0 Moved to event handler.
558
	 * @param string $note (default: '') Optional note to add.
559
	 */
560
	public function cancel_order( $note = '' ) {
561
		_deprecated_function( 'cancel_order', '2.7', 'update_status' );
562
		WC()->session->set( 'order_awaiting_payment', false );
563
		$this->update_status( 'cancelled', $note );
0 ignored issues
show
Bug introduced by
The method update_status() does not exist on WC_Abstract_Legacy_Order. Did you maybe mean update()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
564
	}
565
566
	/**
567
	 * Record sales.
568
	 * @deprecated 2.7.0
569
	 */
570
	public function record_product_sales() {
571
		_deprecated_function( 'record_product_sales', '2.7', 'wc_update_total_sales_counts' );
572
		wc_update_total_sales_counts( $this->get_id() );
573
	}
574
575
	/**
576
	 * Increase applied coupon counts.
577
	 * @deprecated 2.7.0
578
	 */
579
	public function increase_coupon_usage_counts() {
580
		_deprecated_function( 'increase_coupon_usage_counts', '2.7', 'wc_update_coupon_usage_counts' );
581
		wc_update_coupon_usage_counts( $this->get_id() );
582
	}
583
584
	/**
585
	 * Decrease applied coupon counts.
586
	 * @deprecated 2.7.0
587
	 */
588
	public function decrease_coupon_usage_counts() {
589
		_deprecated_function( 'decrease_coupon_usage_counts', '2.7', 'wc_update_coupon_usage_counts' );
590
		wc_update_coupon_usage_counts( $this->get_id() );
591
	}
592
593
	/**
594
	 * Reduce stock levels for all line items in the order.
595
	 * @deprecated 2.7.0
596
	 */
597
	public function reduce_order_stock() {
598
		_deprecated_function( 'reduce_order_stock', '2.7', 'wc_reduce_stock_levels' );
599
		wc_reduce_stock_levels( $this->get_id() );
600
	}
601
602
	/**
603
	 * Send the stock notifications.
604
	 * @deprecated 2.7.0 No longer needs to be called directly.
605
	 */
606
	public function send_stock_notifications( $product, $new_stock, $qty_ordered ) {
0 ignored issues
show
Unused Code introduced by
The parameter $product is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $new_stock is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $qty_ordered is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
607
		_deprecated_function( 'send_stock_notifications', '2.7' );
608
	}
609
610
	/**
611
	 * Output items for display in html emails.
612
	 * @deprecated 2.7.0 Moved to template functions.
613
	 * @param array $args Items args.
614
	 * @return string
615
	 */
616
	public function email_order_items_table( $args = array() ) {
617
		return wc_get_email_order_items( $this, $args );
0 ignored issues
show
Compatibility introduced by
$this of type object<WC_Abstract_Legacy_Order> is not a sub-type of object<WC_Order>. It seems like you assume a child class of the class WC_Abstract_Legacy_Order to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
618
	}
619
620
	/**
621
	 * Get currency.
622
	 * @deprecated 2.7.0
623
	 */
624
	public function get_order_currency() {
625
		_deprecated_function( 'get_order_currency', '2.7', 'get_currency' );
626
		return $this->get_currency();
627
	}
628
}
629