Automattic\WooCommerce\Internal\OrderReviews
SubmissionHandler::maybe_mark_order_complete
Set the completed-at meta when every eligible item has a review by this customer (approved or pending moderation), whether posted in this submission or an earlier one. Spam/trash comments are excluded.
Method of the class: SubmissionHandler{}
Hooks from the method
Returns
null. Nothing (null).
Usage
// private - for code of main (parent) class only $result = $this->maybe_mark_order_complete( $order ): void;
- $order(WC_Order) (required)
- Order being reviewed.
SubmissionHandler::maybe_mark_order_complete() SubmissionHandler::maybe mark order complete code WC 10.9.4
private function maybe_mark_order_complete( WC_Order $order ): void {
// Recording the moment the order first became fully reviewed; never overwrite.
if ( $order->get_meta( self::COMPLETED_META_KEY ) ) {
return;
}
$customer_email = $order->get_billing_email();
if ( '' === $customer_email ) {
return;
}
// Build the same eligible-row set the page uses, then collect the
// distinct (parent product, variation) slots that need a review.
// Counting by slot rather than per-line-item means a double-submit of
// the same variation can't satisfy a sibling variation's quota, and
// the same simple product appearing on multiple rows still only
// needs one review (the page collapses those rows anyway).
// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment -- documented at the page-template invocation site.
$eligible_items = (array) apply_filters( 'woocommerce_review_order_eligible_items', $order->get_items(), $order );
$required_slots = array();
$product_ids = array();
foreach ( $eligible_items as $item ) {
if ( ! $item instanceof \WC_Order_Item_Product ) {
continue;
}
$product_id = (int) $item->get_product_id();
$variation_id = (int) $item->get_variation_id();
if ( $product_id > 0 ) {
$required_slots[ $product_id . '|' . $variation_id ] = true;
$product_ids[ $product_id ] = $product_id;
}
}
if ( empty( $required_slots ) ) {
return;
}
// Single grouped lookup, fetching the comment objects directly so we
// can read comment_post_ID without a follow-up query per row. Limit
// to approved + pending-moderation so spam/trash never count as
// completion, AND to reviews tagged with this order so an older
// review of the same parent product from a previous order doesn't
// satisfy the per-row count for the current one. number=>0 disables
// the default 20-row cap so this still works for orders with many
// reviewable items.
$comments = get_comments(
array(
'post__in' => array_values( $product_ids ),
'author_email' => $customer_email,
'type' => 'review',
'status' => array( 'approve', 'hold' ),
'number' => 0,
'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- bounded by post__in + author_email.
array(
'key' => ItemEligibility::ORDER_META_KEY,
'value' => (string) $order->get_id(),
),
),
)
);
if ( ! is_array( $comments ) || empty( $comments ) ) {
return;
}
// Index reviewed slots by (parent_id, variation_id); duplicate comments
// for the same slot still count as one toward completion.
$reviewed_slots = array();
foreach ( $comments as $comment ) {
if ( $comment instanceof \WP_Comment ) {
$slot_key = (int) $comment->comment_post_ID . '|' . (int) get_comment_meta( (int) $comment->comment_ID, ItemEligibility::VARIATION_META_KEY, true );
$reviewed_slots[ $slot_key ] = true;
}
}
foreach ( $required_slots as $slot_key => $_ ) {
if ( ! isset( $reviewed_slots[ $slot_key ] ) ) {
return;
}
}
$order->update_meta_data( self::COMPLETED_META_KEY, (string) time() );
$order->save();
}