feat(emails): sync site styles into WC classic email options + preview thumbnails (NPPD-1537)#4758
Open
kmwilkerson wants to merge 4 commits into
Conversation
65ec487 to
bdd33a8
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR improves WooCommerce email branding consistency in Newspack by (1) syncing Newspack site branding into WooCommerce classic email options (for classic-template/WC Subscriptions emails) and (2) extending the unified Emails UI preview system to support classic WC emails via wc:{email_id} identifiers, enabling preview thumbnails for those emails.
Changes:
- Add a WooCommerce classic-email style sync that writes the site primary color + logo into
woocommerce_email_*options on first-run and on theme/style changes. - Extend the email preview REST endpoint to accept both numeric IDs and
wc:{email_id}identifiers, rendering classic-template previews via WC’s legacy preview renderer when needed. - Update the Emails UI/types/tests to support string preview identifiers and request previews for all surfaced WooCommerce emails.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
includes/plugins/woocommerce/class-woocommerce-email-style-sync.php |
New class to sync site primary color + logo into WC classic email options and keep them updated. |
includes/plugins/woocommerce/class-woocommerce-connection.php |
Includes the new style-sync integration file during WooCommerce connection init. |
includes/wizards/newspack/class-email-preview.php |
Expands preview REST route to accept wc: IDs and adds classic WC preview rendering path. |
includes/wizards/newspack/class-emails-section.php |
Populates preview_id for WC emails (post ID when block template exists, otherwise wc:{email_id}) and exposes template lookup helper publicly. |
src/wizards/newspack/views/settings/emails/email-preview.tsx |
Allows postId to be `number |
src/wizards/newspack/views/settings/emails/emails.tsx |
Renames preview_post_id → preview_id and supports string IDs for previews. |
src/wizards/newspack/views/settings/emails/emails.test.js |
Updates mock WC rows to provide preview_id for preview rendering. |
src/wizards/newspack/views/settings/emails/email-preview.test.js |
Adds tests for string wc: preview IDs and endpoint path construction. |
tests/unit-tests/woocommerce-email-style-sync.php |
New PHPUnit suite for the WC style-sync helpers/guards in CI contexts. |
tests/unit-tests/email-preview.php |
Updates tests for REST param rename (id) and adds coverage for unregistered wc: preview IDs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
facde84 to
98b0e2d
Compare
f9e5b74 to
3410271
Compare
3 tasks
98b0e2d to
05ae747
Compare
3410271 to
643cb6d
Compare
…w thumbnails (NPPD-1537) Sync the site's primary brand color and logo into WooCommerce's classic email template options so WC Subs transactional emails arrive on-brand. Extend the email preview REST endpoint to accept wc:{email_id} string identifiers alongside numeric post IDs, enabling preview thumbnails for classic-template WC emails that lack block-editor template posts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…st suites Remove the global WooCommerce class stub that was causing Emails_Section tests to think WC was available (then fail on WC()). Test private helpers via Reflection instead. Also unhook Emails::maybe_update_email_templates during set_up to prevent set_theme_mod from calling the missing Newspack_Newsletters::update_color_palette. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Tighten the email preview route regex from `[\w:-]+` to `\d+|wc:[\w-]+`
so non-digit identifiers like `123abc` can't slip past `absint()` and
resolve to a different email post than was requested.
- Restore the `update_option_theme_mods_{theme}` action in `tear_down()`
of the style-sync test suite, so the deliberate removal in `set_up()`
doesn't leak into other test classes via shared global hook state.
The test asserted that no WC email options were written when the version option was already current, but in CI `class_exists( 'WooCommerce' )` is false so `maybe_sync_on_first_run()` short-circuits on the WC guard before ever checking the version — the assertion passed for the wrong reason. The version check is one obvious line and adding a testing-only helper to exercise it isn't worth the churn.
05ae747 to
fa0f290
Compare
643cb6d to
43a03aa
Compare
This was referenced May 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this PR does
Two complementary changes that together make the 6 WooCommerce Subscriptions classic-template emails feel native to a Newspack site (NPPD-1537):
1. Site styles sync into WC's classic email options so WC Subs email template doesn't require manual updating.
2. Preview thumbnails for those same emails in the Newspack emails management UI, using the now-branded classic render path.
The 3 WC core emails (Account Created, Refund, New Order) already render with theme.json colors via the block email editor and are unaffected by part 1. They keep their existing block-editor thumbnail path.
Depends on slice 2 (#4732) for the
Email_Previewclass this PR extends, which depends on slice 1 (#4727). Builds on NPPD-1524 (#4756).Code changes
Backend —
includes/plugins/woocommerce/class-woocommerce-email-style-sync.php(new)WooCommerce_Email_Style_Syncclass. Syncswoocommerce_email_base_color(fromnewspack_get_theme_colors()['primary_color']) andwoocommerce_email_header_image(fromwp_get_attachment_url( get_theme_mod('custom_logo') )) into WC's classic email options.WooCommerce_Emails: option-based version flag (newspack_wc_email_style_sync_version) ensures the sync runs once on first admin load; bumpingCURRENT_VERSIONre-triggers it.customize_save_afterandafter_switch_theme(theme-agnostic hooks that survive a theme switch).woocommerce_email_text_color,woocommerce_email_background_color,woocommerce_email_body_background_color— those stay at WC defaults to avoid readability issues.primary_text_colorfromnewspack_get_theme_colors()is contrast-computed against the brand color (not against white), so mapping it to body text would break on sites with dark primaries. Inline code comment documents the decision.EmailStyleSyncmay run on the same hooks whenwoocommerce_email_auto_sync_with_themeis enabled — last-write-wins is fine since both produce brand-aligned values.Backend —
includes/plugins/woocommerce/class-woocommerce-connection.phpinclude_oncefor the new style sync class alongside the other WC integration files (matches existing pattern; no change toclass-newspack.php).Backend —
includes/wizards/newspack/class-email-preview.php(?P<post_id>\d+)to(?P<id>[\w:-]+)to accept both numeric (block-editor post) and string (WC email ID, prefixedwc:) identifiers. Single route, no parallel endpoints.wc:ID against the registry BEFORE any resolution. Numeric IDs continue through the existingget_post()branch.get_wc_classic_preview_html( string $wc_email_id )method resolves the email ID →WC_Emailclass name viaWC()->mailer()->get_emails(), then uses WC's\Automattic\WooCommerce\Internal\Admin\EmailPreview\EmailPreview::set_email_type()+render().class_exists()guard handles the case where WC's class moves (it's in WC'sInternalnamespace — inline comment notes the dependency). Wrapped in try/catch so render failures fall through to the frontend's existing envelope-icon fallback.Backend —
includes/wizards/newspack/class-emails-section.phppreview_post_idis nowwc:{email_id}instead ofnull. Frontend can now request a thumbnail for every WC email surfaced in the UI.get_wc_email_template_post_id()changed fromprivatetopublic staticsoEmail_Previewcan use it to decide which render path to take.Frontend —
src/wizards/newspack/views/settings/emails/email-preview.tsx: widenspostIdprop type tonumber | string. Existing template-literal path construction handles both shapes — no other changes needed.emails.tsx: addspreview_id?: number | string | nullto theEmailIteminterface.Tests
tests/unit-tests/woocommerce-email-style-sync.php, new): 5 tests covering first-run sync of color + logo, skip-when-version-stamped, theme-change re-sync, no-logo fallback to empty string.tests/unit-tests/email-preview.php, extended):wc:identifier with valid registry entry routes toget_wc_classic_preview_html();wc:identifier not in registry returns 404; classic render produces non-empty HTML.email-preview.test.js, extended): stringpostIdconstructs correct API path; component renders correctly with string identifier.Why this PR
The expensive path to fix WC Subs email branding is converting them to WC's block email editor — a multi-month upstream workstream that's not in this project's scope. This is the cheap path: sync the site's brand color and logo into the legacy WC options the classic templates already read, and reuse slice 2's preview infrastructure to render thumbnails via WC's existing
EmailPreviewclass. Combined effect is that WC Subs emails now feel native end-to-end: branded in the management UI AND branded when delivered to readers.Originally scoped to just the style sync. Thumbnail work was folded in once the investigation confirmed the thumbnail render path could reuse most of slice 2's existing code — better to ship the complete WC Subs branding story in one cohesive PR than two consecutive smaller ones.
Manual testing
Tested locally with Newspack, WooCommerce, WooCommerce Subscriptions, and the WC Block Email Editor feature enabled. Verified:
newspack_wc_email_style_sync_versionto simulate first run, loaded any admin page, confirmedwp option get woocommerce_email_base_colormatches site primary color andwp option get woocommerce_email_header_imagematches site logo URLwoocommerce_email_base_colorupdated viacustomize_save_afterafter_switch_themeAll Submissions: