|
10 | 10 | namespace PartnerProgram\Admin; |
11 | 11 |
|
12 | 12 | use PartnerProgram\Domain\TierResolver; |
| 13 | +use PartnerProgram\Emails\EventRegistry; |
13 | 14 | use PartnerProgram\Support\Capabilities; |
14 | 15 | use PartnerProgram\Support\SettingsRepo; |
15 | 16 |
|
@@ -42,6 +43,7 @@ public static function render_page(): void { |
42 | 43 | 'application' => __( 'Application Form', 'partner-program' ), |
43 | 44 | 'compliance' => __( 'Compliance', 'partner-program' ), |
44 | 45 | 'exclusions' => __( 'Exclusions', 'partner-program' ), |
| 46 | + 'emails' => __( 'Emails', 'partner-program' ), |
45 | 47 | 'logs' => __( 'Logs', 'partner-program' ), |
46 | 48 | 'iotools' => __( 'Import / Export', 'partner-program' ), |
47 | 49 | ]; |
@@ -95,6 +97,7 @@ public static function render_page(): void { |
95 | 97 | case 'application': self::tab_application( $settings ); break; |
96 | 98 | case 'compliance': self::tab_compliance( $settings ); break; |
97 | 99 | case 'exclusions': self::tab_exclusions( $settings ); break; |
| 100 | + case 'emails': self::tab_emails( $settings ); break; |
98 | 101 | case 'logs': self::tab_logs( $settings ); break; |
99 | 102 | } |
100 | 103 |
|
@@ -242,6 +245,96 @@ private static function tab_tracking( SettingsRepo $s ): void { |
242 | 245 | echo '</table>'; |
243 | 246 | } |
244 | 247 |
|
| 248 | + private static function tab_emails( SettingsRepo $s ): void { |
| 249 | + echo '<p class="description">' . esc_html__( 'Customize transactional emails sent by the plugin. Leave subject or body blank to use the built-in default. Tokens like {program_name} are replaced at send time — see each event\'s help text for available tokens.', 'partner-program' ) . '</p>'; |
| 250 | + |
| 251 | + echo '<h2>' . esc_html__( 'Sender', 'partner-program' ) . '</h2>'; |
| 252 | + echo '<table class="form-table">'; |
| 253 | + self::field_text( |
| 254 | + 'emails_from_name', |
| 255 | + __( 'From name', 'partner-program' ), |
| 256 | + (string) $s->get( 'emails.from_name', '' ), |
| 257 | + __( 'Defaults to the program name.', 'partner-program' ) |
| 258 | + ); |
| 259 | + self::field_text( |
| 260 | + 'emails_from_email', |
| 261 | + __( 'From email', 'partner-program' ), |
| 262 | + (string) $s->get( 'emails.from_email', '' ), |
| 263 | + __( 'Defaults to the support email.', 'partner-program' ), |
| 264 | + 'email' |
| 265 | + ); |
| 266 | + printf( |
| 267 | + '<tr><th scope="row"><label for="emails_footer_text">%s</label></th><td><textarea id="emails_footer_text" name="emails_footer_text" rows="2" cols="60">%s</textarea><p class="description">%s</p></td></tr>', |
| 268 | + esc_html__( 'Footer text', 'partner-program' ), |
| 269 | + esc_textarea( (string) $s->get( 'emails.footer_text', '' ) ), |
| 270 | + esc_html__( 'Shown at the bottom of every email. Leave blank for the default.', 'partner-program' ) |
| 271 | + ); |
| 272 | + echo '</table>'; |
| 273 | + |
| 274 | + echo '<h2>' . esc_html__( 'Events', 'partner-program' ) . '</h2>'; |
| 275 | + |
| 276 | + foreach ( EventRegistry::all() as $key => $event ) { |
| 277 | + $config = (array) $s->get( 'emails.events.' . $key, [] ); |
| 278 | + $enabled = array_key_exists( 'enabled', $config ) ? (bool) $config['enabled'] : (bool) $event['default_enabled']; |
| 279 | + $subject = (string) ( $config['subject'] ?? '' ); |
| 280 | + $body = (string) ( $config['body'] ?? '' ); |
| 281 | + |
| 282 | + $tokens_html = ''; |
| 283 | + foreach ( $event['tokens'] as $token => $token_desc ) { |
| 284 | + $tokens_html .= sprintf( |
| 285 | + '<li><code>%s</code> — %s</li>', |
| 286 | + esc_html( $token ), |
| 287 | + esc_html( $token_desc ) |
| 288 | + ); |
| 289 | + } |
| 290 | + |
| 291 | + $audience_label = 'admin' === $event['audience'] |
| 292 | + ? __( 'Sent to admin', 'partner-program' ) |
| 293 | + : __( 'Sent to partner', 'partner-program' ); |
| 294 | + |
| 295 | + ?> |
| 296 | + <details class="pp-email-event" <?php echo $enabled ? 'open' : ''; ?> style="border:1px solid #c3c4c7;background:#fff;padding:8px 16px;margin:0 0 12px;"> |
| 297 | + <summary style="cursor:pointer;font-weight:600;padding:6px 0;"> |
| 298 | + <?php echo esc_html( $event['label'] ); ?> |
| 299 | + <span style="font-weight:400;color:#646970;margin-left:8px;">— <?php echo esc_html( $audience_label ); ?></span> |
| 300 | + </summary> |
| 301 | + <p class="description" style="margin-top:4px;"><?php echo esc_html( $event['description'] ); ?></p> |
| 302 | + <table class="form-table"> |
| 303 | + <tr> |
| 304 | + <th scope="row"><?php esc_html_e( 'Enabled', 'partner-program' ); ?></th> |
| 305 | + <td> |
| 306 | + <label> |
| 307 | + <input type="checkbox" name="emails_events[<?php echo esc_attr( $key ); ?>][enabled]" value="1" <?php checked( $enabled ); ?> /> |
| 308 | + <?php esc_html_e( 'Send this email', 'partner-program' ); ?> |
| 309 | + </label> |
| 310 | + </td> |
| 311 | + </tr> |
| 312 | + <tr> |
| 313 | + <th scope="row"><label for="emails_subject_<?php echo esc_attr( $key ); ?>"><?php esc_html_e( 'Subject', 'partner-program' ); ?></label></th> |
| 314 | + <td> |
| 315 | + <input type="text" id="emails_subject_<?php echo esc_attr( $key ); ?>" name="emails_events[<?php echo esc_attr( $key ); ?>][subject]" value="<?php echo esc_attr( $subject ); ?>" class="large-text" placeholder="<?php echo esc_attr( $event['subject'] ); ?>" /> |
| 316 | + <p class="description"><?php esc_html_e( 'Leave blank to use the default shown as placeholder.', 'partner-program' ); ?></p> |
| 317 | + </td> |
| 318 | + </tr> |
| 319 | + <tr> |
| 320 | + <th scope="row"><label for="emails_body_<?php echo esc_attr( $key ); ?>"><?php esc_html_e( 'Body', 'partner-program' ); ?></label></th> |
| 321 | + <td> |
| 322 | + <textarea id="emails_body_<?php echo esc_attr( $key ); ?>" name="emails_events[<?php echo esc_attr( $key ); ?>][body]" rows="8" class="large-text code" placeholder="<?php echo esc_attr( $event['body'] ); ?>"><?php echo esc_textarea( $body ); ?></textarea> |
| 323 | + <p class="description"><?php esc_html_e( 'Plain text or basic HTML. Leave blank to use the default.', 'partner-program' ); ?></p> |
| 324 | + </td> |
| 325 | + </tr> |
| 326 | + <tr> |
| 327 | + <th scope="row"><?php esc_html_e( 'Available tokens', 'partner-program' ); ?></th> |
| 328 | + <td> |
| 329 | + <ul style="margin:0;padding-left:18px;font-size:13px;line-height:1.6;"><?php echo $tokens_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></ul> |
| 330 | + </td> |
| 331 | + </tr> |
| 332 | + </table> |
| 333 | + </details> |
| 334 | + <?php |
| 335 | + } |
| 336 | + } |
| 337 | + |
245 | 338 | private static function tab_logs( SettingsRepo $s ): void { |
246 | 339 | echo '<table class="form-table">'; |
247 | 340 | self::field_text( |
@@ -762,6 +855,27 @@ public function handle_save(): void { |
762 | 855 | ] ); |
763 | 856 | break; |
764 | 857 |
|
| 858 | + case 'emails': |
| 859 | + $raw_events = isset( $_POST['emails_events'] ) && is_array( $_POST['emails_events'] ) |
| 860 | + ? wp_unslash( (array) $_POST['emails_events'] ) |
| 861 | + : []; |
| 862 | + $clean_events = []; |
| 863 | + foreach ( EventRegistry::all() as $event_key => $event_def ) { |
| 864 | + $row = is_array( $raw_events[ $event_key ] ?? null ) ? $raw_events[ $event_key ] : []; |
| 865 | + $clean_events[ $event_key ] = [ |
| 866 | + 'enabled' => ! empty( $row['enabled'] ), |
| 867 | + 'subject' => sanitize_text_field( (string) ( $row['subject'] ?? '' ) ), |
| 868 | + 'body' => wp_kses_post( (string) ( $row['body'] ?? '' ) ), |
| 869 | + ]; |
| 870 | + } |
| 871 | + $repo->save_section( 'emails', [ |
| 872 | + 'from_name' => sanitize_text_field( wp_unslash( (string) ( $_POST['emails_from_name'] ?? '' ) ) ), |
| 873 | + 'from_email' => sanitize_email( wp_unslash( (string) ( $_POST['emails_from_email'] ?? '' ) ) ), |
| 874 | + 'footer_text' => sanitize_textarea_field( wp_unslash( (string) ( $_POST['emails_footer_text'] ?? '' ) ) ), |
| 875 | + 'events' => $clean_events, |
| 876 | + ] ); |
| 877 | + break; |
| 878 | + |
765 | 879 | case 'logs': |
766 | 880 | $repo->save_section( 'logs', [ |
767 | 881 | 'retention_days' => max( 0, (int) ( $_POST['logs_retention_days'] ?? 90 ) ), |
|
0 commit comments