-
Notifications
You must be signed in to change notification settings - Fork 10.7k
Add experimental emails settings API to V4 #61849
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
Add experimental emails settings API to V4 #61849
Conversation
Testing GuidelinesHi @yuliyan @woocommerce/ballade, 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:
|
|
Claude finished @costasovo's task —— View job Backwards Compatibility ReviewSummaryOverall Risk: None ✅ This PR introduces a new experimental V4 REST API endpoint ( The codebase remains fully backwards compatible with no deprecations required. Detailed Analysis1. REST API Changes (New endpoints only - No BC impact)New Endpoint:
// plugins/woocommerce/includes/rest-api/Server.php:242-245
'settings-general' => GeneralSettingsController::class,
'settings-email' => EmailSettingsController::class, // Existing
'settings-emails' => EmailsSettingsController::class, // New (this PR)
'settings-products' => SettingsProductsController::class,Schema Differences:
2. PHP API Changes (Additive only - No BC impact)WC_Email Base Class:
// plugins/woocommerce/includes/emails/class-wc-email.php:1191-1193
if ( $this->block_email_editor_enabled ) {
$this->form_fields['preheader'] = $this->get_preheader_field();
}Email Subclasses (7 files modified):
3. Hook Changes (Reusing existing hook - No BC impact)Hook Used:
No hooks removed or renamed. 4. Schema & Data Handling (Addressed concerns)Recipient Field Validation (Mentioned in PR description as known issue):
Personalization Tag Handling:
Permalink Null Safety (Fixed in commit
5. Template ChangesNo template files modified - confirmed via git diff. 6. Ecosystem Impact AssessmentExtensions using WC_Email:
Extensions using REST API:
Theme Customizations:
7. Database & OptionsNo schema changes - Uses existing WP options system ( Testing FocusGiven the additive nature of these changes, testing should focus on:
Confidence95% - High confidence in the backwards compatibility assessment. Justification: All changes are purely additive (new endpoint, new protected method, conditional form fields). The implementation follows established WooCommerce patterns, reuses existing hooks, and includes proper feature flagging. The PR author has explicitly noted the recipient validation issue as a known follow-up item, and the current implementation correctly handles it by using The 5% uncertainty accounts for potential edge cases in third-party extensions that might:
|
Instead of hardcoded prefixes the settings API now supports all known prefixes. WOOPRD-926
1528a5e to
e7e330a
Compare
📝 WalkthroughWalkthroughAdds an experimental V4 REST API for email settings (listing, retrieval, update) with a schema that handles personalization-tag wrapping/unwrapping, validation and sanitization; adds conditional Changes
Sequence Diagram(s)sequenceDiagram
participant Client as REST Client
participant Controller as EmailsSettingsController
participant Schema as EmailsSettingsSchema
participant Email as WC_Email
participant Storage as Option Storage
Note over Client,Storage: GET /wc/v4/settings/emails or /settings/emails/{id}
Client->>Controller: GET request
Controller->>Controller: permissions check
Controller->>Email: locate email(s)
Controller->>Schema: get_item_response(email)
Schema->>Email: read form fields & values
Schema->>Schema: unwrap personalization tags (subject, preheader)
Schema->>Controller: formatted response
Controller->>Client: 200 OK + payload
Note over Client,Storage: PUT /wc/v4/settings/emails/{id}
Client->>Controller: PUT request + payload
Controller->>Controller: permissions check
Controller->>Schema: validate_and_sanitize_settings(email, payload)
Schema->>Schema: unwrap tags -> sanitize -> validate
alt validation fails
Schema-->>Controller: WP_Error
Controller->>Client: 400 Bad Request
else validation passes
Controller->>Email: apply updated values
Controller->>Storage: persist options
Schema->>Schema: wrap personalization tags as needed
Controller->>Client: 200 OK + updated payload
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ 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 |
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Email/EmailSettingsControllerTest.php (1)
55-97: Restore the original block editor toggle instead of hard-coding it to “no” after tests
setUp()forceswoocommerce_feature_block_email_editor_enabledto'yes', buttearDown()always resets it to'no'. If another test (or the default fixture) expects that option to remain'yes'or to stay unset, this suite will leave it in the wrong state, causing order-dependent failures. Please capture the prior value in$this->prev_optionsbefore you flip it on, let the existing restoration loop put it back exactly as it was, and drop the hard-coded'no'.Apply something like:
public function setUp(): void { // Enable the v4 REST API feature before bootstrapping. $this->feature_filter = function ( $features ) { $features[] = 'rest-api-v4'; return $features; }; add_filter( 'woocommerce_admin_features', $this->feature_filter ); - parent::setUp(); - // Enable block email editor feature to test reply-to fields. - update_option( 'woocommerce_feature_block_email_editor_enabled', 'yes' ); + parent::setUp(); + $this->prev_options['woocommerce_feature_block_email_editor_enabled'] + = get_option( 'woocommerce_feature_block_email_editor_enabled', null ); + update_option( 'woocommerce_feature_block_email_editor_enabled', 'yes' ); // Snapshot current option values to restore on tearDown. $option_ids = array( 'woocommerce_email_from_name',and in
tearDown()let the existing loop restore the saved value, deleting it when the previous value wasnull, instead of forcing'no'.
🧹 Nitpick comments (1)
plugins/woocommerce/includes/emails/class-wc-email.php (1)
1230-1244: Consider enforcing the 150 character limit mentioned in the description.The field description informs users about a "Max 150 characters" limit, but this constraint is not enforced in the field definition. While email clients will handle overly long preheaders gracefully, adding validation would improve the user experience and data quality.
Consider adding a
maxlengthattribute or custom validation:protected function get_preheader_field() { return array( 'title' => __( 'Preheader', 'woocommerce' ), 'description' => __( 'Shown as a preview in the Inbox, next to the subject line. (Max 150 characters).', 'woocommerce' ), 'placeholder' => '', 'type' => 'text', 'default' => '', 'desc_tip' => true, + 'custom_attributes' => array( + 'maxlength' => 150, + ), ); }Alternatively, verify that the V4 REST API endpoint (mentioned in PR objectives) enforces this limit on the server side.
📜 Review details
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
plugins/woocommerce/changelog/wooprd-926-move-notifications-listing-api-to-woocommerce(1 hunks)plugins/woocommerce/includes/emails/class-wc-email-cancelled-order.php(1 hunks)plugins/woocommerce/includes/emails/class-wc-email-customer-cancelled-order.php(1 hunks)plugins/woocommerce/includes/emails/class-wc-email-customer-invoice.php(1 hunks)plugins/woocommerce/includes/emails/class-wc-email-customer-pos-refunded-order.php(1 hunks)plugins/woocommerce/includes/emails/class-wc-email-customer-refunded-order.php(1 hunks)plugins/woocommerce/includes/emails/class-wc-email-failed-order.php(1 hunks)plugins/woocommerce/includes/emails/class-wc-email-new-order.php(1 hunks)plugins/woocommerce/includes/emails/class-wc-email.php(2 hunks)plugins/woocommerce/includes/rest-api/Server.php(2 hunks)plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Controller.php(1 hunks)plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php(1 hunks)plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Email/EmailSettingsControllerTest.php(1 hunks)plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{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/emails/class-wc-email-customer-cancelled-order.phpplugins/woocommerce/includes/emails/class-wc-email.phpplugins/woocommerce/includes/rest-api/Server.phpplugins/woocommerce/includes/emails/class-wc-email-customer-refunded-order.phpplugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Email/EmailSettingsControllerTest.phpplugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.phpplugins/woocommerce/includes/emails/class-wc-email-new-order.phpplugins/woocommerce/includes/emails/class-wc-email-failed-order.phpplugins/woocommerce/includes/emails/class-wc-email-customer-pos-refunded-order.phpplugins/woocommerce/includes/emails/class-wc-email-customer-invoice.phpplugins/woocommerce/includes/emails/class-wc-email-cancelled-order.phpplugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Controller.phpplugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php
**/*.{php,js,jsx,tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/avoid-regex.mdc)
**/*.{php,js,jsx,tsx,ts}: Avoid using regular expressions unless absolutely necessary to favor readability and maintainability
Only consider regex when no built-in language alternative (string/array APIs) fits the need
Only use regex when performance is critical and faster than alternatives, with measurements to justify
Use regex for complex pattern matching only if the pattern is well-documented and thoroughly tested
Allow regex when maintaining legacy code where an existing, correct pattern is being modified
If regex is necessary, document the pattern extensively to explain what it matches
If regex is necessary, add comprehensive tests covering edge cases and potential security issues
Use named capture groups in regex to improve readability when supported
Validate input before applying regex to ensure it is safe
Assess and mitigate security risks when using regex, including ReDoS and injection vulnerabilities
Avoid regex patterns that can cause catastrophic backtracking (ReDoS)
Do not construct regex from untrusted input to prevent injection attacks
Ensure regex patterns do not overmatch and unintentionally capture unexpected inputs
Files:
plugins/woocommerce/includes/emails/class-wc-email-customer-cancelled-order.phpplugins/woocommerce/includes/emails/class-wc-email.phpplugins/woocommerce/includes/rest-api/Server.phpplugins/woocommerce/includes/emails/class-wc-email-customer-refunded-order.phpplugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Email/EmailSettingsControllerTest.phpplugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.phpplugins/woocommerce/includes/emails/class-wc-email-new-order.phpplugins/woocommerce/includes/emails/class-wc-email-failed-order.phpplugins/woocommerce/includes/emails/class-wc-email-customer-pos-refunded-order.phpplugins/woocommerce/includes/emails/class-wc-email-customer-invoice.phpplugins/woocommerce/includes/emails/class-wc-email-cancelled-order.phpplugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Controller.phpplugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.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.
When making any changes to code that deletes or modifies orders/products/customer data, make sure that there are
sufficient checks in place to prevent accidental data loss. As an example, if deleting a draft order, check that
the order status is indeeddraftorcheckout-draft. Also think about whether race conditions could occur and
delete orders that don't belong to the current customer. When in doubt, ask for clarification in the PR comments.
Files:
plugins/woocommerce/includes/emails/class-wc-email-customer-cancelled-order.phpplugins/woocommerce/includes/emails/class-wc-email.phpplugins/woocommerce/includes/rest-api/Server.phpplugins/woocommerce/includes/emails/class-wc-email-customer-refunded-order.phpplugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Email/EmailSettingsControllerTest.phpplugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.phpplugins/woocommerce/includes/emails/class-wc-email-new-order.phpplugins/woocommerce/includes/emails/class-wc-email-failed-order.phpplugins/woocommerce/includes/emails/class-wc-email-customer-pos-refunded-order.phpplugins/woocommerce/includes/emails/class-wc-email-customer-invoice.phpplugins/woocommerce/includes/emails/class-wc-email-cancelled-order.phpplugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Controller.phpplugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.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/src/Internal/RestApi/Routes/V4/Settings/Email/EmailSettingsControllerTest.phpplugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php
🧠 Learnings (13)
📚 Learning: 2025-08-27T21:13:11.131Z
Learnt from: allilevine
Repo: woocommerce/woocommerce PR: 60514
File: packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-table.php:253-255
Timestamp: 2025-08-27T21:13:11.131Z
Learning: In WooCommerce Email Editor table block renderer (packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-table.php), header and footer borders in the add_header_footer_borders method are intentionally always solid style, not meant to inherit custom border styles. Custom border styles will override these solid borders when applied, creating a proper styling hierarchy.
Applied to files:
plugins/woocommerce/includes/emails/class-wc-email.php
📚 Learning: 2025-06-23T16:55:58.246Z
Learnt from: lysyjan
Repo: woocommerce/woocommerce PR: 59070
File: packages/php/email-editor/src/Integrations/Core/class-initializer.php:103-141
Timestamp: 2025-06-23T16:55:58.246Z
Learning: The core/spacer block in the WooCommerce email editor intentionally does not have a dedicated renderer class and is handled by the fallback renderer instead of having an explicit render_email_callback assigned in the switch statement.
Applied to files:
plugins/woocommerce/includes/emails/class-wc-email.phpplugins/woocommerce/includes/emails/class-wc-email-customer-refunded-order.phpplugins/woocommerce/includes/emails/class-wc-email-failed-order.php
📚 Learning: 2025-06-26T12:13:32.062Z
Learnt from: triple0t
Repo: woocommerce/woocommerce PR: 59186
File: packages/js/email-editor/src/store/initial-state.ts:9-10
Timestamp: 2025-06-26T12:13:32.062Z
Learning: In WooCommerce email editor store initialization (packages/js/email-editor/src/store/initial-state.ts), the current_post_id and current_post_type from window.WooCommerceEmailEditor are required parameters that should cause explicit errors if missing, rather than using fallback values or optional chaining. The design preference is to fail fast when critical initialization data is unavailable.
Applied to files:
plugins/woocommerce/includes/emails/class-wc-email.phpplugins/woocommerce/includes/emails/class-wc-email-new-order.phpplugins/woocommerce/includes/emails/class-wc-email-failed-order.phpplugins/woocommerce/includes/emails/class-wc-email-customer-pos-refunded-order.phpplugins/woocommerce/includes/emails/class-wc-email-cancelled-order.php
📚 Learning: 2025-08-21T07:39:42.952Z
Learnt from: NeosinneR
Repo: woocommerce/woocommerce PR: 60520
File: plugins/woocommerce/src/Internal/Admin/EmailPreview/EmailPreview.php:257-259
Timestamp: 2025-08-21T07:39:42.952Z
Learning: In WooCommerce email preview functionality (EmailPreview.php), rel attributes on links should be overwritten rather than preserved for safety reasons, and anchor links (#) can be treated the same as external links since they're not expected in email previews.
Applied to files:
plugins/woocommerce/includes/emails/class-wc-email.phpplugins/woocommerce/includes/emails/class-wc-email-new-order.php
📚 Learning: 2025-08-19T10:42:44.153Z
Learnt from: yuliyan
Repo: woocommerce/woocommerce PR: 60354
File: packages/php/email-editor/src/Engine/class-settings-controller.php:191-205
Timestamp: 2025-08-19T10:42:44.153Z
Learning: WooCommerce email editor supports WordPress versions newer than 5.5. WordPress 5.5 and older versions are outside the supported range, so backward compatibility considerations for those versions (such as including `wp-block-library-theme-css` for older WP theme styles) are not necessary.
Applied to files:
plugins/woocommerce/includes/emails/class-wc-email.phpplugins/woocommerce/includes/emails/class-wc-email-new-order.php
📚 Learning: 2025-08-08T13:47:37.272Z
Learnt from: lysyjan
Repo: woocommerce/woocommerce PR: 60165
File: plugins/woocommerce/src/Internal/EmailEditor/PageRenderer.php:100-104
Timestamp: 2025-08-08T13:47:37.272Z
Learning: In WooCommerce email editor PHP package (packages/php/email-editor), the localization data passed through the `woocommerce_email_editor_script_localization_data` filter always includes the `editor_settings` key as an array (prepared by `Assets_Manager`). This guarantees nested writes like `['editor_settings']['isFullScreenForced']` are safe in PageRenderer::update_localized_data().
Applied to files:
plugins/woocommerce/includes/emails/class-wc-email.phpplugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php
📚 Learning: 2025-07-15T15:39:21.856Z
Learnt from: jorgeatorres
Repo: woocommerce/woocommerce PR: 59675
File: .github/workflows/release-bump-as-requirement.yml:48-65
Timestamp: 2025-07-15T15:39:21.856Z
Learning: In WooCommerce core repository, changelog entries for all PRs live in `plugins/woocommerce/changelog/` directory and are processed during releases, not at the repository root level.
Applied to files:
plugins/woocommerce/changelog/wooprd-926-move-notifications-listing-api-to-woocommerce
📚 Learning: 2025-09-03T11:50:02.208Z
Learnt from: tpaksu
Repo: woocommerce/woocommerce PR: 60735
File: plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version4/Fulfillments/class-wc-rest-fulfillments-v4-controller-tests.php:10-10
Timestamp: 2025-09-03T11:50:02.208Z
Learning: For REST API controller tests in plugins/woocommerce/tests/**/*.php, test classes should extend WC_REST_Unit_Test_Case instead of WC_Unit_Test_Case because REST routes need to be registered before tests run.
Applied to files:
plugins/woocommerce/includes/rest-api/Server.phpplugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Email/EmailSettingsControllerTest.phpplugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.phpplugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Controller.php
📚 Learning: 2025-08-18T06:11:48.768Z
Learnt from: CR
Repo: woocommerce/woocommerce PR: 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/src/Internal/RestApi/Routes/V4/Settings/Email/EmailSettingsControllerTest.phpplugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php
📚 Learning: 2025-08-18T06:11:48.768Z
Learnt from: CR
Repo: woocommerce/woocommerce PR: 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/src/Internal/RestApi/Routes/V4/Settings/Email/EmailSettingsControllerTest.phpplugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php
📚 Learning: 2025-10-23T01:44:03.397Z
Learnt from: peterwilsoncc
Repo: woocommerce/woocommerce PR: 60447
File: plugins/woocommerce/templates/emails/email-order-details.php:96-131
Timestamp: 2025-10-23T01:44:03.397Z
Learning: In WooCommerce email templates (plugins/woocommerce/templates/emails/), when displaying order details, the order items table and order totals should be separate tables rather than combined with <tfoot>. This follows accessibility guidance: the totals are semantically different information from the line items and should not be forced into a single table structure just for visual positioning. The split improves accessibility for assistive technology users.
Applied to files:
plugins/woocommerce/includes/emails/class-wc-email-new-order.php
📚 Learning: 2025-06-26T14:25:08.421Z
Learnt from: NeosinneR
Repo: woocommerce/woocommerce PR: 0
File: :0-0
Timestamp: 2025-06-26T14:25:08.421Z
Learning: In WooCommerce transactional emails, product images have historically had display issues due to lazy loading attributes being applied, which email clients cannot process since they don't execute JavaScript. This issue existed in both old and new email templates, but became more visible with the new email template system. The fix involves preventing lazy loading on attachment images specifically during email generation by adding skip classes and data attributes.
Applied to files:
plugins/woocommerce/includes/emails/class-wc-email-new-order.phpplugins/woocommerce/includes/emails/class-wc-email-failed-order.php
📚 Learning: 2025-07-29T08:05:14.107Z
Learnt from: lysyjan
Repo: woocommerce/woocommerce PR: 60072
File: packages/php/email-editor/src/Engine/PersonalizationTags/class-personalization-tags-registry.php:110-118
Timestamp: 2025-07-29T08:05:14.107Z
Learning: In WooCommerce email editor personalization tags registry (packages/php/email-editor/src/Engine/PersonalizationTags/class-personalization-tags-registry.php), the get_by_post_type method is designed to return tags with empty post_types arrays regardless of the input post_type parameter (even if empty/whitespace). This is the intended behavior as tags with empty post_types are considered universal tags that apply to all post types.
Applied to files:
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php
🧬 Code graph analysis (11)
plugins/woocommerce/includes/emails/class-wc-email-customer-cancelled-order.php (1)
plugins/woocommerce/includes/emails/class-wc-email.php (1)
get_preheader_field(1235-1244)
plugins/woocommerce/includes/rest-api/Server.php (1)
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Controller.php (1)
Controller(27-351)
plugins/woocommerce/includes/emails/class-wc-email-customer-refunded-order.php (1)
plugins/woocommerce/includes/emails/class-wc-email.php (1)
get_preheader_field(1235-1244)
plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php (5)
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php (2)
EmailsSettingsSchema(27-621)init(61-63)plugins/woocommerce/src/Internal/EmailEditor/WCTransactionalEmails/WCTransactionalEmailPostsGenerator.php (1)
WCTransactionalEmailPostsGenerator(21-273)packages/php/email-editor/src/class-email-editor-container.php (1)
Email_Editor_Container(45-304)packages/php/email-editor/src/Engine/PersonalizationTags/class-personalization-tags-registry.php (1)
Personalization_Tags_Registry(17-140)packages/php/email-editor/src/Engine/PersonalizationTags/class-personalization-tag.php (1)
Personalization_Tag(16-203)
plugins/woocommerce/includes/emails/class-wc-email-new-order.php (1)
plugins/woocommerce/includes/emails/class-wc-email.php (1)
get_preheader_field(1235-1244)
plugins/woocommerce/includes/emails/class-wc-email-failed-order.php (1)
plugins/woocommerce/includes/emails/class-wc-email.php (1)
get_preheader_field(1235-1244)
plugins/woocommerce/includes/emails/class-wc-email-customer-pos-refunded-order.php (1)
plugins/woocommerce/includes/emails/class-wc-email.php (1)
get_preheader_field(1235-1244)
plugins/woocommerce/includes/emails/class-wc-email-customer-invoice.php (1)
plugins/woocommerce/includes/emails/class-wc-email.php (1)
get_preheader_field(1235-1244)
plugins/woocommerce/includes/emails/class-wc-email-cancelled-order.php (1)
plugins/woocommerce/includes/emails/class-wc-email.php (1)
get_preheader_field(1235-1244)
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Controller.php (5)
plugins/woocommerce/src/Internal/RestApi/Routes/V4/AbstractController.php (1)
AbstractController(30-323)plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php (4)
EmailsSettingsSchema(27-621)init(61-63)get_item_response(219-246)validate_and_sanitize_settings(440-476)plugins/woocommerce/includes/rest-api/Server.php (1)
init(46-50)plugins/woocommerce/includes/wc-rest-functions.php (1)
wc_rest_check_manager_permissions(341-355)plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Email/Controller.php (1)
Controller(27-416)
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php (5)
packages/php/email-editor/src/class-email-editor-container.php (1)
Email_Editor_Container(45-304)plugins/woocommerce/src/Internal/RestApi/Routes/V4/AbstractSchema.php (1)
AbstractSchema(26-106)packages/php/email-editor/src/Engine/PersonalizationTags/class-personalization-tags-registry.php (1)
Personalization_Tags_Registry(17-140)plugins/woocommerce/includes/emails/class-wc-email.php (6)
WC_Email(33-1710)is_customer_email(828-830)is_manual(819-821)get_recipient(605-619)get_preheader(565-580)get_additional_content(522-533)plugins/woocommerce/includes/wc-formatting-functions.php (1)
wc_bool_to_string(37-42)
🪛 PHPMD (2.15.0)
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Controller.php
109-109: Avoid unused parameters such as '$request'. (undefined)
(UnusedFormalParameter)
136-136: Avoid unused parameters such as '$request'. (undefined)
(UnusedFormalParameter)
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php
219-219: Avoid unused parameters such as '$request'. (undefined)
(UnusedFormalParameter)
⏰ 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). (31)
- GitHub Check: Blocks e2e tests - Legacy MiniCart 1/3 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Blocks e2e tests 8/10 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Blocks e2e tests - Legacy MiniCart 2/3 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Blocks e2e tests 6/10 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Blocks e2e tests 9/10 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: PHP: 7.4 WP: latest - 1 [WP 6.7.4] 1/2 - @woocommerce/plugin-woocommerce [unit:php]
- GitHub Check: Blocks e2e tests 10/10 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Blocks e2e tests 7/10 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Blocks e2e tests 4/10 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Blocks e2e tests 5/10 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Metrics - @woocommerce/plugin-woocommerce [performance]
- GitHub Check: Blocks e2e tests 3/10 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: PHP: 8.4 WP: latest (HPOS:off) [WP latest] 2/2 - @woocommerce/plugin-woocommerce [unit:php]
- GitHub Check: Blocks e2e tests 2/10 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Core e2e tests 6/6 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Blocks e2e tests 1/10 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: PHP: 8.4 WP: latest (HPOS:off) [WP latest] 1/2 - @woocommerce/plugin-woocommerce [unit:php]
- GitHub Check: Core API tests - @woocommerce/plugin-woocommerce [api]
- 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: pre-release [WP 6.9-beta3] 2/2 - @woocommerce/plugin-woocommerce [unit:php] (optional)
- GitHub Check: Core e2e tests 3/6 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Core e2e tests 2/6 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: PHP: 7.4 WP: latest - 1 [WP 6.7.4] 2/2 - @woocommerce/plugin-woocommerce [unit:php]
- GitHub Check: PHP: 7.4 WP: pre-release [WP 6.9-beta3] 1/2 - @woocommerce/plugin-woocommerce [unit:php] (optional)
- GitHub Check: PHP: 8.4 WP: latest [WP latest] 1/2 - @woocommerce/plugin-woocommerce [unit:php]
- GitHub Check: Core e2e tests 1/6 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: PHP: 8.4 WP: latest - Legacy MiniCart [WP latest] 2/2 - @woocommerce/plugin-woocommerce [unit:php]
- GitHub Check: PHP: 8.4 WP: latest - Legacy MiniCart [WP latest] 1/2 - @woocommerce/plugin-woocommerce [unit:php]
- GitHub Check: PHP: 8.4 WP: latest [WP latest] 2/2 - @woocommerce/plugin-woocommerce [unit:php]
- GitHub Check: build
🔇 Additional comments (11)
plugins/woocommerce/changelog/wooprd-926-move-notifications-listing-api-to-woocommerce (1)
1-5: LGTM!The changelog entry is well-formed and appropriately categorized as a patch-level addition for the experimental V4 settings/emails API.
plugins/woocommerce/includes/emails/class-wc-email.php (1)
1191-1193: LGTM!The conditional addition of the preheader field is properly gated behind the
block_email_editor_enabledfeature flag, ensuring backward compatibility.plugins/woocommerce/includes/emails/class-wc-email-cancelled-order.php (1)
234-236: LGTM!The preheader field is correctly added using the inherited method, following the same pattern as the cc/bcc fields above it.
plugins/woocommerce/includes/emails/class-wc-email-customer-refunded-order.php (1)
355-357: LGTM!The preheader field addition follows the established pattern and is properly gated behind the
block_email_editor_enabledflag.plugins/woocommerce/includes/emails/class-wc-email-customer-cancelled-order.php (1)
224-226: LGTM!The implementation is consistent with the preheader field additions in the other email classes.
plugins/woocommerce/includes/emails/class-wc-email-customer-pos-refunded-order.php (1)
374-376: LGTM!The preheader field is correctly added to the POS refund email, maintaining consistency with the other email classes.
plugins/woocommerce/includes/emails/class-wc-email-new-order.php (1)
263-265: LGTM!The preheader field addition is properly implemented following the consistent pattern across all email classes.
plugins/woocommerce/includes/emails/class-wc-email-customer-invoice.php (1)
258-260: LGTM!The preheader field is correctly added to the customer invoice email, completing the consistent implementation across all email classes in this PR.
plugins/woocommerce/includes/emails/class-wc-email-failed-order.php (1)
235-237: Preheader field gating looks correctFeature flag check lines up with other email classes, and reusing
get_preheader_field()keeps the settings surface consistent with the shared schema.plugins/woocommerce/includes/rest-api/Server.php (1)
27-246: New controller registration wired correctlyImport alias and
get_v4_controllers()entry follow existing patterns, so the new/wc/v4/settings/emailsroutes will be discoverable once the feature flag is on.plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Controller.php (1)
55-293: Endpoint implementation aligns with existing V4 patternsRoute registration, permission checks, and update flow mirror the other settings controllers, and delegating schema work keeps data shaping consistent.
...s/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php
Outdated
Show resolved
Hide resolved
...s/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php
Show resolved
Hide resolved
...ce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php
Show resolved
Hide resolved
There was a problem hiding this 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/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php (1)
83-86: Nice fix: feature flag is now restored in tearDown().Capturing the previous value before flipping the option prevents cross-test leakage. Good cleanup.
🧹 Nitpick comments (5)
plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php (2)
664-686: Assert link type to prevent regressions.Add a strict type check so the API never emits a boolean for link again.
// Verify types. $this->assertIsString( $item['id'] ); $this->assertIsString( $item['title'] ); + $this->assertIsString( $item['link'] ); $this->assertTrue( is_int( $item['post_id'] ) || is_null( $item['post_id'] ), 'post_id should be int or null' );
598-601: Make preheader expectation explicit.Block editor is enabled in setUp(); preheader should exist. Remove the conditional to catch regressions.
- if ( isset( $data['values']['preheader'] ) ) { - $this->assertEquals( 'Check your order [woocommerce/order-number]', $data['values']['preheader'] ); - } + $this->assertArrayHasKey( 'preheader', $data['values'] ); + $this->assertEquals( 'Check your order [woocommerce/order-number]', $data['values']['preheader'] );plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php (3)
219-252: Silence PHPMD: mark the request parameter as intentionally unused.Rename the parameter to $_request to satisfy “UnusedFormalParameter”.
- public function get_item_response( $email, WP_REST_Request $request, array $include_fields = array() ): array { + public function get_item_response( $email, WP_REST_Request $_request, array $include_fields = array() ): array {
345-365: Guard against preg_replace returning null.preg_replace may return null on PCRE errors. Fall back to the original value.
- $unwrapped_value = preg_replace( '/<!--(\[(?:' . $prefixes_pattern . ')\/[^\]]+\])-->/i', '$1', $value ); - return $unwrapped_value; + $unwrapped_value = preg_replace( '/<!--(\[(?:' . $prefixes_pattern . ')\/[^\]]+\])-->/i', '$1', $value ); + return is_string( $unwrapped_value ) ? $unwrapped_value : $value;
390-392: Same null-guard for wrapping.Apply the same defensive check here.
- return preg_replace( '/(?<!<!--)(\[(?:' . $prefixes_pattern . ')\/[^\]]+\])(?!-->)/i', '<!--$1-->', $value ); + $wrapped = preg_replace( '/(?<!<!--)(\[(?:' . $prefixes_pattern . ')\/[^\]]+\])(?!-->)/i', '<!--$1-->', $value ); + return is_string( $wrapped ) ? $wrapped : $value;
📜 Review details
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php(1 hunks)plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{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/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.phpplugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.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/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php
**/*.{php,js,jsx,tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/avoid-regex.mdc)
**/*.{php,js,jsx,tsx,ts}: Avoid using regular expressions unless absolutely necessary to favor readability and maintainability
Only consider regex when no built-in language alternative (string/array APIs) fits the need
Only use regex when performance is critical and faster than alternatives, with measurements to justify
Use regex for complex pattern matching only if the pattern is well-documented and thoroughly tested
Allow regex when maintaining legacy code where an existing, correct pattern is being modified
If regex is necessary, document the pattern extensively to explain what it matches
If regex is necessary, add comprehensive tests covering edge cases and potential security issues
Use named capture groups in regex to improve readability when supported
Validate input before applying regex to ensure it is safe
Assess and mitigate security risks when using regex, including ReDoS and injection vulnerabilities
Avoid regex patterns that can cause catastrophic backtracking (ReDoS)
Do not construct regex from untrusted input to prevent injection attacks
Ensure regex patterns do not overmatch and unintentionally capture unexpected inputs
Files:
plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.phpplugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.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.
When making any changes to code that deletes or modifies orders/products/customer data, make sure that there are
sufficient checks in place to prevent accidental data loss. As an example, if deleting a draft order, check that
the order status is indeeddraftorcheckout-draft. Also think about whether race conditions could occur and
delete orders that don't belong to the current customer. When in doubt, ask for clarification in the PR comments.
Files:
plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.phpplugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php
🧠 Learnings (18)
📚 Learning: 2025-09-03T11:50:02.208Z
Learnt from: tpaksu
Repo: woocommerce/woocommerce PR: 60735
File: plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version4/Fulfillments/class-wc-rest-fulfillments-v4-controller-tests.php:10-10
Timestamp: 2025-09-03T11:50:02.208Z
Learning: For REST API controller tests in plugins/woocommerce/tests/**/*.php, test classes should extend WC_REST_Unit_Test_Case instead of WC_Unit_Test_Case because REST routes need to be registered before tests run.
Applied to files:
plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php
📚 Learning: 2025-08-18T06:11:48.768Z
Learnt from: CR
Repo: woocommerce/woocommerce PR: 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/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php
📚 Learning: 2025-08-12T14:22:05.865Z
Learnt from: NeosinneR
Repo: woocommerce/woocommerce PR: 60325
File: plugins/woocommerce/tests/php/includes/settings/class-wc-settings-accounts-test.php:0-0
Timestamp: 2025-08-12T14:22:05.865Z
Learning: In WooCommerce settings tests, the woocommerce_enable_delayed_account_creation setting is conditionally present based on wp_is_block_theme() being true OR (wp_is_block_theme() being false AND CartCheckoutUtils::is_checkout_block_default() being true). In test environments with block themes, checking only wp_is_block_theme() is sufficient to determine if the setting should be expected in the settings array.
Applied to files:
plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php
📚 Learning: 2025-06-16T09:20:22.981Z
Learnt from: gigitux
Repo: woocommerce/woocommerce PR: 58846
File: plugins/woocommerce/client/blocks/tests/e2e/tests/all-products/all-products.block_theme.spec.ts:41-52
Timestamp: 2025-06-16T09:20:22.981Z
Learning: In WooCommerce E2E tests, the database is reset to the initial state for each test, so there's no need to manually restore global template changes (like clearing the header template) as the test infrastructure handles cleanup automatically.
Applied to files:
plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php
📚 Learning: 2025-06-25T15:39:25.166Z
Learnt from: vladolaru
Repo: woocommerce/woocommerce PR: 59160
File: plugins/woocommerce/tests/php/src/Internal/Admin/Settings/PaymentsProviders/WooPayments/WooPaymentsServiceTest.php:360-373
Timestamp: 2025-06-25T15:39:25.166Z
Learning: Test mocks should accurately simulate the behavior of the functions they replace, including return value semantics. For WordPress functions like `update_option`, the mock should properly return `false` when the value hasn't changed and `true` when it has, to avoid masking logic errors in tests.
Applied to files:
plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php
📚 Learning: 2025-08-14T08:20:36.357Z
Learnt from: Aljullu
Repo: woocommerce/woocommerce PR: 60191
File: plugins/woocommerce/client/blocks/tests/e2e/tests/single-product-template/single-product-template-compatibility-layer.spec.ts:4-4
Timestamp: 2025-08-14T08:20:36.357Z
Learning: In WooCommerce e2e tests, some test files intentionally use hard-coded "woocommerce/woocommerce//" template IDs instead of BLOCK_THEME_SLUG to test backwards compatibility with the legacy plugin-scoped template ID format. These should not be updated to use the dynamic slug constant as they serve a specific testing purpose.
Applied to files:
plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php
📚 Learning: 2025-10-24T13:25:49.900Z
Learnt from: hannahtinkler
Repo: woocommerce/woocommerce PR: 61384
File: plugins/woocommerce/tests/php/src/Internal/PushNotifications/Entities/PushTokenTest.php:208-216
Timestamp: 2025-10-24T13:25:49.900Z
Learning: In plugins/woocommerce/tests/**/*.php files, omit setUp() and tearDown() methods when they are not needed, as the project's linting configuration makes it easier to omit these methods than to add them with phpcs:ignore comments.
Applied to files:
plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php
📚 Learning: 2025-08-14T08:22:34.886Z
Learnt from: Aljullu
Repo: woocommerce/woocommerce PR: 60191
File: plugins/woocommerce/client/blocks/tests/e2e/tests/product-filters/rating-filter-editor.block_theme.spec.ts:36-36
Timestamp: 2025-08-14T08:22:34.886Z
Learning: In WooCommerce e2e tests, some test files intentionally use hard-coded "woocommerce/woocommerce//" template slugs (not just template IDs) instead of BLOCK_THEME_SLUG to test backwards compatibility with the legacy plugin-scoped template slug format. These should not be updated to use the dynamic slug constant as they serve a specific backwards compatibility testing purpose.
Applied to files:
plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php
📚 Learning: 2025-08-21T07:39:42.952Z
Learnt from: NeosinneR
Repo: woocommerce/woocommerce PR: 60520
File: plugins/woocommerce/src/Internal/Admin/EmailPreview/EmailPreview.php:257-259
Timestamp: 2025-08-21T07:39:42.952Z
Learning: In WooCommerce EmailPreview::ensure_links_open_in_new_tab(), the XML declaration removal regex should not be anchored to the beginning since DOCTYPE appears before the XML declaration in the HTML output.
Applied to files:
plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php
📚 Learning: 2025-06-23T05:47:52.696Z
Learnt from: samueljseay
Repo: woocommerce/woocommerce PR: 59051
File: plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/mini-cart-footer-block/index.tsx:66-70
Timestamp: 2025-06-23T05:47:52.696Z
Learning: For WooCommerce mini-cart blocks in plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/, the standardized conditional pattern for experimental features should be `if ( isExperimentalMiniCartEnabled() ) { blockSettings.save = () => <InnerBlocks.Content />; }` - defaulting to the traditional Save component and only overriding when the experimental feature is enabled.
Applied to files:
plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php
📚 Learning: 2025-07-29T08:05:14.107Z
Learnt from: lysyjan
Repo: woocommerce/woocommerce PR: 60072
File: packages/php/email-editor/src/Engine/PersonalizationTags/class-personalization-tags-registry.php:110-118
Timestamp: 2025-07-29T08:05:14.107Z
Learning: In WooCommerce email editor personalization tags registry (packages/php/email-editor/src/Engine/PersonalizationTags/class-personalization-tags-registry.php), the get_by_post_type method is designed to return tags with empty post_types arrays regardless of the input post_type parameter (even if empty/whitespace). This is the intended behavior as tags with empty post_types are considered universal tags that apply to all post types.
Applied to files:
plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.phpplugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php
📚 Learning: 2025-08-21T07:39:42.952Z
Learnt from: NeosinneR
Repo: woocommerce/woocommerce PR: 60520
File: plugins/woocommerce/src/Internal/Admin/EmailPreview/EmailPreview.php:257-259
Timestamp: 2025-08-21T07:39:42.952Z
Learning: In WooCommerce email preview functionality (EmailPreview.php), rel attributes on links should be overwritten rather than preserved for safety reasons, and anchor links (#) can be treated the same as external links since they're not expected in email previews.
Applied to files:
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php
📚 Learning: 2025-06-26T12:13:32.062Z
Learnt from: triple0t
Repo: woocommerce/woocommerce PR: 59186
File: packages/js/email-editor/src/store/initial-state.ts:9-10
Timestamp: 2025-06-26T12:13:32.062Z
Learning: In WooCommerce email editor store initialization (packages/js/email-editor/src/store/initial-state.ts), the current_post_id and current_post_type from window.WooCommerceEmailEditor are required parameters that should cause explicit errors if missing, rather than using fallback values or optional chaining. The design preference is to fail fast when critical initialization data is unavailable.
Applied to files:
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php
📚 Learning: 2025-07-30T20:52:28.759Z
Learnt from: xristos3490
Repo: woocommerce/woocommerce PR: 59947
File: plugins/woocommerce/src/Internal/DataStores/StockNotifications/StockNotificationsDataStore.php:89-106
Timestamp: 2025-07-30T20:52:28.759Z
Learning: In WooCommerce database schema design, email field lengths should match WordPress Core's wp_users table (100 characters) for consistency, rather than following RFC 5321's maximum of 320 characters.
Applied to files:
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php
📚 Learning: 2025-10-03T09:27:22.888Z
Learnt from: dmallory42
Repo: woocommerce/woocommerce PR: 61244
File: plugins/woocommerce/src/RestApi/Routes/V4/PaymentGateways/Controller.php:236-239
Timestamp: 2025-10-03T09:27:22.888Z
Learning: In the WooCommerce REST API V4 Payment Gateways controller (`plugins/woocommerce/src/RestApi/Routes/V4/PaymentGateways/Controller.php`), the `title` and `description` fields are intentionally validated using `validate_setting_text_field` even when their form field definitions specify different field types. This is by design and should not be flagged as an inconsistency.
Applied to files:
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php
📚 Learning: 2025-08-27T14:31:54.181Z
Learnt from: allilevine
Repo: woocommerce/woocommerce PR: 60514
File: packages/php/email-editor/src/Integrations/Core/Renderer/Blocks/class-table.php:478-515
Timestamp: 2025-08-27T14:31:54.181Z
Learning: wp_kses can be overly restrictive in email editor contexts and may strip out all caption content instead of sanitizing it. WP_HTML_Tag_Processor with custom security validation is preferred for HTML sanitization in WooCommerce email editor blocks.
Applied to files:
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php
📚 Learning: 2025-10-23T01:44:03.397Z
Learnt from: peterwilsoncc
Repo: woocommerce/woocommerce PR: 60447
File: plugins/woocommerce/templates/emails/email-order-details.php:96-131
Timestamp: 2025-10-23T01:44:03.397Z
Learning: In WooCommerce email templates (plugins/woocommerce/templates/emails/), when displaying order details, the order items table and order totals should be separate tables rather than combined with <tfoot>. This follows accessibility guidance: the totals are semantically different information from the line items and should not be forced into a single table structure just for visual positioning. The split improves accessibility for assistive technology users.
Applied to files:
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php
📚 Learning: 2025-08-08T13:47:37.272Z
Learnt from: lysyjan
Repo: woocommerce/woocommerce PR: 60165
File: plugins/woocommerce/src/Internal/EmailEditor/PageRenderer.php:100-104
Timestamp: 2025-08-08T13:47:37.272Z
Learning: In WooCommerce email editor PHP package (packages/php/email-editor), the localization data passed through the `woocommerce_email_editor_script_localization_data` filter always includes the `editor_settings` key as an array (prepared by `Assets_Manager`). This guarantees nested writes like `['editor_settings']['isFullScreenForced']` are safe in PageRenderer::update_localized_data().
Applied to files:
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php
🧬 Code graph analysis (2)
plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Settings/Emails/EmailsSettingsControllerTest.php (5)
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php (2)
EmailsSettingsSchema(27-627)init(61-63)plugins/woocommerce/src/Internal/EmailEditor/WCTransactionalEmails/WCTransactionalEmailPostsGenerator.php (1)
WCTransactionalEmailPostsGenerator(21-273)packages/php/email-editor/src/class-email-editor-container.php (1)
Email_Editor_Container(45-304)packages/php/email-editor/src/Engine/PersonalizationTags/class-personalization-tags-registry.php (1)
Personalization_Tags_Registry(17-140)packages/php/email-editor/src/Engine/PersonalizationTags/class-personalization-tag.php (1)
Personalization_Tag(16-203)
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php (5)
packages/php/email-editor/src/class-email-editor-container.php (1)
Email_Editor_Container(45-304)plugins/woocommerce/src/Internal/RestApi/Routes/V4/AbstractSchema.php (1)
AbstractSchema(26-106)packages/php/email-editor/src/Engine/PersonalizationTags/class-personalization-tags-registry.php (1)
Personalization_Tags_Registry(17-140)plugins/woocommerce/includes/emails/class-wc-email.php (6)
get_email_group_title(469-482)is_customer_email(828-830)is_manual(819-821)get_recipient(605-619)get_preheader(565-580)get_additional_content(522-533)plugins/woocommerce/includes/wc-formatting-functions.php (1)
wc_bool_to_string(37-42)
🪛 PHPMD (2.15.0)
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php
219-219: Avoid unused parameters such as '$request'. (undefined)
(UnusedFormalParameter)
⏰ 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). (33)
- GitHub Check: Blocks e2e tests 9/10 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Blocks e2e tests 1/10 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Core e2e tests - Legacy MiniCart - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Blocks e2e tests 7/10 - @woocommerce/plugin-woocommerce [e2e]
- 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 4/10 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Blocks e2e tests 2/10 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Blocks e2e tests 5/10 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: PHP: 8.4 WP: latest (HPOS:off) [WP latest] 2/2 - @woocommerce/plugin-woocommerce [unit:php]
- GitHub Check: Core e2e tests 6/6 - @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 - Legacy MiniCart 1/3 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: PHP: 8.4 WP: latest (HPOS:off) [WP latest] 1/2 - @woocommerce/plugin-woocommerce [unit:php]
- GitHub Check: Blocks e2e tests 10/10 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Metrics - @woocommerce/plugin-woocommerce [performance]
- GitHub Check: Core e2e tests 1/6 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Core e2e tests 5/6 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: Core e2e tests 4/6 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: PHP: 7.4 WP: pre-release [WP 6.9-beta3] 2/2 - @woocommerce/plugin-woocommerce [unit:php] (optional)
- GitHub Check: PHP: 7.4 WP: latest - 1 [WP 6.7.4] 2/2 - @woocommerce/plugin-woocommerce [unit:php]
- GitHub Check: PHP: 8.4 WP: latest [WP latest] 2/2 - @woocommerce/plugin-woocommerce [unit:php]
- GitHub Check: PHP: 8.4 WP: latest - Legacy MiniCart [WP latest] 1/2 - @woocommerce/plugin-woocommerce [unit:php]
- GitHub Check: PHP: 7.4 WP: pre-release [WP 6.9-beta3] 1/2 - @woocommerce/plugin-woocommerce [unit:php] (optional)
- GitHub Check: Core e2e tests 2/6 - @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 3/6 - @woocommerce/plugin-woocommerce [e2e]
- GitHub Check: PHP: 7.4 WP: latest - 1 [WP 6.7.4] 1/2 - @woocommerce/plugin-woocommerce [unit:php]
- GitHub Check: PHP: 8.4 WP: latest - Legacy MiniCart [WP latest] 2/2 - @woocommerce/plugin-woocommerce [unit:php]
- GitHub Check: Lint - @woocommerce/plugin-woocommerce
- GitHub Check: review-with-tracking
- GitHub Check: build
🔇 Additional comments (1)
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Schema/EmailsSettingsSchema.php (1)
226-231: Good hardening: normalize link to an empty string.Prevents boolean leaks from get_permalink(false). LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look good and works as expected. LGTM!
Nit: Could you please update the PR title (or the commit message) before mergin? Just noticed it's already updated.
plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/Emails/Controller.php
Show resolved
Hide resolved
|
Hi @costasovo! Your PR contains REST API changes. Please consider updating the REST API documentation if your changes affect the public API. Changed API files: |
Changes proposed in this Pull Request:
This PR adds the
settings/emailsroute to the experimental V4 API.The endpoint was moved from the temporary endpoint and updated to align with other settings APIs (e.g. general settings). The main changes are:
valuesis_manualto be able to mark emails that are sent only manuallyThere are a few things that need to be addressed as follow-up:
Closes WOOPRD-926.
How to test the changes in this Pull Request:
The endpoint is covered by unit tests. It can also be tested with an app that uses it.