Completed
Push — master ( 63fb13...1c592b )
by Mike
22:09
created

WC_Abstract_Legacy_Order::cancel_order()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
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
	 * @param object|int $item order item ID or item object.
25
	 * @param WC_Product $product
26
	 * @param array $args data to update.
27
	 * @return int updated order item ID
28
	 */
29
	 public function update_product( $item, $product, $args ) {
30
		_deprecated_function( 'WC_Order::update_product', '2.7', 'Interact with WC_Order_Item_Product class' );
31
		if ( is_numeric( $item ) ) {
32
			$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...
33
		}
34
		if ( ! is_object( $item ) || ! $item->is_type( 'line_item' ) ) {
35
			return false;
36
		}
37
		if ( ! $this->get_id() ) {
38
			$this->save(); // Order must exist
39
		}
40
41
		// BW compatibility with old args
42 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...
43
			foreach ( $args['totals'] as $key => $value ) {
44
				if ( 'tax' === $key ) {
45
					$args['total_tax'] = $value;
46
				} elseif ( 'tax_data' === $key ) {
47
					$args['taxes'] = $value;
48
				} else {
49
					$args[ $key ] = $value;
50
				}
51
			}
52
		}
53
54
		// Handly qty if set
55
		if ( isset( $args['qty'] ) ) {
56 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...
57
				$item->add_meta_data( apply_filters( 'woocommerce_backordered_item_meta_name', __( 'Backordered', 'woocommerce' ) ), $args['qty'] - max( 0, $product->get_total_stock() ), true );
58
			}
59
			$args['subtotal'] = $args['subtotal'] ? $args['subtotal'] : $product->get_price_excluding_tax( $args['qty'] );
60
			$args['total']	= $args['total'] ? $args['total'] : $product->get_price_excluding_tax( $args['qty'] );
61
		}
62
63
		$item->set_order_id( $this->get_id() );
64
		$item->set_all( $args );
65
		$item->save();
66
		do_action( 'woocommerce_order_edit_product', $this->get_id(), $item->get_id(), $args, $product );
67
68
		return $item->get_id();
69
	}
70
71
	/**
72
	 * Update coupon for order. Note this does not update order totals.
73
	 * @param object|int $item
74
	 * @param array $args
75
	 * @return int updated order item ID
76
	 */
77
	public function update_coupon( $item, $args ) {
78
		_deprecated_function( 'WC_Order::update_coupon', '2.7', 'Interact with WC_Order_Item_Coupon class' );
79
		if ( is_numeric( $item ) ) {
80
			$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...
81
		}
82
		if ( ! is_object( $item ) || ! $item->is_type( 'coupon' ) ) {
83
			return false;
84
		}
85
		if ( ! $this->get_id() ) {
86
			$this->save(); // Order must exist
87
		}
88
89
		// BW compatibility for old args
90
		if ( isset( $args['discount_amount'] ) ) {
91
			$args['discount'] = $args['discount_amount'];
92
		}
93
		if ( isset( $args['discount_amount_tax'] ) ) {
94
			$args['discount_tax'] = $args['discount_amount_tax'];
95
		}
96
97
		$item->set_order_id( $this->get_id() );
98
		$item->set_all( $args );
99
		$item->save();
100
101
		do_action( 'woocommerce_order_update_coupon', $this->get_id(), $item->get_id(), $args );
102
103
		return $item->get_id();
104
	}
105
106
	/**
107
	 * Update shipping method for order.
108
	 *
109
	 * Note this does not update the order total.
110
	 *
111
	 * @param object|int $item
112
	 * @param array $args
113
	 * @return int updated order item ID
114
	 */
115
	public function update_shipping( $item, $args ) {
116
		_deprecated_function( 'WC_Order::update_shipping', '2.7', 'Interact with WC_Order_Item_Shipping class' );
117
		if ( is_numeric( $item ) ) {
118
			$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...
119
		}
120
		if ( ! is_object( $item ) || ! $item->is_type( 'shipping' ) ) {
121
			return false;
122
		}
123
		if ( ! $this->get_id() ) {
124
			$this->save(); // Order must exist
125
		}
126
127
		// BW compatibility for old args
128
		if ( isset( $args['cost'] ) ) {
129
			$args['total'] = $args['cost'];
130
		}
131
132
		$item->set_order_id( $this->get_id() );
133
		$item->set_all( $args );
134
		$item->save();
135
		$this->calculate_shipping();
136
137
		do_action( 'woocommerce_order_update_shipping', $this->get_id(), $item->get_id(), $args );
138
139
		return $item->get_id();
140
	}
141
142
	/**
143
	 * Update fee for order.
144
	 *
145
	 * Note this does not update order totals.
146
	 *
147
	 * @param object|int $item
148
	 * @param array $args
149
	 * @return int updated order item ID
150
	 */
151 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...
152
		_deprecated_function( 'WC_Order::update_fee', '2.7', 'Interact with WC_Order_Item_Fee class' );
153
		if ( is_numeric( $item ) ) {
154
			$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...
155
		}
156
		if ( ! is_object( $item ) || ! $item->is_type( 'fee' ) ) {
157
			return false;
158
		}
159
		if ( ! $this->get_id() ) {
160
			$this->save(); // Order must exist
161
		}
162
163
		$item->set_order_id( $this->get_id() );
164
		$item->set_all( $args );
165
		$item->save();
166
167
		do_action( 'woocommerce_order_update_fee', $this->get_id(), $item->get_id(), $args );
168
169
		return $item->get_id();
170
	}
171
172
	/**
173
	 * Update tax line on order.
174
	 * Note this does not update order totals.
175
	 *
176
	 * @since 2.7
177
	 * @param object|int $item
178
	 * @param array $args
179
	 * @return int updated order item ID
180
	 */
181 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...
182
		_deprecated_function( 'WC_Order::update_tax', '2.7', 'Interact with WC_Order_Item_Tax class' );
183
		if ( is_numeric( $item ) ) {
184
			$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...
185
		}
186
		if ( ! is_object( $item ) || ! $item->is_type( 'tax' ) ) {
187
			return false;
188
		}
189
		if ( ! $this->get_id() ) {
190
			$this->save(); // Order must exist
191
		}
192
193
		$item->set_order_id( $this->get_id() );
194
		$item->set_all( $args );
195
		$item->save();
196
197
		do_action( 'woocommerce_order_update_tax', $this->get_id(), $item->get_id(), $args );
198
199
		return $item->get_id();
200
	}
201
202
	/**
203
	 * Get a product (either product or variation).
204
	 * @deprecated Add deprecation notices in future release. Replaced with $item->get_product()
205
	 * @param object $item
206
	 * @return WC_Product|bool
207
	 */
208
	public function get_product_from_item( $item ) {
209
		if ( is_callable( array( $item, 'get_product' ) ) ) {
210
			$product = $item->get_product();
211
		} else {
212
			$product = false;
213
		}
214
		return apply_filters( 'woocommerce_get_product_from_item', $product, $item, $this );
215
	}
216
217
	/**
218
	 * Set the customer address.
219
	 * @param array $address Address data.
220
	 * @param string $type billing or shipping.
221
	 */
222
	public function set_address( $address, $type = 'billing' ) {
223
		foreach ( $address as $key => $value ) {
224
			update_post_meta( $this->get_id(), "_{$type}_" . $key, $value );
225 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...
226
				$this->{"set_{$type}_{$key}"}( $value );
227
			}
228
		}
229
	}
230
231
	/**
232
	 * Set an order total.
233
	 * @param float $amount
234
	 * @param string $total_type
235
	 * @return bool
236
	 */
237
	public function legacy_set_total( $amount, $total_type = 'total' ) {
238
		if ( ! in_array( $total_type, array( 'shipping', 'tax', 'shipping_tax', 'total', 'cart_discount', 'cart_discount_tax' ) ) ) {
239
			return false;
240
		}
241
242
		switch ( $total_type ) {
243
			case 'total' :
244
				$amount = wc_format_decimal( $amount, wc_get_price_decimals() );
245
				$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...
246
				update_post_meta( $this->get_id(), '_order_total', $amount );
247
				break;
248
			case 'cart_discount' :
249
				$amount = wc_format_decimal( $amount );
250
				$this->set_discount_total( $amount );
251
				update_post_meta( $this->get_id(), '_cart_discount', $amount );
252
				break;
253
			case 'cart_discount_tax' :
254
				$amount = wc_format_decimal( $amount );
255
				$this->set_discount_tax( $amount );
256
				update_post_meta( $this->get_id(), '_cart_discount_tax', $amount );
257
				break;
258
			case 'shipping' :
259
				$amount = wc_format_decimal( $amount );
260
				$this->set_shipping_total( $amount );
261
				update_post_meta( $this->get_id(), '_order_shipping', $amount );
262
				break;
263
			case 'shipping_tax' :
264
				$amount = wc_format_decimal( $amount );
265
				$this->set_shipping_tax( $amount );
266
				update_post_meta( $this->get_id(), '_order_shipping_tax', $amount );
267
				break;
268
			case 'tax' :
269
				$amount = wc_format_decimal( $amount );
270
				$this->set_cart_tax( $amount );
271
				update_post_meta( $this->get_id(), '_order_tax', $amount );
272
				break;
273
		}
274
275
		return true;
276
	}
277
278
	/**
279
	 * Magic __isset method for backwards compatibility.
280
	 * @param string $key
281
	 * @return bool
282
	 */
283
	public function __isset( $key ) {
284
		// Legacy properties which could be accessed directly in the past.
285
		$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' );
286
		return $this->get_id() ? ( in_array( $key, $legacy_props ) || metadata_exists( 'post', $this->get_id(), '_' . $key ) ) : false;
287
	}
288
289
	/**
290
	 * Magic __get method for backwards compatibility.
291
	 * @param string $key
292
	 * @return mixed
293
	 */
294
	public function __get( $key ) {
295
		_doing_it_wrong( $key, 'Order properties should not be accessed directly.', '2.7' );
296
297
		if ( 'completed_date' === $key ) {
298
			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...
299
		} elseif ( 'paid_date' === $key ) {
300
			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...
301
		} elseif ( 'modified_date' === $key ) {
302
			return $this->get_date_modified();
303
		} elseif ( 'order_date' === $key ) {
304
			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...
305
		} elseif ( 'id' === $key ) {
306
			return $this->get_id();
307
		} elseif ( 'post' === $key ) {
308
			return get_post( $this->get_id() );
309
		} elseif ( 'status' === $key || 'post_status' === $key ) {
310
			return $this->get_status();
311
		} elseif ( 'customer_message' === $key || 'customer_note' === $key ) {
312
			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...
313
		} elseif ( in_array( $key, array( 'user_id', 'customer_user' ) ) ) {
314
			return $this->get_customer_id();
315
		} elseif ( 'tax_display_cart' === $key ) {
316
			return get_option( 'woocommerce_tax_display_cart' );
317
		} elseif ( 'display_totals_ex_tax' === $key ) {
318
			return 'excl' === get_option( 'woocommerce_tax_display_cart' );
319
		} elseif ( 'display_cart_ex_tax' === $key ) {
320
			return 'excl' === get_option( 'woocommerce_tax_display_cart' );
321
		} elseif ( 'cart_discount' === $key ) {
322
			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...
323
		} elseif ( 'cart_discount_tax' === $key ) {
324
			return $this->get_discount_tax();
325
		} elseif ( 'order_tax' === $key ) {
326
			return $this->get_cart_tax();
327
		} elseif ( 'order_shipping_tax' === $key ) {
328
			return $this->get_shipping_tax();
329
		} elseif ( 'order_shipping' === $key ) {
330
			return $this->get_shipping_total();
331
		} elseif ( 'order_total' === $key ) {
332
			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...
333
		} elseif ( 'order_type' === $key ) {
334
			return $this->get_type();
335
		} elseif ( 'order_currency' === $key ) {
336
			return $this->get_currency();
337
		} elseif ( 'order_version' === $key ) {
338
			return $this->get_version();
339
	 	} elseif ( is_callable( array( $this, "get_{$key}" ) ) ) {
340
			return $this->{"get_{$key}"}();
341
		} else {
342
			return get_post_meta( $this->get_id(), '_' . $key, true );
343
		}
344
	}
345
346
	/**
347
	 * has_meta function for order items.
348
	 *
349
	 * @param string $order_item_id
350
	 * @return array of meta data.
351
	 */
352
	public function has_meta( $order_item_id ) {
353
		global $wpdb;
354
355
		_deprecated_function( 'has_meta', '2.7', 'WC_Order_item::get_meta_data' );
356
357
		return $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value, meta_id, order_item_id
358
			FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id = %d
359
			ORDER BY meta_id", absint( $order_item_id ) ), ARRAY_A );
360
	}
361
362
	/**
363
	 * Display meta data belonging to an item.
364
	 * @param  array $item
365
	 */
366
	public function display_item_meta( $item ) {
367
		_deprecated_function( 'get_item_meta', '2.7', 'wc_display_item_meta' );
368
		$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...
369
		$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...
370
		$item_meta->display();
371
	}
372
373
	/**
374
	 * Display download links for an order item.
375
	 * @param  array $item
376
	 */
377
	public function display_item_downloads( $item ) {
378
		_deprecated_function( 'display_item_downloads', '2.7', 'wc_display_item_downloads' );
379
		$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...
380
381
		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...
382
			$download_files = $this->get_item_downloads( $item );
383
			$i			  = 0;
384
			$links		  = array();
385
386
			foreach ( $download_files as $download_id => $file ) {
387
				$i++;
388
				$prefix  = count( $download_files ) > 1 ? sprintf( __( 'Download %d', 'woocommerce' ), $i ) : __( 'Download', 'woocommerce' );
389
				$links[] = '<small class="download-url">' . $prefix . ': <a href="' . esc_url( $file['download_url'] ) . '" target="_blank">' . esc_html( $file['name'] ) . '</a></small>' . "\n";
390
			}
391
392
			echo '<br/>' . implode( '<br/>', $links );
393
		}
394
	}
395
396
	/**
397
	 * Get the Download URL.
398
	 *
399
	 * @param  int $product_id
400
	 * @param  int $download_id
401
	 * @return string
402
	 */
403
	public function get_download_url( $product_id, $download_id ) {
404
		_deprecated_function( 'get_download_url', '2.7', 'WC_Order_Item_Product::get_item_download_url' );
405
		return add_query_arg( array(
406
			'download_file' => $product_id,
407
			'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...
408
			'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...
409
			'key'           => $download_id,
410
		), trailingslashit( home_url() ) );
411
	}
412
413
	/**
414
	 * Get the downloadable files for an item in this order.
415
	 *
416
	 * @param  array $item
417
	 * @return array
418
	 */
419
	public function get_item_downloads( $item ) {
420
		_deprecated_function( 'get_item_downloads', '2.7', 'WC_Order_Item_Product::get_item_downloads' );
421
		return $item->get_item_downloads();
0 ignored issues
show
Bug introduced by
The method get_item_downloads 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...
422
	}
423
424
	/**
425
	 * Gets shipping total. Alias of WC_Order::get_shipping_total().
426
	 * @deprecated 2.7.0 since this is an alias only.
427
	 * @return float
428
	 */
429
	public function get_total_shipping() {
430
		return $this->get_shipping_total();
431
	}
432
433
	/**
434
	 * Get order item meta.
435
	 * @deprecated 2.7.0
436
	 * @param mixed $order_item_id
437
	 * @param string $key (default: '')
438
	 * @param bool $single (default: false)
439
	 * @return array|string
440
	 */
441
	public function get_item_meta( $order_item_id, $key = '', $single = false ) {
442
		_deprecated_function( 'get_item_meta', '2.7', 'wc_get_order_item_meta' );
443
		return get_metadata( 'order_item', $order_item_id, $key, $single );
444
	}
445
446
	/**
447
	 * Get all item meta data in array format in the order it was saved. Does not group meta by key like get_item_meta().
448
	 *
449
	 * @param mixed $order_item_id
450
	 * @return array of objects
451
	 */
452
	public function get_item_meta_array( $order_item_id ) {
453
		_deprecated_function( 'get_item_meta_array', '2.7', 'WC_Order_Item::get_meta_data() (note the format has changed)' );
454
		$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...
455
		$meta_data       = $item->get_meta_data();
456
		$item_meta_array = array();
457
458
		foreach ( $meta_data as $meta ) {
459
			$item_meta_array[ $meta->meta_id ] = $meta;
460
		}
461
462
		return $item_meta_array;
463
	}
464
465
	/**
466
	 * Expand item meta into the $item array.
467
	 * @deprecated 2.7.0 Item meta no longer expanded due to new order item
468
	 *		classes. This function now does nothing to avoid data breakage.
469
	 * @param array $item before expansion.
470
	 * @return array
471
	 */
472
	public function expand_item_meta( $item ) {
473
		_deprecated_function( 'expand_item_meta', '2.7', '' );
474
		return $item;
475
	}
476
477
	/**
478
	 * Load the order object. Called from the constructor.
479
	 * @deprecated 2.7.0 Logic moved to constructor
480
	 * @param int|object|WC_Order $order Order to init.
481
	 */
482 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...
483
		_deprecated_function( 'init', '2.7', 'Logic moved to constructor' );
484
		if ( is_numeric( $order ) ) {
485
			$this->read( $order );
486
		} elseif ( $order instanceof WC_Order ) {
487
			$this->read( absint( $order->get_id() ) );
488
		} elseif ( isset( $order->ID ) ) {
489
			$this->read( absint( $order->ID ) );
490
		}
491
	}
492
493
	/**
494
	 * Gets an order from the database.
495
	 * @deprecated 2.7
496
	 * @param int $id (default: 0).
497
	 * @return bool
498
	 */
499 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...
500
		_deprecated_function( 'get_order', '2.7', 'read' );
501
		if ( ! $id ) {
502
			return false;
503
		}
504
		if ( $result = get_post( $id ) ) {
505
			$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...
506
			return true;
507
		}
508
		return false;
509
	}
510
511
	/**
512
	 * Populates an order from the loaded post data.
513
	 * @deprecated 2.7
514
	 * @param mixed $result
515
	 */
516
	public function populate( $result ) {
517
		_deprecated_function( 'populate', '2.7', 'read' );
518
		$this->read( $result->ID );
519
	}
520
521
	/**
522
	 * Cancel the order and restore the cart (before payment).
523
	 * @deprecated 2.7.0 Moved to event handler.
524
	 * @param string $note (default: '') Optional note to add.
525
	 */
526
	public function cancel_order( $note = '' ) {
527
		_deprecated_function( 'cancel_order', '2.7', 'update_status' );
528
		WC()->session->set( 'order_awaiting_payment', false );
529
		$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...
530
	}
531
532
	/**
533
	 * Record sales.
534
	 * @deprecated 2.7.0
535
	 */
536
	public function record_product_sales() {
537
		_deprecated_function( 'record_product_sales', '2.7', 'wc_update_total_sales_counts' );
538
		wc_update_total_sales_counts( $this->get_id() );
539
	}
540
541
	/**
542
	 * Increase applied coupon counts.
543
	 * @deprecated 2.7.0
544
	 */
545
	public function increase_coupon_usage_counts() {
546
		_deprecated_function( 'increase_coupon_usage_counts', '2.7', 'wc_update_coupon_usage_counts' );
547
		wc_update_coupon_usage_counts( $this->get_id() );
548
	}
549
550
	/**
551
	 * Decrease applied coupon counts.
552
	 * @deprecated 2.7.0
553
	 */
554
	public function decrease_coupon_usage_counts() {
555
		_deprecated_function( 'decrease_coupon_usage_counts', '2.7', 'wc_update_coupon_usage_counts' );
556
		wc_update_coupon_usage_counts( $this->get_id() );
557
	}
558
559
	/**
560
	 * Reduce stock levels for all line items in the order.
561
	 * @deprecated 2.7.0
562
	 */
563
	public function reduce_order_stock() {
564
		_deprecated_function( 'reduce_order_stock', '2.7', 'wc_reduce_stock_levels' );
565
		wc_reduce_stock_levels( $this->get_id() );
566
	}
567
568
	/**
569
	 * Send the stock notifications.
570
	 * @deprecated 2.7.0 No longer needs to be called directly.
571
	 */
572
	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...
573
		_deprecated_function( 'send_stock_notifications', '2.7' );
574
	}
575
576
	/**
577
	 * Output items for display in html emails.
578
	 * @deprecated 2.7.0 Moved to template functions.
579
	 * @param array $args Items args.
580
	 * @return string
581
	 */
582
	public function email_order_items_table( $args = array() ) {
583
		_deprecated_function( 'email_order_items_table', '2.7', 'wc_get_email_order_items' );
584
		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...
585
	}
586
587
	/**
588
	 * Get currency.
589
	 * @deprecated 2.7.0
590
	 */
591
	public function get_order_currency() {
592
		_deprecated_function( 'get_order_currency', '2.7', 'get_currency' );
593
		return apply_filters( 'woocommerce_get_order_currency', $this->get_currency(), $this );
594
	}
595
}
596