Skip to content

fix(emails): clarify free checkout notifications#1673

Merged
superdav42 merged 2 commits into
mainfrom
feature/auto-20260724-155950
Jul 25, 2026
Merged

fix(emails): clarify free checkout notifications#1673
superdav42 merged 2 commits into
mainfrom
feature/auto-20260724-155950

Conversation

@superdav42

@superdav42 superdav42 commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Classify checkout notifications as paid, free membership, or trial outcomes.
  • Use outcome-specific customer and admin subjects, copy, details, and receipt handling.
  • Avoid sending the customer checkout email as an admin copy; keep the dedicated admin notification.
  • Add conditional email-template blocks and focused coverage.

Verification

  • vendor/bin/phpcs inc/helpers/class-sender.php inc/managers/class-payment-manager.php inc/managers/class-email-manager.php views/emails/customer/payment-received.php views/emails/admin/payment-received.php tests/WP_Ultimo/Helpers/Sender_Test.php tests/WP_Ultimo/Managers/Email_Manager_Test.php
  • vendor/bin/phpstan analyse inc/helpers/class-sender.php inc/managers/class-email-manager.php inc/managers/class-payment-manager.php
  • vendor/bin/phpunit --filter 'Sender_Test|Email_Manager_Test|Payment_Manager_Test'

aidevops.sh v3.32.180 plugin for OpenCode v1.18.4

Summary by CodeRabbit

  • New Features
    • Payment-received email templates now render different sections based on whether the payment is paid, a free signup, or a trial.
    • Admin and customer payment-received subjects and introductions are now driven by configurable placeholders.
  • Bug Fixes
    • Invoice PDFs are now attached only when the payment is eligible (includes required state/settings conditions).
    • Customer payment-received emails no longer include an unnecessary administrative copy, and the default subject metadata was updated.
  • Tests
    • Added coverage for conditional shortcode block rendering and strengthened existing email manager assertions.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: afebfcf3-390e-43d4-a5fb-a2fc1dfed6e0

📥 Commits

Reviewing files that changed from the base of the PR and between 196ebc5 and 3f2af99.

📒 Files selected for processing (1)
  • inc/managers/class-payment-manager.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • inc/managers/class-payment-manager.php

📝 Walkthrough

Walkthrough

Payment success events now include derived payment states and email-specific subjects and intros. Sender supports conditional template blocks, and admin/customer payment emails render separate paid, free-signup, and trial content.

Changes

Payment Email Flow

Layer / File(s) Summary
Conditional shortcode rendering
inc/helpers/class-sender.php, tests/WP_Ultimo/Helpers/Sender_Test.php
Sender::process_shortcodes() now keeps or removes {{#KEY}}...{{/KEY}} blocks according to payload truthiness, with coverage for both outcomes. Existing mail callback tests also explicitly unset unused parameters.
Payment state and email registration
inc/managers/class-payment-manager.php, inc/managers/class-email-manager.php, tests/WP_Ultimo/Managers/Email_Manager_Test.php
Payment success handling derives paid, free-signup, and trial states and assigns email subjects/intros. Default email metadata uses subject placeholders, disables the customer admin copy, and restricts invoice attachments for unpaid payments.
State-specific payment email templates
views/emails/admin/payment-received.php, views/emails/customer/payment-received.php
Admin and customer templates conditionally render paid, free-signup, and trial details with updated payment, membership, receipt, and customer fields.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Payment_Manager
  participant wu_do_event
  participant Email_Manager
  participant Sender
  participant Payment_Templates
  Payment_Manager->>Payment_Manager: derive payment and membership state
  Payment_Manager->>wu_do_event: emit payment_received payload
  wu_do_event->>Email_Manager: deliver payload
  Email_Manager->>Sender: process subject and template shortcodes
  Sender->>Payment_Templates: render state-specific sections
  Payment_Templates-->>Email_Manager: rendered payment email
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the email-notification work, though it narrows the scope to free checkout while the PR also covers paid and trial cases.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/auto-20260724-155950

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

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

@github-actions

Copy link
Copy Markdown

🔨 Build Complete - Ready for Testing!

📦 Download Build Artifact (Recommended)

Download the zip build, upload to WordPress and test:

🌐 Test in WordPress Playground (Very Experimental)

Click the link below to instantly test this PR in your browser - no installation needed!
Playground support for multisite is very limitied, hopefully it will get better in the future.

🚀 Launch in Playground

Login credentials: admin / password

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (2)
inc/helpers/class-sender.php (1)

239-257: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Conditional blocks aren't stripped when payload is empty.

The early return at Line 241-243 runs before the new conditional-block preprocessing, so calling process_shortcodes() with an empty payload leaves raw {{#key}}...{{/key}} markers (and their inner content) in the output instead of stripping them.

🐛 Proposed fix
 	public static function process_shortcodes($content, $payload = []) {
 
-		if (empty($payload)) {
-			return $content;
-		}
-
 		/*
 		 * Allow templates to include a block only when the matching payload
 		 * value is truthy. This keeps a single transactional email template
 		 * useful for related outcomes, such as paid checkouts and free trials.
 		 */
 		$content = preg_replace_callback(
 			'/{{#([a-zA-Z0-9_]+)}}(.*?){{\/\1}}/s',
 			function ($matches) use ($payload) {
 				return ! empty($payload[ $matches[1] ]) ? $matches[2] : '';
 			},
 			$content
 		);
 
+		if (empty($payload)) {
+			return $content;
+		}
+
 		$match = [];
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@inc/helpers/class-sender.php` around lines 239 - 257, Update
process_shortcodes so conditional-block preprocessing runs before any
empty-payload return. Ensure empty payloads strip every {{`#key`}}...{{/key}}
block and its contents, while preserving the existing truthy-payload behavior
that retains matching block content.
inc/managers/class-email-manager.php (1)

164-172: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Compare against the rendered email subject when attaching invoice PDFs.

Sender::send_mail() replaces shortcodes in $args['subject'] before wp_mail(), so PHPMailer receives the interpolated subject. attach_invoice_pdf() compares phpmailer_init’s $mail->Subject against the raw template subject, so these payment emails miss their invoice attachments:

$args['subject'] = 'Site - {{payment_email_admin_subject}}'

runs the replacement, but the registered payload includes payment_email_admin_subject => 'Payment received: ...'. For payment_received_admin/payment_received_customer, register the attachment with the same processed subject:

🐛 Proposed fix
 				if ($invoice_payment) {
 					$file_name = 'invoice-' . $invoice_payment->get_hash() . '.pdf';
 
-					$this->attach_invoice_pdf($invoice_payment, $file_name, $args['subject']);
+					$this->attach_invoice_pdf($invoice_payment, $file_name, Sender::process_shortcodes($args['subject'], $payload));
 				}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@inc/managers/class-email-manager.php` around lines 164 - 172, Update the
payment invoice attachment flow around attach_invoice_pdf() so
payment_received_admin and payment_received_customer register the attachment
using the subject after Sender::send_mail() shortcode replacement, matching
PHPMailer’s rendered mail Subject rather than the raw $args['subject'] template.
Preserve the existing invoice lookup, filename, and paid-status conditions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@inc/managers/class-payment-manager.php`:
- Around line 130-215: Guard all customer_name and payment_product_names reads
in the payment email subject and intro branches within the payment
payload-building method. Reuse the codebase’s defensive wu_get_isset() pattern,
supplying appropriate empty fallbacks when these payload keys are absent, while
preserving the existing paid, trial, and free-membership messaging behavior.

---

Outside diff comments:
In `@inc/helpers/class-sender.php`:
- Around line 239-257: Update process_shortcodes so conditional-block
preprocessing runs before any empty-payload return. Ensure empty payloads strip
every {{`#key`}}...{{/key}} block and its contents, while preserving the existing
truthy-payload behavior that retains matching block content.

In `@inc/managers/class-email-manager.php`:
- Around line 164-172: Update the payment invoice attachment flow around
attach_invoice_pdf() so payment_received_admin and payment_received_customer
register the attachment using the subject after Sender::send_mail() shortcode
replacement, matching PHPMailer’s rendered mail Subject rather than the raw
$args['subject'] template. Preserve the existing invoice lookup, filename, and
paid-status conditions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2defad8f-ce23-4ca8-b821-447c682017af

📥 Commits

Reviewing files that changed from the base of the PR and between 56eab5a and 196ebc5.

📒 Files selected for processing (7)
  • inc/helpers/class-sender.php
  • inc/managers/class-email-manager.php
  • inc/managers/class-payment-manager.php
  • tests/WP_Ultimo/Helpers/Sender_Test.php
  • tests/WP_Ultimo/Managers/Email_Manager_Test.php
  • views/emails/admin/payment-received.php
  • views/emails/customer/payment-received.php

Comment thread inc/managers/class-payment-manager.php Outdated
@github-actions

Copy link
Copy Markdown

🔨 Build Complete - Ready for Testing!

📦 Download Build Artifact (Recommended)

Download the zip build, upload to WordPress and test:

🌐 Test in WordPress Playground (Very Experimental)

Click the link below to instantly test this PR in your browser - no installation needed!
Playground support for multisite is very limitied, hopefully it will get better in the future.

🚀 Launch in Playground

Login credentials: admin / password

@superdav42
superdav42 merged commit 5ab40c6 into main Jul 25, 2026
11 checks passed
@superdav42

Copy link
Copy Markdown
Collaborator Author

Summary

  • Classify checkout notifications as paid, free membership, or trial outcomes.
  • Use outcome-specific customer and admin subjects, copy, details, and receipt handling.
  • Avoid sending the customer checkout email as an admin copy; keep the dedicated admin notification.
  • Add conditional email-template blocks and focused coverage.

Verification

  • vendor/bin/phpcs inc/helpers/class-sender.php inc/managers/class-payment-manager.php inc/managers/class-email-manager.php views/emails/customer/payment-received.php views/emails/admin/payment-received.php tests/WP_Ultimo/Helpers/Sender_Test.php tests/WP_Ultimo/Managers/Email_Manager_Test.php
  • vendor/bin/phpstan analyse inc/helpers/class-sender.php inc/managers/class-email-manager.php inc/managers/class-payment-manager.php
  • vendor/bin/phpunit --filter 'Sender_Test|Email_Manager_Test|Payment_Manager_Test'

aidevops.sh v3.32.180 plugin for OpenCode v1.18.4


Merged via PR #1673 to main.
Merged by deterministic merge pass (pulse-wrapper.sh).

@superdav42 superdav42 added the review-feedback-scanned Merged PR already scanned for quality feedback label Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review-feedback-scanned Merged PR already scanned for quality feedback

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant