Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ phpcs-report.txt
!/assets/css/vue-vendor.css
!/assets/css/vue-frontend.css
!/assets/css/wp-version-before-5-3.css
.vscode
78 changes: 45 additions & 33 deletions includes/REST/OrderControllerV2.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace WeDevs\Dokan\REST;

use WC_Customer_Download;
use WC_Data_Store;
use WP_Error;
use WP_REST_Server;
Expand Down Expand Up @@ -59,6 +60,16 @@ public function register_routes() {
'required' => true,
],
],
'download_remaining' => [
'type' => 'integer',
'description' => __( 'Download remaining.', 'dokan-lite' ),
'required' => false,
],
'access_expires' => [
'type' => 'string',
'description' => __( 'Access expires.', 'dokan-lite' ),
'required' => false,
],
],
],
[
Expand Down Expand Up @@ -125,10 +136,6 @@ public function register_routes() {
public function get_order_downloads( $request ) {
global $wpdb;

$user_id = dokan_get_current_user_id();
$data = [];
$downloads = [];

$download_permissions = $wpdb->get_results(
$wpdb->prepare(
"
Expand All @@ -138,38 +145,27 @@ public function get_order_downloads( $request ) {
)
);

$product_ids = wp_list_pluck( $download_permissions, 'product_id' );
$product_ids = array_unique( $product_ids );

$products = wc_get_products(
[
'include' => $product_ids,
]
);

$existing_product_ids = wp_list_pluck( $products, 'id' );
$product_ids = array_unique( wp_list_pluck( $download_permissions, 'product_id' ) );

$downloads = array_filter(
$download_permissions,
function ( $download ) use ( $existing_product_ids ) {
return in_array( $download->product_id, $existing_product_ids );
// Create a lookup map for products by ID.
$products = [];
foreach ( $product_ids as $product_id ) {
$product = wc_get_product( $product_id );
if ( ! $product ) {
continue;
}
);
$products[ $product_id ] = $product;
}

$downloads = array_map(
function ( $download ) use ( $products, $request ) {
$filter_items = array_filter(
$products,
function ( $product ) use ( $download ) {
return $product->get_id() === intval( $download->product_id );
}
);
$download->product = reset( $filter_items );

return $this->prepare_data_for_response( $download, $request );
},
$downloads
);
// Filter downloads with existing products and prepare response.
$downloads = [];
foreach ( $download_permissions as $download ) {
$product_id = intval( $download->product_id );
if ( isset( $products_by_id[ $product_id ] ) ) {
$download->product = $products[ $product_id ];
$downloads[] = $this->prepare_data_for_response( $download, $request );
}
}
Comment on lines +160 to +168
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical bug: Undefined variable $products_by_id causes empty results.

Line 164 references $products_by_id but the lookup map is stored in $products (line 151-157). This condition will always evaluate to false since $products_by_id is undefined, resulting in an empty $downloads array.

🐛 Proposed fix
         // Filter downloads with existing products and prepare response.
         $downloads = [];
         foreach ( $download_permissions as $download ) {
             $product_id = intval( $download->product_id );
-            if ( isset( $products_by_id[ $product_id ] ) ) {
+            if ( isset( $products[ $product_id ] ) ) {
                 $download->product = $products[ $product_id ];
                 $downloads[] = $this->prepare_data_for_response( $download, $request );
             }
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Filter downloads with existing products and prepare response.
$downloads = [];
foreach ( $download_permissions as $download ) {
$product_id = intval( $download->product_id );
if ( isset( $products_by_id[ $product_id ] ) ) {
$download->product = $products[ $product_id ];
$downloads[] = $this->prepare_data_for_response( $download, $request );
}
}
// Filter downloads with existing products and prepare response.
$downloads = [];
foreach ( $download_permissions as $download ) {
$product_id = intval( $download->product_id );
if ( isset( $products[ $product_id ] ) ) {
$download->product = $products[ $product_id ];
$downloads[] = $this->prepare_data_for_response( $download, $request );
}
}
🧰 Tools
🪛 PHPMD (2.15.0)

164-164: Avoid unused local variables such as '$products_by_id'. (undefined)

(UnusedLocalVariable)

🤖 Prompt for AI Agents
In `@includes/REST/OrderControllerV2.php` around lines 160 - 168, The bug is that
the loop in OrderControllerV2 filtering downloads checks an undefined
$products_by_id, causing all items to be skipped; update the condition to check
the existing lookup map $products (i.e., replace
isset($products_by_id[$product_id]) with isset($products[$product_id])) and keep
the subsequent assignment $download->product = $products[$product_id] so
downloads are correctly collected and prepared for response in the same method.


$data = $this->format_downloads_data( $downloads, $products );

Expand Down Expand Up @@ -230,6 +226,8 @@ public function prepare_data_for_response( $download, $request ) {
public function grant_order_downloads( $requests ) {
$order_id = intval( $requests->get_param( 'id' ) );
$product_ids = array_filter( array_map( 'absint', (array) wp_unslash( $requests->get_param( 'ids' ) ) ) );
$remaining = $requests->get_param( 'download_remaining' );
$expiry = $requests->get_param( 'access_expires' );
$file_counter = 0;
$order = dokan()->order->get( $order_id );
$data = [];
Expand All @@ -244,6 +242,20 @@ public function grant_order_downloads( $requests ) {

foreach ( $files as $download_id => $file ) {
$inserted_id = wc_downloadable_file_permission( $download_id, $product_id, $order );
if ( ! $inserted_id ) {
continue;
}

$download = new WC_Customer_Download( $inserted_id );
if ( $download ) {
if ( $remaining ) {
$download->set_downloads_remaining( $remaining );
}
if ( $expiry ) {
$download->set_access_expires( $expiry );
}
$download->save();
}

if ( $inserted_id ) {
++$file_counter;
Expand Down
34 changes: 19 additions & 15 deletions includes/REST/OrderControllerV3.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,25 @@ function ( $download ) use ( $products ) {
return ! empty( $product_item->get_id() ) && ! empty( $download->product_id ) && absint( $product_item->get_id() ) === absint( $download->product_id );
}
);
$product = reset( $product );

$download->product = [
'id' => $product->get_id(),
'name' => $product->get_name(),
'slug' => $product->get_slug(),
'link' => $product->get_permalink(),
];

/**
* @var $file \WC_Product_Download
*/
$file = $product->get_file( $download->download_id );
$download->file_data = $file->get_data();
$download->file_data['file_title'] = wc_get_filename_from_url( $product->get_file_download_path( $download->download_id ) );
$product = ! empty( $product ) ? reset( $product ) : null;

if ( $product ) {
$download->product = [
'id' => $product->get_id(),
'name' => $product->get_name(),
'slug' => $product->get_slug(),
'link' => $product->get_permalink(),
];

/**
* @var \WC_Product_Download|false $file
*/
$file = $product->get_file( $download->download_id );
if ( $file instanceof \WC_Product_Download ) {
$download->file_data = $file->get_data();
$download->file_data['file_title'] = wc_get_filename_from_url( $product->get_file_download_path( $download->download_id ) );
}
}

return $download;
},
Expand Down
Loading