Skip to content

WC_Data: Throw an exception when attempting to parse an invalid date format #58700

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

roccotripaldi
Copy link
Contributor

@roccotripaldi roccotripaldi commented Jun 10, 2025

Submission Review Guidelines:

Changes proposed in this Pull Request:

The issue:

In WC_Data->set_date_prop assumes that the value of the date, if it is not an int or a WC_DateTime object, will be a string. It will attempt to run preg_match on the value, without fully ensuring the value is of type string. This will result in fatals in rare cases when the value is something other than an int, a WC_DateTime object, or a string.

My fix:

Make sure the value is actually a string before running preg_match. If it's not a string, throw an exception.

Closes #58401

How to test the changes in this Pull Request:

~Testing the actually failure is difficult because it requires having a Woo store with older data. ~

Here is a patch to emulate the error from the bug report:
debug.patch

We can emulate the error like this:

  1. On your testing site, checkout trunk
  2. In WP Admin, create an order and apply a coupon to the order.
  3. Using Postman or Curl send a GET request to /wp-json/wc/v3/orders
  4. You should receive a 200 response.
  5. Apply the patch above, and resend the request.
  6. You'll get a 500 error.

Test the fix in this PR:

  1. Check out this PR, and send the request again.
  2. You should get a 200.

You can remove the patch, and finally test:

  1. That GET requests to wp-json/wc/v3/orders continue to work.
  2. That there are no side effects from the new Exception introduced in this PR. We can ensure this by merging this PR into a beta release.

Testing that has already taken place:

I've run through the testing instructions above a few times, and made sure the issue goes away.

I did make some attempts to unit test here, but I wasn't able to create a test that worked, or made any sense!

See my latest commit:
9682157

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

Changelog Entry Comment

Comment

Fixes a bug where listing Woo orders on the REST API will crash if the order has a coupon with a malformed date.

Summary by CodeRabbit

  • Bug Fixes

    • Resolved an issue where retrieving orders with coupons containing malformed dates in the WooCommerce REST API could cause a crash.
    • Improved error handling for invalid date inputs to prevent similar issues in the future.
  • Style

    • Minor formatting improvements for code readability.

@github-actions github-actions bot added the plugin: woocommerce Issues related to the WooCommerce Core plugin. label Jun 10, 2025
@roccotripaldi roccotripaldi requested review from a team and naman03malhotra and removed request for a team June 10, 2025 20:14
Copy link
Contributor

github-actions bot commented Jun 10, 2025

Testing Guidelines

Hi @naman03malhotra ,

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.

@roccotripaldi roccotripaldi marked this pull request as ready for review June 11, 2025 21:15
Copy link
Contributor

github-actions bot commented Jun 11, 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.

Copy link
Contributor

@naman03malhotra naman03malhotra left a comment

Choose a reason for hiding this comment

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

Testing the actual failure is difficult because it requires having a Woo store with older data.

👋 Hey Rooco, thanks for taking this forward.
Would it be possible to simulate the behavior that might be causing this issue? I believe it’s important to replicate the exact scenario before proposing a fix that will help us to remove any uncertainty. One approach could be to manually adjust the relevant database values (or use a temporary data stub) to mimic older store data and observe the outcome.

@roccotripaldi
Copy link
Contributor Author

@naman03malhotra challenge accepted.

Copy link
Contributor

coderabbitai bot commented Jun 13, 2025

Walkthrough

This change refines error handling for date properties in WooCommerce's data abstraction, ensuring that invalid date inputs—such as malformed coupon dates—trigger explicit errors instead of causing a TypeError. The update directly addresses a REST API crash when orders contain coupons with incorrectly formatted dates.

Changes

File(s) Change Summary
plugins/woocommerce/includes/abstracts/abstract-wc-data.php Improved error handling in set_date_prop to explicitly catch and report invalid date types; docblock updates.
plugins/woocommerce/rest-api/Controllers/Version2/class-wc-rest-orders-v2-controller.php Removed an extraneous blank line in coupon meta handling (no logic change).
plugins/woocommerce/changelog/58700-wooplug-4457-rest-api-orders-get-with-coupons-has-typeerror-preg_match Added changelog entry describing the REST API orders/coupon date bug fix.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant REST API (Orders)
    participant WC_Data (Order/Coupon)
    participant Error Handler

    Client->>REST API (Orders): GET /wc/v3/orders
    REST API (Orders)->>WC_Data (Order/Coupon): set_date_prop(date_created, value)
    alt value is WC_DateTime, numeric, or string
        WC_Data (Order/Coupon)-->>REST API (Orders): Set date property
    else value is invalid (e.g., stdClass)
        WC_Data (Order/Coupon)->>Error Handler: error('invalid_date', ...)
        Error Handler-->>REST API (Orders): Return error response
    end
    REST API (Orders)-->>Client: Return orders or error message
Loading

Assessment against linked issues

Objective Addressed Explanation
Prevent REST API 500 error when querying orders with coupon line items due to TypeError in preg_match (stdClass given instead of string) (#58401)
Ensure robust handling of coupon date_created data types in REST API responses to prevent type errors (#58401)
REST API request should succeed or return a proper error message without crashing when encountering malformed coupon date data (#58401)
The fix should be isolated to WooCommerce core logic and not rely on other plugins or themes (#58401)

Poem

In WooCommerce fields where the coupons play,
A bug once lurked, causing orders to sway.
With dates now checked, and errors made clear,
No more TypeErrors for shoppers to fear!
So rabbits rejoice, with a hop and a cheer—
The REST API’s safe, and the checkout sincere!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

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.
    • Explain this complex logic.
    • 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. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai 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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • 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

🧹 Nitpick comments (3)
plugins/woocommerce/includes/abstracts/abstract-wc-data.php (3)

22-24: Replace placeholder x.x.x with a concrete version before release

Doc-block placeholders are useful during development, but should be resolved to an actual version tag (e.g. @since 8.9.0) before the code lands in trunk, otherwise the generated developer docs become ambiguous.

Also applies to: 30-30


908-910: Follow WP coding-standards: use elseif, not else if

The surrounding codebase consistently uses elseif. Switching to the canonical form avoids scrutiny from PHPCS and keeps the file stylistically uniform.

-           } else if( is_string( $value ) ) {
+           } elseif ( is_string( $value ) ) {

917-920: Consider logging the swallowed invalid_date exception

$this->error() throws a WC_Data_Exception, but the catch immediately swallows all exceptions. While this is an intentional “fail-soft” pattern, completely ignoring the error makes debugging harder.

A lightweight compromise:

-           // If we get here, the value is not a valid date.
-           $this->error( 'invalid_date', __( 'Invalid date provided.', 'woocommerce' ) );
+           // If we get here, the value is not a valid date.
+           $this->error( 'invalid_date', __( 'Invalid date provided.', 'woocommerce' ) );
-       } catch ( Exception $e ) {} // @codingStandardsIgnoreLine.
+       } catch ( Exception $e ) {
+           // Surface in debug logs while still failing softly for end-users.
+           wc_get_logger()->debug(
+               sprintf( 'set_date_prop(%s) failed: %s', $prop, $e->getMessage() ),
+               array( 'source' => 'wc-data' )
+           );
+       }

This keeps the public behaviour unchanged yet leaves a breadcrumb trail for site owners.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ab07d51 and a5bf0fe.

📒 Files selected for processing (3)
  • plugins/woocommerce/changelog/58700-wooplug-4457-rest-api-orders-get-with-coupons-has-typeerror-preg_match (1 hunks)
  • plugins/woocommerce/includes/abstracts/abstract-wc-data.php (3 hunks)
  • plugins/woocommerce/includes/rest-api/Controllers/Version2/class-wc-rest-orders-v2-controller.php (0 hunks)
💤 Files with no reviewable changes (1)
  • plugins/woocommerce/includes/rest-api/Controllers/Version2/class-wc-rest-orders-v2-controller.php
⏰ Context from checks skipped due to timeout of 90000ms (24)
  • GitHub Check: Blocks e2e tests 7/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 9/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 10/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 6/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core API tests - @woocommerce/plugin-woocommerce [api]
  • GitHub Check: Blocks e2e tests 8/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 5/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 4/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core e2e tests 3/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core e2e tests 5/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core e2e tests 1/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core e2e tests 4/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Metrics - @woocommerce/plugin-woocommerce [performance]
  • GitHub Check: Blocks e2e tests 3/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 1/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Blocks e2e tests 2/10 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: PHP: 8.4 WP: latest [WP latest] 1/2 - @woocommerce/plugin-woocommerce [unit:php]
  • GitHub Check: Core e2e tests 6/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: Core e2e tests 2/6 - @woocommerce/plugin-woocommerce [e2e]
  • GitHub Check: PHP: 8.4 WP: latest [WP latest] 2/2 - @woocommerce/plugin-woocommerce [unit:php]
  • GitHub Check: PHP: 7.4 WP: latest - 1 [WP 6.7.2] 2/2 - @woocommerce/plugin-woocommerce [unit:php]
  • GitHub Check: PHP: 7.4 WP: latest - 1 [WP 6.7.2] 1/2 - @woocommerce/plugin-woocommerce [unit:php]
  • GitHub Check: Lint - @woocommerce/plugin-woocommerce
  • GitHub Check: build
🔇 Additional comments (1)
plugins/woocommerce/changelog/58700-wooplug-4457-rest-api-orders-get-with-coupons-has-typeerror-preg_match (1)

1-4: Changelog entry looks good

Clear, concise, and formatted per the existing convention.

@PanosSynetos
Copy link
Contributor

@roccotripaldi make sure to check the failing tests. For example, linting failed on this PR

. lint:changes:branch:php: FILE: plugins/woocommerce/includes/abstracts/abstract-wc-data.php
. lint:changes:branch:php: -----------------------------------------------------------------------------------------------
. lint:changes:branch:php: FOUND 3 ERRORS AND 1 WARNING AFFECTING 4 LINES
. lint:changes:branch:php: -----------------------------------------------------------------------------------------------
. lint:changes:branch:php:  908 | WARNING | Usage of ELSE IF is discouraged; use ELSEIF instead (PSR2.ControlStructures.ElseIfDeclaration.NotAllowed)
. lint:changes:branch:php:  908 | ERROR | Space after opening control structure is required (WordPress.WhiteSpace.ControlStructureSpacing.NoSpaceAfterStructureOpen)
. lint:changes:branch:php:  908 | ERROR | No space before opening parenthesis is prohibited (WordPress.WhiteSpace.ControlStructureSpacing.NoSpaceBeforeOpenParenthesis)
. lint:changes:branch:php:  908 | ERROR | Expected 1 space after IF keyword; 0 found (Squiz.ControlStructures.ControlSignature.SpaceAfterKeyword)

Coderabbit has also made some suggestions, check them out if they are valid :) Thanks to both of you @naman03malhotra and @roccotripaldi for driving this forward

Copy link
Contributor

@naman03malhotra naman03malhotra left a comment

Choose a reason for hiding this comment

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

Hey Rocco, thanks for taking it forward. Please do take a look at the failing linter CI and tests, as Panos mentioned. Additionally, it is important that we test this change to ensure it remains future-proof against any unintended alterations.

I'll take a proper look at it next week.

@roccotripaldi
Copy link
Contributor Author

Thanks for the review Naman. I spent 2 hours today trying to write a unit test for this, but I couldn't figure out how. There are higher priorities now, so I don't want to spend too much time with this. I'll close this PR, but maybe someone with more Woo experience can take a try at a later date.

@roccotripaldi roccotripaldi deleted the wooplug-4457-rest-api-orders-get-with-coupons-has-typeerror-preg_match branch July 2, 2025 19:26
@PanosSynetos PanosSynetos reopened this Jul 3, 2025
@PanosSynetos
Copy link
Contributor

Hey @roccotripaldi - before closing the PR, let's discuss what you tested, if you were able to replicate or not the issue , so the next one is aware.

Thank you

@roccotripaldi
Copy link
Contributor Author

Hey @roccotripaldi - before closing the PR, let's discuss what you tested, if you were able to replicate or not the issue , so the next one is aware.

Thanks for that Panos. I didn't believe there was any value in this PR, but maybe their is! I've updated the PR description to better summarize my fix, and what I've tried.

@naman03malhotra naman03malhotra self-requested a review July 11, 2025 13:10
Copy link
Contributor

@naman03malhotra naman03malhotra left a comment

Choose a reason for hiding this comment

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

Hey @roccotripaldi your fix looks good, I've tested it with mutiple invalid date formats and I am able to reproduce it with the instructions you mentioned.

I've created a followup PR to add test for this to make sure we don't regress, I've assigned it for the review: #60022

Copy link
Contributor

@naman03malhotra naman03malhotra left a comment

Choose a reason for hiding this comment

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

Once we merge the next PR with tests: #60022, the next step would be to fix the lint issues and make sure everything is green before we merge.

Copy link
Contributor

@naman03malhotra naman03malhotra left a comment

Choose a reason for hiding this comment

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

Looking good now overall, let's merge when tests are green!

@@ -19,7 +19,7 @@
*
* Implemented by classes using the same CRUD(s) pattern.
*
* @version 2.6.0
* @version x.x.x
Copy link
Contributor

Choose a reason for hiding this comment

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

So in core we don't rename it to x.x.x, we add the exact version, i.e the version this PR will be released with.

Also, I think we add @SInCE to preserve the original version.

Copy link
Contributor

Choose a reason for hiding this comment

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

What @naman03malhotra said :)

@since    2.6.0
@version  10.2.0

Copy link
Contributor

@naman03malhotra naman03malhotra left a comment

Choose a reason for hiding this comment

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

Hey @roccotripaldi, this should be good to go, I've merged the PR for tests #60022, once the CI passed and some minor feedback to be addressed in the PR.

@naman03malhotra
Copy link
Contributor

CI is passing now after the fresh pull from trunk.

@roccotripaldi roccotripaldi added this to the 10.2.0 milestone Aug 1, 2025
@roccotripaldi roccotripaldi dismissed naman03malhotra’s stale review August 1, 2025 13:01

Naman gave his thumbs up and all feedback was addressed.

Copy link
Contributor

@naman03malhotra naman03malhotra left a comment

Choose a reason for hiding this comment

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

Approving as CI is passing! testing well and the test PR #60022 is also merged!

@naman03malhotra
Copy link
Contributor

@roccotripaldi this is ready to be merged, but I'll let you do the honors.

@PanosSynetos PanosSynetos merged commit ae189f7 into trunk Aug 4, 2025
37 checks passed
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.

REST API orders GET with coupons has TypeError: preg_match Argument 2 must be of type string stdClass given abstract-wc-data.php:910
3 participants