Commit 4206f87a3d0 for woocommerce
commit 4206f87a3d0b922b92e5cb715b52308e9d1cf46a
Author: Marin Atanasov <8436925+tyxla@users.noreply.github.com>
Date: Thu Mar 26 00:20:54 2026 +0900
Fix `get_item_downloads()` not always returning an `array` (#63816)
* Fix get_item_downloads() not always returning an array
After #61518, get_item_downloads() could implicitly return null when
the product or order does not exist. Ensure the method always returns
the initialized empty array when the early conditions are not met.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add changefile(s) from automation for the following project(s): woocommerce
* Update phpstan baseline
* Early return when no downloads
* Add extra defensive check for filtered value
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: woocommercebot <woocommercebot@users.noreply.github.com>
diff --git a/plugins/woocommerce/changelog/63816-fix-get-item-downloads-return-array b/plugins/woocommerce/changelog/63816-fix-get-item-downloads-return-array
new file mode 100644
index 00000000000..e12810e9552
--- /dev/null
+++ b/plugins/woocommerce/changelog/63816-fix-get-item-downloads-return-array
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+Comment: Fix `get_item_downloads()` not always returning an `array`
+
diff --git a/plugins/woocommerce/includes/class-wc-order-item-product.php b/plugins/woocommerce/includes/class-wc-order-item-product.php
index 4de34de8e3b..917e0edc4c6 100644
--- a/plugins/woocommerce/includes/class-wc-order-item-product.php
+++ b/plugins/woocommerce/includes/class-wc-order-item-product.php
@@ -431,47 +431,55 @@ class WC_Order_Item_Product extends WC_Order_Item {
$order = $this->get_order();
$product_id = $this->get_variation_id() ? $this->get_variation_id() : $this->get_product_id();
- if ( $product && $order && $product->is_downloadable() && $order->is_download_permitted() ) {
- $email_hash = function_exists( 'hash' ) ? hash( 'sha256', $order->get_billing_email() ) : sha1( $order->get_billing_email() );
- $data_store = WC_Data_Store::load( 'customer-download' );
- $customer_downloads = $data_store->get_downloads(
- array(
- 'user_email' => $order->get_billing_email(),
- 'order_id' => $order->get_id(),
- 'product_id' => $product_id,
- )
- );
- foreach ( $customer_downloads as $customer_download ) {
- $download_id = $customer_download->get_download_id();
-
- if ( $product->has_file( $download_id ) ) {
- $file = $product->get_file( $download_id );
- $files[ $download_id ] = $file->get_data();
- $files[ $download_id ]['downloads_remaining'] = $customer_download->get_downloads_remaining();
- $files[ $download_id ]['access_expires'] = $customer_download->get_access_expires();
- $files[ $download_id ]['download_url'] = add_query_arg(
- array(
- 'download_file' => $product_id,
- 'order' => $order->get_order_key(),
- 'uid' => $email_hash,
- 'key' => $download_id,
- ),
- trailingslashit( home_url() )
- );
- }
+ if ( ! $product || ! $order || ! $product->is_downloadable() || ! $order->is_download_permitted() ) {
+ return array();
+ }
+
+ $email_hash = function_exists( 'hash' ) ? hash( 'sha256', $order->get_billing_email() ) : sha1( $order->get_billing_email() );
+ $data_store = WC_Data_Store::load( 'customer-download' );
+ $customer_downloads = $data_store->get_downloads(
+ array(
+ 'user_email' => $order->get_billing_email(),
+ 'order_id' => $order->get_id(),
+ 'product_id' => $product_id,
+ )
+ );
+ foreach ( $customer_downloads as $customer_download ) {
+ $download_id = $customer_download->get_download_id();
+
+ if ( $product->has_file( $download_id ) ) {
+ $file = $product->get_file( $download_id );
+ $files[ $download_id ] = $file->get_data();
+ $files[ $download_id ]['downloads_remaining'] = $customer_download->get_downloads_remaining();
+ $files[ $download_id ]['access_expires'] = $customer_download->get_access_expires();
+ $files[ $download_id ]['download_url'] = add_query_arg(
+ array(
+ 'download_file' => $product_id,
+ 'order' => $order->get_order_key(),
+ 'uid' => $email_hash,
+ 'key' => $download_id,
+ ),
+ trailingslashit( home_url() )
+ );
}
+ }
- /**
- * Filters the list of downloadable files for an order item.
- *
- * @since 2.7.0
- *
- * @param array $files Array of downloadable file data.
- * @param WC_Order_Item_Product $item The order item product object.
- * @param WC_Order $order The order object.
- */
- return apply_filters( 'woocommerce_get_item_downloads', $files, $this, $order );
+ /**
+ * Filters the list of downloadable files for an order item.
+ *
+ * @since 2.7.0
+ *
+ * @param array $files Array of downloadable file data.
+ * @param WC_Order_Item_Product $item The order item product object.
+ * @param WC_Order $order The order object.
+ */
+ $files = apply_filters( 'woocommerce_get_item_downloads', $files, $this, $order );
+
+ if ( ! is_array( $files ) ) {
+ return array();
}
+
+ return $files;
}
/**
diff --git a/plugins/woocommerce/phpstan-baseline.neon b/plugins/woocommerce/phpstan-baseline.neon
index 9f56a27909d..a6cfa0d0613 100644
--- a/plugins/woocommerce/phpstan-baseline.neon
+++ b/plugins/woocommerce/phpstan-baseline.neon
@@ -12840,12 +12840,6 @@ parameters:
count: 1
path: includes/class-wc-order-item-product.php
- -
- message: '#^Method WC_Order_Item_Product\:\:get_item_downloads\(\) should return array but return statement is missing\.$#'
- identifier: return.missing
- count: 1
- path: includes/class-wc-order-item-product.php
-
-
message: '#^Method WC_Order_Item_Product\:\:set_backorder_meta\(\) has no return type specified\.$#'
identifier: missingType.return