Conversation
Testing GuidelinesHi @Konamiman @woocommerce/flux, Apart from reviewing the code changes, please make sure to review the testing instructions (Guide) and verify that relevant tests (E2E, Unit, Integration, etc.) have been added or updated as needed. Reminder: PR reviewers are required to document testing performed. This includes:
|
Test using WordPress PlaygroundThe changes in this pull request can be previewed and tested using a WordPress Playground instance. Test this pull request with WordPress Playground. Note that this URL is valid for 30 days from when this comment was last updated. You can update it by closing/reopening the PR or pushing a new commit. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughpersist_order_to_db now signals whether CoGS was changed via the order API; save_cogs_data uses the original stored CoGS value (pre-filter) and only writes or deletes the Changes
Sequence Diagram(s)sequenceDiagram
participant Checkout as Checkout / Caller
participant DataStore as OrdersTableDataStore
participant Filters as WP Filters
participant DB as Database
Checkout->>DataStore: persist_order_to_db($order, $changes)
DataStore->>DataStore: compute $cogs_value_changed = ! $only_changes || array_key_exists('cogs_total_value',$changes)
DataStore->>DataStore: $cogs_value_original = get_meta('_cogs_total_value') // pre-filter
DataStore->>Filters: apply_filters('woocommerce_cogs_total_value', $cogs_value_original, $order)
Filters-->>DataStore: $cogs_value_filtered
DataStore->>DataStore: $sync_meta = $cogs_value_changed || ($cogs_value_original !== (float)$cogs_value_filtered)
alt $sync_meta == true
DataStore->>DB: update or delete `_cogs_total_value` meta
else $sync_meta == false
DataStore-->>Checkout: skip meta write
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php (1)
2167-2175: Missing(float)cast on$cogs_valueafter the null check — inconsistent with item-level counterpartThe item-level
save_cogs_datainabstract-wc-order-item-type-data-store.phpexplicitly casts after the null check:$cogs_value = (float) $cogs_value;This method omits that cast. There are two downstream consequences:
Line 2172 —
$sync_metastrict-comparison (!==) may fire spuriously. If the filter returns anintorstringthat is numerically equal to$cogs_value_original, PHP's!==treats them as unequal (type mismatch), setting$sync_meta = trueand triggering an unnecessary DB write — defeating the optimisation.Line 2175 —
0.0 === $cogs_valuestrict-comparison may miss the delete branch. If the filter returns0(int) instead of0.0(float), the delete branch is skipped; the code falls through to the update or add branch, storing the wrong type and leaving a stale meta row instead of removing it.Both issues are guarded by the
@param float|nulldocblock, but extension developers are not guaranteed to honour it.🛡️ Proposed fix — add the cast immediately after the null check
$cogs_value = apply_filters( 'woocommerce_save_order_cogs_value', $cogs_value_original, $order ); if ( null === $cogs_value ) { return; } + + $cogs_value = (float) $cogs_value; $sync_meta = $changed_via_order_object || $cogs_value_original !== $cogs_value;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php` around lines 2167 - 2175, The $cogs_value returned from apply_filters in the OrdersTableDataStore save routine must be normalized to a float after the null check to match the item-level behavior and avoid type-strict comparison bugs; so in the method handling $cogs_value (the block using $cogs_value_original, $cogs_value, apply_filters('woocommerce_save_order_cogs_value', ...), $sync_meta and the subsequent 0.0 === $cogs_value check and data_store_meta->get_metadata_by_key($order, '_cogs_total_value')), cast $cogs_value to (float) immediately after confirming it is not null so strict !== and === comparisons behave correctly and deletions/updates are not skipped or wrongly triggered.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php`:
- Around line 2152-2153: Update the docblock for the parameter
$changed_via_order_object in OrdersTableDataStore (the save COGS/order save
routine) to fix typos: change "Where" to "Whether", "was changes" to "was
changed", and "api" to "API" so the `@param` reads that the boolean indicates
whether the COGS value was changed via the order object API; keep the parameter
name ($changed_via_order_object) and surrounding docblock format intact.
---
Nitpick comments:
In `@plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php`:
- Around line 2167-2175: The $cogs_value returned from apply_filters in the
OrdersTableDataStore save routine must be normalized to a float after the null
check to match the item-level behavior and avoid type-strict comparison bugs; so
in the method handling $cogs_value (the block using $cogs_value_original,
$cogs_value, apply_filters('woocommerce_save_order_cogs_value', ...), $sync_meta
and the subsequent 0.0 === $cogs_value check and
data_store_meta->get_metadata_by_key($order, '_cogs_total_value')), cast
$cogs_value to (float) immediately after confirming it is not null so strict !==
and === comparisons behave correctly and deletions/updates are not skipped or
wrongly triggered.
…thub.com:woocommerce/woocommerce into performance/63118-reduce-sqls-number-iteration-5
There was a problem hiding this comment.
🧹 Nitpick comments (2)
plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php (2)
2167-2175: Add a(float)cast after the null check — inconsistent with item data store and causes two correctness gaps.
apply_filterscan return any type. Without a cast, two issues arise:
$cogs_value_original !== $cogs_value(line 2172) is a strict comparison. If a filter returnsint 0orstring "0"for a zero-CoGS order,0.0 !== 0→true→$sync_meta = true→ a write is forced on every subsequent save, defeating the optimisation.
0.0 === $cogs_value(line 2175) is a strict comparison. Withint 0the check isfalse, so the delete branch is bypassed and theelseif/elsebranch runs instead — updating or inserting meta with an integer value rather than deleting it.The analogous
save_cogs_datainabstract-wc-order-item-type-data-store.php(line 243) explicitly casts:$cogs_value = (float) $cogs_value;after the null check. This PR should do the same.♻️ Proposed fix
if ( null === $cogs_value ) { return; } + $cogs_value = (float) $cogs_value; + $sync_meta = $changed_via_order_object || $cogs_value_original !== $cogs_value;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php` around lines 2167 - 2175, After the null check on $cogs_value (right after apply_filters in OrdersTableDataStore), cast the filter result to float (e.g. $cogs_value = (float) $cogs_value;) so comparisons against $cogs_value_original and the strict checks like 0.0 === $cogs_value behave consistently; update the code around $cogs_value_original, $cogs_value and the metadata logic that calls $this->data_store_meta->get_metadata_by_key to rely on the normalized float value.
2183-2188:elsebranch creates a 0-value_cogs_total_valuemeta row that serves no purpose.When
$sync_meta = true(e.g., first checkout save with products having no CoGS set),$cogs_value = 0.0, and no existing meta: theelsebranch inserts a new row with value0.0.read_cogs_dataat line 1426 treats both "absent meta" and "meta = 0" identically, so the row has no semantic benefit. The item-levelsave_cogs_datainabstract-wc-order-item-type-data-store.php(lines 243–249) avoids this by only writing non-zero values.♻️ Proposed fix
- } else { + } elseif ( 0.0 !== $cogs_value ) { $meta = new \WC_Meta_Data(); $meta->key = '_cogs_total_value'; $meta->value = $cogs_value; $this->data_store_meta->add_meta( $order, $meta ); }Note: If the
(float)cast from the previous suggestion is applied first, the0.0 !== $cogs_valueguard here is guaranteed to be a clean float comparison.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php` around lines 2183 - 2188, The else branch in OrdersTableDataStore is inserting a redundant _cogs_total_value meta row with 0.0; modify the logic so you only call $this->data_store_meta->add_meta($order, $meta) when $cogs_value is non-zero (use a strict float check, e.g. $cogs_value !== 0.0 after casting to float earlier), matching the item-level save_cogs_data behavior and keeping read_cogs_data semantics consistent; ensure you reference the same meta key '_cogs_total_value' and the data_store_meta->add_meta call when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php`:
- Around line 2167-2175: After the null check on $cogs_value (right after
apply_filters in OrdersTableDataStore), cast the filter result to float (e.g.
$cogs_value = (float) $cogs_value;) so comparisons against $cogs_value_original
and the strict checks like 0.0 === $cogs_value behave consistently; update the
code around $cogs_value_original, $cogs_value and the metadata logic that calls
$this->data_store_meta->get_metadata_by_key to rely on the normalized float
value.
- Around line 2183-2188: The else branch in OrdersTableDataStore is inserting a
redundant _cogs_total_value meta row with 0.0; modify the logic so you only call
$this->data_store_meta->add_meta($order, $meta) when $cogs_value is non-zero
(use a strict float check, e.g. $cogs_value !== 0.0 after casting to float
earlier), matching the item-level save_cogs_data behavior and keeping
read_cogs_data semantics consistent; ensure you reference the same meta key
'_cogs_total_value' and the data_store_meta->add_meta call when making the
change.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php (1)
2155-2190:⚠️ Potential issue | 🟡 MinorAdd unit tests for the
$cogs_value_changed=falsebranching paths insave_cogs_data.The new
$cogs_value_changedoptimization introduces code paths that aren't explicitly tested: (1) value unchanged by API, filter unchanged → no meta write, and (2) value unchanged by API, filter modifies it → meta write. All existing COGS tests callset_cogs_total_value()beforesave(), so$cogs_value_changedis always true. A test that saves an order without callingset_cogs_total_value()but with the filter returning a different value would verify the optimization works correctly and prevent regressions if the changes-tracking mechanism is modified.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php` around lines 2155 - 2190, Add unit tests covering the save_cogs_data( WC_Abstract_Order $order, bool $cogs_value_changed ) branching when $cogs_value_changed is false: create one test where you do not call set_cogs_total_value() and the woocommerce_save_order_cogs_value filter returns the same value so no meta is written, and another test where you do not call set_cogs_total_value() but the filter returns a different value so the _cogs_total_value meta is added/updated; assert meta presence/absence using the data store meta helpers (matching the logic in save_cogs_data) and ensure you exercise the delete/update/add branches (existing_meta true/false and zero-value deletion) so regressions in the change-tracking optimization are caught.
🧹 Nitpick comments (2)
plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php (2)
2173-2189:elsebranch adds a redundant0.0meta entry when CoGS is zero and no existing meta.When
$sync_meta = true(e.g., because$cogs_value_changed = true),$cogs_value = 0.0, and$existing_metais empty, theelsebranch fires and executes an unnecessaryadd_metacall. Sinceread_cogs_datadefaults to0when no_cogs_total_valuemeta exists, storing0.0is semantically equivalent to storing nothing — and costs one SQL against the optimization goal of this PR.♻️ Proposed fix
- } else { + } elseif ( 0.0 !== $cogs_value ) { $meta = new \WC_Meta_Data(); $meta->key = '_cogs_total_value'; $meta->value = $cogs_value; $this->data_store_meta->add_meta( $order, $meta ); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php` around lines 2173 - 2189, The code currently calls add_meta in the else branch even when $cogs_value === 0.0 and no existing meta, creating a redundant zero-valued meta; update the logic in OrdersTableDataStore (the block using $sync_meta, $cogs_value and $existing_meta) so that you only call $this->data_store_meta->add_meta($order, $meta) when $cogs_value is not 0.0 (e.g., add a guard like if ( 0.0 !== $cogs_value ) before constructing and adding the new \WC_Meta_Data), leaving the existing delete_meta path intact for existing zero metas and skipping any insert when value is zero and no meta exists.
2143-2143: Add guard to prevent storing CoGS meta when value is 0 on new orders.The else branch at lines 2183–2188 adds
_cogs_total_valuemeta even when the value is0.0, but only for new orders (when no existing meta exists). The delete branch at lines 2173–2176 correctly removes the meta when the value is0.0and existing meta is present. To maintain consistency and avoid unnecessary database writes, guard the else clause to skip adding meta for zero values:Suggested fix
} elseif ( 0.0 !== $cogs_value ) { $meta = new \WC_Meta_Data(); $meta->key = '_cogs_total_value'; $meta->value = $cogs_value; $this->data_store_meta->add_meta( $order, $meta ); }This aligns with the behavior in the existing test
test_saving_order_saves_cogs_value_if_not_zero_and_cogs_enabled(lines 3861–3865), which expects no meta to be stored when CoGS is set to0.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php` at line 2143, The else branch in OrdersTableDataStore::save_cogs_data currently adds a _cogs_total_value meta even when $cogs_value is 0.0; update the branch that constructs a new \WC_Meta_Data and calls $this->data_store_meta->add_meta( $order, $meta ) to only run when $cogs_value !== 0.0 (or 0.0 !== $cogs_value), so zero values do not create the meta and mirror the delete behavior that removes existing zero-value meta.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php`:
- Around line 2155-2190: Add unit tests covering the save_cogs_data(
WC_Abstract_Order $order, bool $cogs_value_changed ) branching when
$cogs_value_changed is false: create one test where you do not call
set_cogs_total_value() and the woocommerce_save_order_cogs_value filter returns
the same value so no meta is written, and another test where you do not call
set_cogs_total_value() but the filter returns a different value so the
_cogs_total_value meta is added/updated; assert meta presence/absence using the
data store meta helpers (matching the logic in save_cogs_data) and ensure you
exercise the delete/update/add branches (existing_meta true/false and zero-value
deletion) so regressions in the change-tracking optimization are caught.
---
Nitpick comments:
In `@plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php`:
- Around line 2173-2189: The code currently calls add_meta in the else branch
even when $cogs_value === 0.0 and no existing meta, creating a redundant
zero-valued meta; update the logic in OrdersTableDataStore (the block using
$sync_meta, $cogs_value and $existing_meta) so that you only call
$this->data_store_meta->add_meta($order, $meta) when $cogs_value is not 0.0
(e.g., add a guard like if ( 0.0 !== $cogs_value ) before constructing and
adding the new \WC_Meta_Data), leaving the existing delete_meta path intact for
existing zero metas and skipping any insert when value is zero and no meta
exists.
- Line 2143: The else branch in OrdersTableDataStore::save_cogs_data currently
adds a _cogs_total_value meta even when $cogs_value is 0.0; update the branch
that constructs a new \WC_Meta_Data and calls $this->data_store_meta->add_meta(
$order, $meta ) to only run when $cogs_value !== 0.0 (or 0.0 !== $cogs_value),
so zero values do not create the meta and mirror the delete behavior that
removes existing zero-value meta.
This approval has been dismissed due to the PR being moved to draft status. Please request a new review when ready.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php`:
- Around line 2175-2188: The save_cogs_data branch incorrectly uses a strict
float comparison (0.0 === $cogs_value) which can miss integer zero values and
causes an update instead of delete, and the insert (else) branch unconditionally
calls add_meta even when $cogs_value is zero; update save_cogs_data to use a
non-strict check (== 0) or cast to float before comparing so both int(0) and 0.0
are treated as zero when deciding to call delete_meta($order, $existing_meta),
and in the else (add_meta) branch skip creating/adding the new \WC_Meta_Data if
$cogs_value == 0 to avoid inserting redundant zero rows; adjust logic around
$existing_meta, $cogs_value, and calls to data_store_meta->delete_meta,
->update_meta, and ->add_meta accordingly.
There was a problem hiding this comment.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php`:
- Around line 2175-2188: The code in OrdersTableDataStore handling $cogs_value
can insert or update a zero value instead of deleting/omitting the meta; fix by
treating any numeric zero (int(0) or float(0.0) or "0") as "no meta":
coerce/check with a strict numeric-zero guard (e.g. cast or use == 0.0 or
is_numeric + floatval(...) === 0.0) before branching so that when the computed
$cogs_value is zero you always call $this->data_store_meta->delete_meta(...) or
skip add_meta/update_meta; ensure the else branch only calls add_meta when the
normalized float value is non-zero and the elseif branch only updates when the
normalized float is non-zero, referencing $cogs_value, $existing_meta,
OrdersTableDataStore and the data_store_meta methods
delete_meta/update_meta/add_meta to locate the logic to change.
…n order (#63372) Added guarding conditions for updating CoGS meta when persisting an order to reduce the number of SQLs on the checkout page.
Submission Review Guidelines:
Changes proposed in this Pull Request:
Re-iterate on #63118 (#63110, WOOPLUG-6243)
Tune the logic of saving CoGS meta for the orders. For the checkout page, the numbers are as follows:
How to test the changes in this Pull Request:
Additionally, verify that adding a product with CoGS data to the cart and completing the checkout populates the orders' CoGS data.