Skip to content

Conversation

@albarin
Copy link
Contributor

@albarin albarin commented Aug 26, 2025

Submission Review Guidelines:

Changes proposed in this Pull Request:

This PR reduces the number of calls to get_post_meta by following the same structure as class-wc-product-data-store-cpt.php. Instead of calling get_post_meta for each field, it gets all the post meta in one call.

Closes #37326

How to test the changes in this Pull Request:

Using the WooCommerce Testing Instructions Guide, include your detailed testing instructions:

  1. Create a variable product and smoke test the edit product page for variations (add/edit/delete variations, change variations properties, adding images, etc.).
  2. Smoke test a purchase of variable products in the frontend (add to cart, cart, checkout, etc.).
  3. Smoke test any other scenarios related to product variations that you can think of.

Testing that has already taken place:

Changelog entry

  • Automatically create a changelog entry from the details below.
  • This Pull Request does not require a changelog entry. (Comment required below)
Changelog Entry Details

Significance

  • Patch
  • Minor
  • Major

Type

  • Fix - Fixes an existing bug
  • Add - Adds functionality
  • Update - Update existing functionality
  • Dev - Development related task
  • Tweak - A minor adjustment to the codebase
  • Performance - Address performance issues
  • Enhancement - Improvement to existing functionality

Message

Reduce the number of calls to get_post_meta in WC_Product_Variation_Data_Store_CPT.

Changelog Entry Comment

Comment

@github-actions github-actions bot added the plugin: woocommerce Issues related to the WooCommerce Core plugin. label Aug 26, 2025
@albarin albarin marked this pull request as ready for review September 1, 2025 10:44
@woocommercebot woocommercebot requested review from a team and jorgeatorres and removed request for a team September 1, 2025 10:45
@github-actions
Copy link
Contributor

github-actions bot commented Sep 1, 2025

Testing Guidelines

Hi @Konamiman @kalessil ,

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:

  • 🖼️ Screenshots or screen recordings.
  • 📝 List of functionality tested / steps followed.
  • 🌐 Site details (environment attributes such as hosting type, plugins, theme, store size, store age, and relevant settings).
  • 🔍 Any analysis performed, such as assessing potential impacts on environment attributes and other plugins, conducting performance profiling, or using LLM/AI-based analysis.

⚠️ Within the testing details you provide, please ensure that no sensitive information (such as API keys, passwords, user data, etc.) is included in this public issue.

@albarin albarin requested review from Konamiman and kalessil and removed request for jorgeatorres September 1, 2025 10:45
@github-actions
Copy link
Contributor

github-actions bot commented Sep 1, 2025

Test using WordPress Playground

The changes in this pull request can be previewed and tested using a WordPress Playground instance.
WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

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.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 1, 2025

📝 Walkthrough

Walkthrough

Refactors WC_Product_Variation_Data_Store_CPT to read post meta in bulk, map meta keys to product properties, set variation and parent data in bulk, centralizes COGS handling, and adds tests plus a changelog entry documenting reduced get_post_meta calls.

Changes

Cohort / File(s) Summary
Data store refactor
plugins/woocommerce/includes/data-stores/class-wc-product-variation-data-store-cpt.php
Replace many individual get_post_meta calls with single bulk get_post_meta( $id ) reads for variation and parent; use meta_key→prop maps; build and post-process $variation_data and $parent_data; call set_props() / set_parent_data() once; add load_cogs_data() and exclude _cogs_value_is_additive from generic internal meta handling.
Unit tests
plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-variations-data-store-cpt-test.php
Add data store setup/teardown, enable COGS feature for tests, and add three tests verifying variation property loading, stock behavior, and parent data population (including shipping_class_id, catalog_visibility, image_id).
Changelog
plugins/woocommerce/changelog/60614-fix-37326
Add changelog entry noting a minor performance change that reduces get_post_meta calls in WC_Product_Variation_Data_Store_CPT.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Caller
  participant DS as WC_Product_Variation_Data_Store_CPT
  participant WP as WP_Meta/Terms
  participant Prod as WC_Product_Variation

  Caller->>DS: read(variation)
  DS->>WP: get_post_meta(variation_id)  // single bulk fetch
  DS->>DS: iterate meta_key→prop map\nmaybe_unserialize + post-process
  DS->>Prod: set_props(variation_data)  // single bulk set
  DS->>WP: get_post_meta(parent_id)  // parent bulk fetch
  DS->>DS: iterate parent meta map\ncompute title/status/image/shipping/class/stock
  DS->>Prod: set_parent_data(parent_data)
  DS-->>Caller: populated variation
  Note over DS: load_cogs_data() reads `_cogs_value_is_additive` and sets COGS props
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/37326

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
plugins/woocommerce/includes/data-stores/class-wc-product-variation-data-store-cpt.php (1)

366-477: Consolidate inline get_post_meta in COGS block
The direct call

$cogs_value_is_additive = 'yes' === get_post_meta( $product->get_id(), '_cogs_value_is_additive', true );

at line 496 still issues a separate query. Replace it with the value already loaded into $set_props['cogs_value_is_additive'].

🧹 Nitpick comments (7)
plugins/woocommerce/includes/data-stores/class-wc-product-variation-data-store-cpt.php (6)

366-401: Bulk meta read is solid; avoid setting COGS flags when the feature is disabled.
Right now cogs_value_is_additive may be set via set_props even if the feature is off. Gate it by not piping it through the generic map.

Apply:

 $meta_key_to_props = array(
   '_variation_description'  => 'description',
   '_regular_price'          => 'regular_price',
   '_sale_price'             => 'sale_price',
   '_sale_price_dates_from'  => 'date_on_sale_from',
   '_sale_price_dates_to'    => 'date_on_sale_to',
   '_manage_stock'           => 'manage_stock',
   '_stock_status'           => 'stock_status',
   '_virtual'                => 'virtual',
   '_product_image_gallery'  => 'gallery_image_ids',
   '_download_limit'         => 'download_limit',
   '_download_expiry'        => 'download_expiry',
   '_downloadable'           => 'downloadable',
   '_sku'                    => 'sku',
   '_global_unique_id'       => 'global_unique_id',
   '_stock'                  => 'stock_quantity',
   '_weight'                 => 'weight',
   '_length'                 => 'length',
   '_width'                  => 'width',
   '_height'                 => 'height',
   '_low_stock_amount'       => 'low_stock_amount',
   '_backorders'             => 'backorders',
   '_cogs_total_value'       => 'cogs_total_value',
-  '_cogs_value_is_additive' => 'cogs_value_is_additive',
   '_tax_class'              => 'tax_class',
 );

402-406: Normalize gallery IDs and shipping class type.
Use core helpers for robustness and consistent typing.

-$set_props['gallery_image_ids'] = array_filter( explode( ',', $set_props['gallery_image_ids'] ?? '' ) );
-$set_props['shipping_class_id'] = current( $this->get_term_ids( $id, 'product_shipping_class' ) );
+$set_props['gallery_image_ids'] = wp_parse_id_list( (string) ( $set_props['gallery_image_ids'] ?? '' ) );
+$set_props['shipping_class_id'] = absint( current( $this->get_term_ids( $id, 'product_shipping_class' ) ) );

409-419: Avoid double-setting/extra query for COGS; use preloaded meta and apply the existing filter inline.
Currently you set COGS here and then call load_cogs_data() later, which re-reads and re-sets. Use the pre-fetched values and apply the filter to keep semantics while saving a query.

 if ( $this->cogs_feature_is_enabled() ) {
-	$cogs_value             = $set_props['cogs_total_value'] ?? '';
-	$cogs_value             = '' === $cogs_value ? null : (float) $cogs_value;
-	$cogs_value_is_additive = 'yes' === ( $set_props['cogs_value_is_additive'] ?? '' );
+	$cogs_value             = $set_props['cogs_total_value'] ?? '';
+	$cogs_value             = '' === $cogs_value ? null : (float) $cogs_value;
+	$cogs_value_is_additive = 'yes' === ( $post_meta_values['_cogs_value_is_additive'][0] ?? '' );
+	// Preserve filter behavior from load_cogs_data().
+	$cogs_value_is_additive = apply_filters( 'woocommerce_load_product_cogs_is_additive_flag', $cogs_value_is_additive, $product );
 	$product->set_props(
 		array(
 			'cogs_value'             => $cogs_value,
 			'cogs_value_is_additive' => $cogs_value_is_additive,
 		)
 	);
 }

Then remove the later load_cogs_data() call (see below).


469-477: Type normalization on parent data is good; one tiny consistency tweak.
You already absint shipping class and normalize stock. Consider also casting image_id to absint for consistency.

-$parent_data['image_id']           = get_post_thumbnail_id( $product->get_parent_id() );
+$parent_data['image_id']           = absint( get_post_thumbnail_id( $product->get_parent_id() ) );

479-482: Cross-sell IDs default handling.
Passing a possibly empty string into set_cross_sell_ids() is safe (it casts to array and filters empties). If you want to be explicit:

-$product->set_cross_sell_ids( $parent_data['_crosssell_ids'] );
+$product->set_cross_sell_ids( (array) ( $parent_data['_crosssell_ids'] ?? array() ) );

483-485: Remove redundant COGS reload once inline filter is applied.
If you adopt the inline-filter approach above, this second load is redundant and adds queries.

-if ( $this->cogs_feature_is_enabled() ) {
-	$this->load_cogs_data( $product );
-}
+// COGS already set from preloaded meta with filter applied.
plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-variations-data-store-cpt-test.php (1)

39-109: Broad property load test is comprehensive; one assertion may be brittle.
get_gallery_image_ids() typically returns ints; asserting strings could be fragile across environments.

- $this->assertEquals( array( '123', '456', '789' ), $product->get_gallery_image_ids() );
+ $this->assertEquals( array( 123, 456, 789 ), $product->get_gallery_image_ids() );
📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 95f88a1 and 0924c33.

📒 Files selected for processing (3)
  • plugins/woocommerce/changelog/60614-fix-37326 (1 hunks)
  • plugins/woocommerce/includes/data-stores/class-wc-product-variation-data-store-cpt.php (2 hunks)
  • plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-variations-data-store-cpt-test.php (3 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{php,js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/code-quality.mdc)

**/*.{php,js,jsx,ts,tsx}: Guard against unexpected inputs
Sanitize and validate any potentially dangerous inputs
Ensure code is backwards compatible
Write code that is readable and intuitive
Ensure code has unit or E2E tests where applicable

Files:

  • plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-variations-data-store-cpt-test.php
  • plugins/woocommerce/includes/data-stores/class-wc-product-variation-data-store-cpt.php
plugins/woocommerce/tests/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/woo-phpunit.mdc)

plugins/woocommerce/tests/**/*.php: Ensure test classes define public setUp() and tearDown() methods (not protected)
All PHPUnit test methods must be public, not protected
Add declare(strict_types=1); at the top of each test file
Test classes should extend WC_Unit_Test_Case

Files:

  • plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-variations-data-store-cpt-test.php
**/*.{php,js,ts,jsx,tsx}

⚙️ CodeRabbit configuration file

**/*.{php,js,ts,jsx,tsx}: Don't trust that extension developers will follow the best practices, make sure the code:

  • Guards against unexpected inputs.
  • Sanitizes and validates any potentially dangerous inputs.
  • Is backwards compatible.
  • Is readable and intuitive.
  • Has unit or E2E tests where applicable.

Files:

  • plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-variations-data-store-cpt-test.php
  • plugins/woocommerce/includes/data-stores/class-wc-product-variation-data-store-cpt.php
🧠 Learnings (6)
📚 Learning: 2025-08-18T06:11:48.768Z
Learnt from: CR
PR: woocommerce/woocommerce#0
File: .cursor/rules/woo-phpunit.mdc:0-0
Timestamp: 2025-08-18T06:11:48.768Z
Learning: Applies to plugins/woocommerce/tests/**/*.php : Ensure test classes define public setUp() and tearDown() methods (not protected)

Applied to files:

  • plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-variations-data-store-cpt-test.php
📚 Learning: 2025-08-29T10:13:44.268Z
Learnt from: Aljullu
PR: woocommerce/woocommerce#60667
File: plugins/woocommerce/src/Blocks/BlockTypes/AddToCartForm.php:122-125
Timestamp: 2025-08-29T10:13:44.268Z
Learning: In WooCommerce, the ProductType class in plugins/woocommerce/src/Enums/ProductType.php contains string constants (not a PHP backed enum), so ProductType::VARIATION directly returns the string 'variation' and can be passed directly to methods like WC_Product::is_type() without needing ->value.

Applied to files:

  • plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-variations-data-store-cpt-test.php
📚 Learning: 2025-08-18T06:11:48.768Z
Learnt from: CR
PR: woocommerce/woocommerce#0
File: .cursor/rules/woo-phpunit.mdc:0-0
Timestamp: 2025-08-18T06:11:48.768Z
Learning: Applies to plugins/woocommerce/tests/**/*.php : Add declare(strict_types=1); at the top of each test file

Applied to files:

  • plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-variations-data-store-cpt-test.php
📚 Learning: 2025-08-18T06:11:48.768Z
Learnt from: CR
PR: woocommerce/woocommerce#0
File: .cursor/rules/woo-phpunit.mdc:0-0
Timestamp: 2025-08-18T06:11:48.768Z
Learning: Applies to plugins/woocommerce/tests/**/*.php : Test classes should extend WC_Unit_Test_Case

Applied to files:

  • plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-variations-data-store-cpt-test.php
📚 Learning: 2025-08-11T18:01:34.499Z
Learnt from: nerrad
PR: woocommerce/woocommerce#60158
File: plugins/woocommerce/tests/php/includes/class-wc-brands-test.php:207-223
Timestamp: 2025-08-11T18:01:34.499Z
Learning: In the WooCommerce test suite, the team prefers test helper methods to fail immediately with errors (like undefined index) rather than adding defensive checks, as this makes test failures more visible and helps identify setup issues quickly. This applies to helper methods like `get_first_brand_term()` in test files.

Applied to files:

  • plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-variations-data-store-cpt-test.php
📚 Learning: 2025-08-18T06:11:48.768Z
Learnt from: CR
PR: woocommerce/woocommerce#0
File: .cursor/rules/woo-phpunit.mdc:0-0
Timestamp: 2025-08-18T06:11:48.768Z
Learning: Applies to plugins/woocommerce/tests/**/*.php : All PHPUnit test methods must be public, not protected

Applied to files:

  • plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-variations-data-store-cpt-test.php
🧬 Code graph analysis (2)
plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-variations-data-store-cpt-test.php (3)
plugins/woocommerce/includes/data-stores/class-wc-product-variation-data-store-cpt.php (2)
  • WC_Product_Variation_Data_Store_CPT (22-658)
  • read (49-108)
plugins/woocommerce/tests/legacy/framework/helpers/class-wc-helper-product.php (2)
  • WC_Helper_Product (16-447)
  • create_variation_product (166-260)
plugins/woocommerce/includes/abstracts/abstract-wc-product.php (43)
  • set_sold_individually (1072-1074)
  • set_cross_sell_ids (1132-1134)
  • set_regular_price (912-914)
  • set_sale_price (922-924)
  • set_date_on_sale_from (932-934)
  • set_date_on_sale_to (942-944)
  • set_manage_stock (1017-1019)
  • set_downloadable (1279-1281)
  • set_gallery_image_ids (1399-1403)
  • set_download_limit (1379-1381)
  • set_download_expiry (1389-1391)
  • set_backorders (1052-1054)
  • set_sku (856-872)
  • set_global_unique_id (880-895)
  • set_stock_quantity (1027-1029)
  • set_weight (1082-1084)
  • set_length (1092-1094)
  • set_width (1102-1104)
  • set_height (1112-1114)
  • set_tax_class (990-1000)
  • set_cogs_value (2347-2352)
  • get_regular_price (299-301)
  • get_sale_price (309-311)
  • get_date_on_sale_from (320-322)
  • get_date_on_sale_to (331-333)
  • get_manage_stock (373-375)
  • is_virtual (1626-1628)
  • is_downloadable (1617-1619)
  • get_gallery_image_ids (642-644)
  • get_download_limit (697-699)
  • get_download_expiry (675-677)
  • get_backorders (405-407)
  • get_sku (268-270)
  • get_global_unique_id (279-281)
  • get_stock_quantity (383-385)
  • get_weight (437-439)
  • get_length (447-449)
  • get_width (457-459)
  • get_height (467-469)
  • get_tax_class (362-364)
  • get_cogs_value (2375-2382)
  • get_sold_individually (427-429)
  • get_cross_sell_ids (507-509)
plugins/woocommerce/includes/data-stores/class-wc-product-variation-data-store-cpt.php (4)
plugins/woocommerce/includes/abstracts/abstract-wc-data.php (1)
  • set_props (786-811)
plugins/woocommerce/includes/data-stores/class-wc-product-data-store-cpt.php (1)
  • cogs_feature_is_enabled (2461-2463)
plugins/woocommerce/includes/wc-formatting-functions.php (1)
  • wc_stock_amount (487-496)
plugins/woocommerce/includes/abstracts/abstract-wc-product.php (2)
  • set_sold_individually (1072-1074)
  • set_cross_sell_ids (1132-1134)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (11)
plugins/woocommerce/changelog/60614-fix-37326 (1)

1-4: Changelog entry reads well and matches scope.
Clear, standard format. Nothing to change.

plugins/woocommerce/includes/data-stores/class-wc-product-variation-data-store-cpt.php (5)

30-33: Exclude COGS additive flag from public meta: good call.
Adding _cogs_value_is_additive to internal keys prevents leaking implementation details via meta_data.


443-461: Parent meta bulk read looks correct.
Mapping covers expected keys and reduces queries as intended. Nice parity with the variation mapping.

Also applies to: 464-468


611-632: COGS save hook usage LGTM.
Respects the suppress-on-null pattern and tracks updated_props correctly.


596-610: Meta persistence map is minimal and focused.
Only _variation_description here; remaining handled by parent. Good separation.


541-549: Visibility sync logic remains correct.
Keeps the out-of-stock term in sync; no changes needed.

plugins/woocommerce/tests/php/includes/data-stores/class-wc-product-variations-data-store-cpt-test.php (5)

1-7: Test file header and imports conform to guidelines.
declare(strict_types=1); present; enums imported explicitly. Good.


15-27: Setup is clean and typed.
Public setUp(), typed private property, and trait usage look good.


32-37: Teardown cleans feature flags and filters.
Prevents cross-test leakage. Good practice.


114-135: Stock-focused test is precise.
Validates both initial load and subsequent backorders change.


140-183: Parent data assertions cover key fields.
Covers title/status/SKU/stock/dimensions/tax class/purchase note and presence of derived keys.

Copy link
Contributor

@kalessil kalessil left a comment

Choose a reason for hiding this comment

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

Code review feedback: see minor comments.

Also similar inefficient approach exists in \Abstract_WC_Order_Data_Store_CPT::read_order_data, \WC_Coupon_Data_Store_CPT::read, \WC_Order_Data_Store_CPT::read_order_data, \WC_Order_Refund_Data_Store_CPT::read_order_data, \WC_Product_Data_Store_CPT::get_data_for_lookup_table and similar cases, we should probably create additional tickets to address those separately in smaller PRs.

Copy link
Contributor

@kalessil kalessil left a comment

Choose a reason for hiding this comment

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

One more question: do we know how the changes will impact RAM usage (and if we need to unset the fetched metas arrays to help GC)?

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
plugins/woocommerce/includes/data-stores/class-wc-product-variation-data-store-cpt.php (1)

427-433: Nice: parent_id cached locally.

This addresses the earlier nit about repeated get_parent_id() calls.

🧹 Nitpick comments (4)
plugins/woocommerce/includes/data-stores/class-wc-product-variation-data-store-cpt.php (4)

366-408: Harden types for gallery/shipping class and avoid unknown props in set_props.

  • gallery_image_ids: parse to int IDs (handles whitespace/dupes).
  • shipping_class_id: cast to int for consistency with parent block.
  • Optional: don’t feed unknown props (e.g., cogs_total_value, cogs_value_is_additive) into set_props since there are no setters; compute them outside.

Apply:

-		$variation_data['gallery_image_ids'] = array_filter( explode( ',', $variation_data['gallery_image_ids'] ?? '' ) );
-		$variation_data['shipping_class_id'] = current( $this->get_term_ids( $id, 'product_shipping_class' ) );
+		$variation_data['gallery_image_ids'] = wp_parse_id_list( $variation_data['gallery_image_ids'] ?? '' );
+		$variation_data['shipping_class_id'] = absint( current( $this->get_term_ids( $id, 'product_shipping_class' ) ) );

Optionally trim the mapping to avoid unknown setters:

-			'_cogs_total_value'       => 'cogs_total_value',
-			'_cogs_value_is_additive' => 'cogs_value_is_additive',

409-417: Avoid double-setting the COGS “additive” flag.

You set cogs_value_is_additive here and then again in load_cogs_data(). To reduce churn and keep filter application in one place, set only cogs_value here and leave the additive flag to load_cogs_data().

 			$product->set_props(
 				array(
 					'cogs_value'             => $cogs_value,
-					'cogs_value_is_additive' => $cogs_value_is_additive,
 				)
 			);

444-478: Cast cross-sell IDs to ints before use.

set_cross_sell_ids() filters empties but doesn’t cast. Normalize to ints once when building $parent_data.

 		foreach ( $parent_meta_key_to_props as $meta_key => $prop ) {
 			$meta_value           = $parent_post_meta_values[ $meta_key ][0] ?? '';
 			$parent_data[ $prop ] = maybe_unserialize( $meta_value ); // get_post_meta only unserializes single values.
 		}
 
+		$parent_data['_crosssell_ids'] = array_map( 'absint', (array) $parent_data['_crosssell_ids'] );

497-513: COGS loader OK; minor note on duplication.

This re-sets the additive flag (and hits the meta cache). Consider relying solely on this path for the flag (see earlier comment) to keep filtering and assignment in one place.

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0924c33 and 5b1767b.

📒 Files selected for processing (1)
  • plugins/woocommerce/includes/data-stores/class-wc-product-variation-data-store-cpt.php (3 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{php,js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/code-quality.mdc)

**/*.{php,js,jsx,ts,tsx}: Guard against unexpected inputs
Sanitize and validate any potentially dangerous inputs
Ensure code is backwards compatible
Write code that is readable and intuitive
Ensure code has unit or E2E tests where applicable

Files:

  • plugins/woocommerce/includes/data-stores/class-wc-product-variation-data-store-cpt.php
**/*.{php,js,ts,jsx,tsx}

⚙️ CodeRabbit configuration file

**/*.{php,js,ts,jsx,tsx}: Don't trust that extension developers will follow the best practices, make sure the code:

  • Guards against unexpected inputs.
  • Sanitizes and validates any potentially dangerous inputs.
  • Is backwards compatible.
  • Is readable and intuitive.
  • Has unit or E2E tests where applicable.

Files:

  • plugins/woocommerce/includes/data-stores/class-wc-product-variation-data-store-cpt.php
🧬 Code graph analysis (1)
plugins/woocommerce/includes/data-stores/class-wc-product-variation-data-store-cpt.php (4)
plugins/woocommerce/includes/abstracts/abstract-wc-data.php (1)
  • set_props (786-811)
plugins/woocommerce/includes/data-stores/class-wc-product-data-store-cpt.php (1)
  • cogs_feature_is_enabled (2461-2463)
plugins/woocommerce/includes/wc-formatting-functions.php (1)
  • wc_stock_amount (487-496)
plugins/woocommerce/includes/abstracts/abstract-wc-product.php (2)
  • set_sold_individually (1072-1074)
  • set_cross_sell_ids (1132-1134)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (22)
  • GitHub Check: Blocks e2e tests 5/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 9/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 7/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 1/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 6/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Metrics - @woocommerce/plugin-woocommerce [performance]
  • GitHub Check: PHP: 7.4 WP: latest - 1 [WP 6.7.3] 1/2 - @woocommerce/plugin-woocommerce [unit:php]
  • GitHub Check: Blocks e2e tests 3/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 8/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 2/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 4/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core API tests - @woocommerce/plugin-woocommerce [api]
  • GitHub Check: PHP: 8.4 WP: latest [WP latest] 1/2 - @woocommerce/plugin-woocommerce [unit:php]
  • GitHub Check: Core e2e tests 3/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core e2e tests 4/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core e2e tests 5/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: PHP: 7.4 WP: latest - 1 [WP 6.7.3] 2/2 - @woocommerce/plugin-woocommerce [unit:php]
  • GitHub Check: Core e2e tests 1/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: PHP: 8.4 WP: latest [WP latest] 2/2 - @woocommerce/plugin-woocommerce [unit:php]
  • GitHub Check: Core e2e tests 2/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Lint - @woocommerce/plugin-woocommerce
  • GitHub Check: build
🔇 Additional comments (6)
plugins/woocommerce/includes/data-stores/class-wc-product-variation-data-store-cpt.php (6)

30-33: Good exclusion of internal COGS meta.

Excluding _cogs_value_is_additive from generic meta is correct and avoids leaking internal flags into public meta.


480-483: Prop pull from parent looks good.

Copying parent-only props (sold_individually, tax_status, cross_sell_ids) onto the variation is consistent with current behavior.


526-528: Visibility term updates for shipping class are correct.

Updates only when needed; no concerns.


542-550: Stock-status-driven visibility is correct.

Term sync logic is minimal and accurate.


560-587: Attribute meta sync logic LGTM.

Efficiently updates current attrs and cleans stale keys.


597-637: Saving COGS additive flag via filter is well-structured.

Good use of apply_filters and update_or_delete_post_meta; aligns with the read path.

Copy link
Contributor

@kalessil kalessil left a comment

Choose a reason for hiding this comment

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

LGTM! Did smoke tests, once more proofread to ensure the mappings are matching.

@albarin albarin merged commit 311c80c into trunk Sep 2, 2025
37 checks passed
@albarin albarin deleted the fix/37326 branch September 2, 2025 14:36
@github-actions github-actions bot added this to the 10.3.0 milestone Sep 2, 2025
@albarin albarin mentioned this pull request Sep 29, 2025
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

plugin: woocommerce Issues related to the WooCommerce Core plugin.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Enhancement]: Performance gains with Variable Product Data Store

3 participants